| @@ -1208,6 +1208,9 @@ static double bnd_fmax ( double a, double b ) | |||
| // max glyphs for position testing | |||
| #define BND_MAX_GLYPHS 1024 | |||
| // max rows for position testing | |||
| #define BND_MAX_ROWS 32 | |||
| // text distance from bottom | |||
| #define BND_TEXT_PAD_DOWN 7 | |||
| @@ -2171,6 +2174,23 @@ void bndNodeIconLabel(NVGcontext *ctx, float x, float y, float w, float h, | |||
| } | |||
| } | |||
| static void bndCaretPosition(NVGcontext *ctx, float x, float y, float w, | |||
| float *bounds, float lineHeight, const char *c, NVGtextRow *rows, | |||
| int nrows, int *cr, float *cx, float *cy) { | |||
| static NVGglyphPosition glyphs[BND_MAX_GLYPHS]; | |||
| int r,nglyphs; | |||
| for (r=0; r < nrows && rows[r].end < c; ++r); | |||
| *cr = r; | |||
| *cx = rows[r].minx; | |||
| *cy = bounds[1]+r*lineHeight; | |||
| nglyphs = nvgTextGlyphPositions( | |||
| ctx, x, y, rows[r].start, rows[r].end+1, glyphs, BND_MAX_GLYPHS); | |||
| for (int i=0; i < nglyphs; ++i) { | |||
| *cx=glyphs[i].x; | |||
| if (glyphs[i].str == c) break; | |||
| } | |||
| } | |||
| void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h, | |||
| int iconid, NVGcolor color, float fontsize, const char *label, | |||
| NVGcolor caretcolor, int cbegin, int cend) { | |||
| @@ -2194,70 +2214,45 @@ void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h, | |||
| w -= BND_TEXT_RADIUS+pleft; | |||
| if (cend >= cbegin) { | |||
| #if 1 | |||
| float c0,c1; | |||
| const char *cb;const char *ce; | |||
| static NVGglyphPosition glyphs[BND_MAX_GLYPHS]; | |||
| int nglyphs = nvgTextGlyphPositions( | |||
| ctx, x, y, label, label+cend+1, glyphs, BND_MAX_GLYPHS); | |||
| c0=glyphs[0].x; | |||
| c1=glyphs[nglyphs-1].x; | |||
| cb = label+cbegin; ce = label+cend; | |||
| // TODO: this is slow | |||
| for (int i=0; i < nglyphs; ++i) { | |||
| if (glyphs[i].str == cb) | |||
| c0 = glyphs[i].x; | |||
| if (glyphs[i].str == ce) | |||
| c1 = glyphs[i].x; | |||
| } | |||
| int c0r,c1r; | |||
| float c0x,c0y,c1x,c1y; | |||
| float asc,desc,lh; | |||
| static NVGtextRow rows[BND_MAX_ROWS]; | |||
| int nrows = nvgTextBreakLines( | |||
| ctx, label, label+cend+1, w, rows, BND_MAX_ROWS); | |||
| nvgTextBoxBounds(ctx, x, y, w, label, NULL, bounds); | |||
| nvgTextMetrics(ctx, &asc, &desc, &lh); | |||
| bndCaretPosition(ctx, x, y, w, bounds, lh, label+cbegin, | |||
| rows, nrows, &c0r, &c0x, &c0y); | |||
| bndCaretPosition(ctx, x, y, w, bounds, lh, label+cend, | |||
| rows, nrows, &c1r, &c1x, &c1y); | |||
| nvgTextBounds(ctx,x,y,label,NULL, bounds); | |||
| nvgBeginPath(ctx); | |||
| if (cbegin == cend) { | |||
| nvgFillColor(ctx, nvgRGBf(0.337,0.502,0.761)); | |||
| nvgRect(ctx, c0-1, bounds[1], 2, bounds[3]-bounds[1]); | |||
| nvgRect(ctx, c0x-1, c0y, 2, lh+1); | |||
| } else { | |||
| nvgFillColor(ctx, caretcolor); | |||
| nvgRect(ctx, c0-1, bounds[1], c1-c0+1, bounds[3]-bounds[1]); | |||
| if (c0r == c1r) { | |||
| nvgRect(ctx, c0x-1, c0y, c1x-c0x+1, lh+1); | |||
| } else { | |||
| int blk; | |||
| float by; | |||
| if (c0r < c1r) { | |||
| nvgRect(ctx, c0x-1, c0y, bounds[2]-c0x+1, lh+1); | |||
| nvgRect(ctx, bounds[0], c1y, c1x-bounds[0]+1, lh+1); | |||
| blk=c1r-c0r-1; by=c0y+lh; | |||
| } else { | |||
| nvgRect(ctx, c1x-1, c1y, bounds[2]-c1x+1, lh+1); | |||
| nvgRect(ctx, bounds[0], c0y, c0x-bounds[0]+1, lh+1); | |||
| blk=c0r-c1r-1; by=c1y+lh; | |||
| } | |||
| if (blk) | |||
| nvgRect(ctx, bounds[0], by, bounds[2]-bounds[0], blk*lh+1); | |||
| } | |||
| } | |||
| nvgFill(ctx); | |||
| #else | |||
| float c0,c1; | |||
| const char *cb; | |||
| const char *ce; | |||
| const char *line; | |||
| int numlines; | |||
| cb = label+cbegin; ce = label+cend; | |||
| line = label; | |||
| NVGtextRow rows[2]; | |||
| numlines = nvgTextBreakLines(ctx, line, NULL, w, rows, 2); | |||
| /* | |||
| int nglyphs = nvgTextGlyphPositions( | |||
| ctx, x, y, label, label+cend+1, glyphs, BND_MAX_GLYPHS); | |||
| c0=glyphs[0].x; | |||
| c1=glyphs[nglyphs-1].x; | |||
| // TODO: this is slow | |||
| for (int i=0; i < nglyphs; ++i) { | |||
| if (glyphs[i].str == cb) | |||
| c0 = glyphs[i].x; | |||
| if (glyphs[i].str == ce) | |||
| c1 = glyphs[i].x; | |||
| } | |||
| nvgTextBounds(ctx,x,y,label,NULL, bounds); | |||
| nvgBeginPath(ctx); | |||
| if (cbegin == cend) { | |||
| nvgFillColor(ctx, nvgRGBf(0.337,0.502,0.761)); | |||
| nvgRect(ctx, c0-1, bounds[1], 2, bounds[3]-bounds[1]); | |||
| } else { | |||
| nvgFillColor(ctx, caretcolor); | |||
| nvgRect(ctx, c0-1, bounds[1], c1-c0+1, bounds[3]-bounds[1]); | |||
| } | |||
| nvgFill(ctx); | |||
| */ | |||
| #endif | |||
| } | |||
| nvgBeginPath(ctx); | |||