diff --git a/blendish.h b/blendish.h index 869a9fc..e815bf5 100644 --- a/blendish.h +++ b/blendish.h @@ -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);