Browse Source

Fixed text related calculations for hi-dpi rendering

- calculate all text related stuff using scaling
- removed a couple of compiler warnings
- tweaked caret picking
shared-context
Mikko Mononen 11 years ago
parent
commit
fdb96903c8
3 changed files with 54 additions and 44 deletions
  1. +3
    -8
      example/demo.c
  2. +7
    -6
      example/perf.c
  3. +44
    -30
      src/nanovg.c

+ 3
- 8
example/demo.c View File

@@ -827,11 +827,6 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP); nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgTextMetrics(vg, NULL, NULL, &lineh); nvgTextMetrics(vg, NULL, NULL, &lineh);


/* nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(255,255,0,128));
nvgRect(vg, x, y, width, height);
nvgFill(vg);*/

// The text break API can be used to fill a large buffer of rows, // The text break API can be used to fill a large buffer of rows,
// or to iterate over the text just few lines (or just one) at a time. // or to iterate over the text just few lines (or just one) at a time.
// The "next" variable of the last returned item tells where to continue. // The "next" variable of the last returned item tells where to continue.
@@ -857,14 +852,14 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
for (j = 0; j < nglyphs; j++) { for (j = 0; j < nglyphs; j++) {
float x0 = glyphs[j].x; float x0 = glyphs[j].x;
float x1 = (j+1 < nglyphs) ? glyphs[j+1].x : x+row->width; float x1 = (j+1 < nglyphs) ? glyphs[j+1].x : x+row->width;
float gx = (x0 + x1)/2;
if (mx > px && mx <= gx)
float gx = x0 * 0.3f + x1 * 0.7f;
if (mx >= px && mx < gx)
caretx = glyphs[j].x; caretx = glyphs[j].x;
px = gx; px = gx;
} }
nvgBeginPath(vg); nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(255,192,0,255)); nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgRect(vg, caretx, y, 2, lineh);
nvgRect(vg, caretx, y, 1, lineh);
nvgFill(vg); nvgFill(vg);
} }
y += lineh; y += lineh;


+ 7
- 6
example/perf.c View File

@@ -17,25 +17,26 @@
// timer query support // timer query support
#ifndef GL_ARB_timer_query #ifndef GL_ARB_timer_query
#define GL_TIME_ELAPSED 0x88BF #define GL_TIME_ELAPSED 0x88BF
typedef void (APIENTRY *pfnGLGETQUERYOBJECTUI64V)(GLuint id, GLenum pname, GLuint64* params);
pfnGLGETQUERYOBJECTUI64V glGetQueryObjectui64v = 0;
//typedef void (APIENTRY *pfnGLGETQUERYOBJECTUI64V)(GLuint id, GLenum pname, GLuint64* params);
//pfnGLGETQUERYOBJECTUI64V glGetQueryObjectui64v = 0;
#endif #endif


void initGPUTimer(struct GPUtimer* timer) void initGPUTimer(struct GPUtimer* timer)
{ {
memset(timer, 0, sizeof(*timer)); memset(timer, 0, sizeof(*timer));


timer->supported = glfwExtensionSupported("GL_ARB_timer_query");
/* timer->supported = glfwExtensionSupported("GL_ARB_timer_query");
if (timer->supported) { if (timer->supported) {
#ifndef GL_ARB_timer_query #ifndef GL_ARB_timer_query
glGetQueryObjectui64v = (pfnGLGETQUERYOBJECTUI64V)glfwGetProcAddress("glGetQueryObjectui64v"); glGetQueryObjectui64v = (pfnGLGETQUERYOBJECTUI64V)glfwGetProcAddress("glGetQueryObjectui64v");
printf("glGetQueryObjectui64v=%p\n", glGetQueryObjectui64v);
if (!glGetQueryObjectui64v) { if (!glGetQueryObjectui64v) {
timer->supported = GL_FALSE; timer->supported = GL_FALSE;
return; return;
} }
#endif #endif
glGenQueries(GPU_QUERY_COUNT, timer->queries); glGenQueries(GPU_QUERY_COUNT, timer->queries);
}
}*/
} }


void startGPUTimer(struct GPUtimer* timer) void startGPUTimer(struct GPUtimer* timer)
@@ -58,13 +59,13 @@ int stopGPUTimer(struct GPUtimer* timer, float* times, int maxTimes)
// check for results if there are any // check for results if there are any
glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available); glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available);
if (available) { if (available) {
GLuint64 timeElapsed = 0;
/* GLuint64 timeElapsed = 0;
glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed); glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed);
timer->ret++; timer->ret++;
if (n < maxTimes) { if (n < maxTimes) {
times[n] = (float)((double)timeElapsed * 1e-9); times[n] = (float)((double)timeElapsed * 1e-9);
n++; n++;
}
}*/
} }
} }
return n; return n;


+ 44
- 30
src/nanovg.c View File

@@ -1304,7 +1304,6 @@ static int nvg__expandStrokeAndFill(struct NVGcontext* ctx, int feats, float w,
float wo = 0, iw = 0, aa = ctx->fringeWidth; float wo = 0, iw = 0, aa = ctx->fringeWidth;
int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol / 4.0f); int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol / 4.0f);
int nleft = 0; int nleft = 0;
struct NVGstate* state = nvg__getState(ctx);


if (w > 0.0f) iw = 1.0f / w; if (w > 0.0f) iw = 1.0f / w;


@@ -1791,7 +1790,6 @@ void nvgCircle(struct NVGcontext* ctx, float cx, float cy, float r)


void nvgDebugDumpPathCache(struct NVGcontext* ctx) void nvgDebugDumpPathCache(struct NVGcontext* ctx)
{ {
struct NVGstate* state = nvg__getState(ctx);
const struct NVGpath* path; const struct NVGpath* path;
int i, j; int i, j;


@@ -2038,6 +2036,8 @@ void nvgTextBox(struct NVGcontext* ctx, float x, float y, float width, const cha
int nvgTextGlyphPositions(struct NVGcontext* ctx, const char* string, const char* end, float x, float y, struct NVGglyphPosition* positions, int maxPositions) int nvgTextGlyphPositions(struct NVGcontext* ctx, const char* string, const char* end, float x, float y, struct NVGglyphPosition* positions, int maxPositions)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;
struct FONStextIter iter; struct FONStextIter iter;
struct FONSquad q; struct FONSquad q;
int npos = 0; int npos = 0;
@@ -2051,19 +2051,17 @@ int nvgTextGlyphPositions(struct NVGcontext* ctx, const char* string, const char
if (string == end) if (string == end)
return 0; return 0;


// TODO: should use scaled text to better match with rendering.

fonsSetSize(ctx->fs, state->fontSize);
fonsSetSpacing(ctx->fs, state->letterSpacing);
fonsSetBlur(ctx->fs, state->fontBlur);
fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign); fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId); fonsSetFont(ctx->fs, state->fontId);


px = x;
fonsTextIterInit(ctx->fs, &iter, x, y, string, end);
px = x*scale;
fonsTextIterInit(ctx->fs, &iter, x*scale, y*scale, string, end);
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
positions[npos].str = iter.str; positions[npos].str = iter.str;
positions[npos].x = px;
positions[npos].x = px * invscale;
px = iter.x; px = iter.x;
npos++; npos++;
if (npos >= maxPositions) if (npos >= maxPositions)
@@ -2082,6 +2080,8 @@ enum NVGcodepointType {
int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* end, float maxRowWidth, struct NVGtextRow* rows, int maxRows) int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* end, float maxRowWidth, struct NVGtextRow* rows, int maxRows)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;
struct FONStextIter iter; struct FONStextIter iter;
struct FONSquad q; struct FONSquad q;
int nrows = 0; int nrows = 0;
@@ -2104,14 +2104,14 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en


if (string == end) return 0; if (string == end) return 0;


// TODO: should use scaled text to better match with rendering.

fonsSetSize(ctx->fs, state->fontSize);
fonsSetSpacing(ctx->fs, state->letterSpacing);
fonsSetBlur(ctx->fs, state->fontBlur);
fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign); fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId); fonsSetFont(ctx->fs, state->fontId);


maxRowWidth *= scale;

fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end); fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end);
while (fonsTextIterNext(ctx->fs, &iter, &q)) { while (fonsTextIterNext(ctx->fs, &iter, &q)) {
switch (iter.codepoint) { switch (iter.codepoint) {
@@ -2140,7 +2140,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
// Always handle new lines. // Always handle new lines.
rows[nrows].start = rowStart != NULL ? rowStart : iter.str; rows[nrows].start = rowStart != NULL ? rowStart : iter.str;
rows[nrows].end = rowEnd != NULL ? rowEnd : iter.str; rows[nrows].end = rowEnd != NULL ? rowEnd : iter.str;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = iter.next; rows[nrows].next = iter.next;
nrows++; nrows++;
if (nrows >= maxRows) if (nrows >= maxRows)
@@ -2173,7 +2173,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
// The current word is longer than the row length, just break it from here. // The current word is longer than the row length, just break it from here.
rows[nrows].start = rowStart; rows[nrows].start = rowStart;
rows[nrows].end = iter.str; rows[nrows].end = iter.str;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = iter.str; rows[nrows].next = iter.str;
nrows++; nrows++;
if (nrows >= maxRows) if (nrows >= maxRows)
@@ -2188,7 +2188,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
// Break the line from the end of the last word, and start new line from the begining of the new. // Break the line from the end of the last word, and start new line from the begining of the new.
rows[nrows].start = rowStart; rows[nrows].start = rowStart;
rows[nrows].end = breakEnd; rows[nrows].end = breakEnd;
rows[nrows].width = breakWidth;
rows[nrows].width = breakWidth * invscale;
rows[nrows].next = wordStart; rows[nrows].next = wordStart;
nrows++; nrows++;
if (nrows >= maxRows) if (nrows >= maxRows)
@@ -2230,7 +2230,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
if (rowStart != NULL) { if (rowStart != NULL) {
rows[nrows].start = rowStart; rows[nrows].start = rowStart;
rows[nrows].end = rowEnd; rows[nrows].end = rowEnd;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = end; rows[nrows].next = end;
nrows++; nrows++;
} }
@@ -2241,33 +2241,47 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
float nvgTextBounds(struct NVGcontext* ctx, const char* string, const char* end, float* bounds) float nvgTextBounds(struct NVGcontext* ctx, const char* string, const char* end, float* bounds)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;
float width;


if (state->fontId == FONS_INVALID) return 0; if (state->fontId == FONS_INVALID) return 0;


// TODO: should use scaled text to better match with rendering.

fonsSetSize(ctx->fs, state->fontSize);
fonsSetSpacing(ctx->fs, state->letterSpacing);
fonsSetBlur(ctx->fs, state->fontBlur);
fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign); fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId); fonsSetFont(ctx->fs, state->fontId);


return fonsTextBounds(ctx->fs, string, end, bounds);
width = fonsTextBounds(ctx->fs, string, end, bounds);
if (bounds != NULL) {
bounds[0] *= invscale;
bounds[1] *= invscale;
bounds[2] *= invscale;
bounds[3] *= invscale;
}
return width * invscale;
} }


void nvgTextMetrics(struct NVGcontext* ctx, float* ascender, float* descender, float* lineh) void nvgTextMetrics(struct NVGcontext* ctx, float* ascender, float* descender, float* lineh)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;


if (state->fontId == FONS_INVALID) return; if (state->fontId == FONS_INVALID) return;


// TODO: should use scaled text to better match with rendering.

fonsSetSize(ctx->fs, state->fontSize);
fonsSetSpacing(ctx->fs, state->letterSpacing);
fonsSetBlur(ctx->fs, state->fontBlur);
fonsSetSize(ctx->fs, state->fontSize*scale);
fonsSetSpacing(ctx->fs, state->letterSpacing*scale);
fonsSetBlur(ctx->fs, state->fontBlur*scale);
fonsSetAlign(ctx->fs, state->textAlign); fonsSetAlign(ctx->fs, state->textAlign);
fonsSetFont(ctx->fs, state->fontId); fonsSetFont(ctx->fs, state->fontId);


fonsVertMetrics(ctx->fs, ascender, descender, lineh); fonsVertMetrics(ctx->fs, ascender, descender, lineh);
if (ascender != NULL)
*ascender *= invscale;
if (descender != NULL)
*descender *= invscale;
if (lineh != NULL)
*lineh *= invscale;
} }

Loading…
Cancel
Save