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);
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,
// 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.
@@ -857,14 +852,14 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
for (j = 0; j < nglyphs; j++) {
float x0 = glyphs[j].x;
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;
px = gx;
}
nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgRect(vg, caretx, y, 2, lineh);
nvgRect(vg, caretx, y, 1, lineh);
nvgFill(vg);
}
y += lineh;


+ 7
- 6
example/perf.c View File

@@ -17,25 +17,26 @@
// timer query support
#ifndef GL_ARB_timer_query
#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

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

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

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
glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available);
if (available) {
GLuint64 timeElapsed = 0;
/* GLuint64 timeElapsed = 0;
glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed);
timer->ret++;
if (n < maxTimes) {
times[n] = (float)((double)timeElapsed * 1e-9);
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;
int ncap = nvg__curveDivs(w, NVG_PI, ctx->tessTol / 4.0f);
int nleft = 0;
struct NVGstate* state = nvg__getState(ctx);

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)
{
struct NVGstate* state = nvg__getState(ctx);
const struct NVGpath* path;
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)
{
struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;
struct FONStextIter iter;
struct FONSquad q;
int npos = 0;
@@ -2051,19 +2051,17 @@ int nvgTextGlyphPositions(struct NVGcontext* ctx, const char* string, const char
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);
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)) {
positions[npos].str = iter.str;
positions[npos].x = px;
positions[npos].x = px * invscale;
px = iter.x;
npos++;
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)
{
struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;
struct FONStextIter iter;
struct FONSquad q;
int nrows = 0;
@@ -2104,14 +2104,14 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en

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);
fonsSetFont(ctx->fs, state->fontId);

maxRowWidth *= scale;

fonsTextIterInit(ctx->fs, &iter, 0, 0, string, end);
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
switch (iter.codepoint) {
@@ -2140,7 +2140,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
// Always handle new lines.
rows[nrows].start = rowStart != NULL ? rowStart : iter.str;
rows[nrows].end = rowEnd != NULL ? rowEnd : iter.str;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = iter.next;
nrows++;
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.
rows[nrows].start = rowStart;
rows[nrows].end = iter.str;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = iter.str;
nrows++;
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.
rows[nrows].start = rowStart;
rows[nrows].end = breakEnd;
rows[nrows].width = breakWidth;
rows[nrows].width = breakWidth * invscale;
rows[nrows].next = wordStart;
nrows++;
if (nrows >= maxRows)
@@ -2230,7 +2230,7 @@ int nvgTextBreakLines(struct NVGcontext* ctx, const char* string, const char* en
if (rowStart != NULL) {
rows[nrows].start = rowStart;
rows[nrows].end = rowEnd;
rows[nrows].width = rowWidth;
rows[nrows].width = rowWidth * invscale;
rows[nrows].next = end;
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)
{
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;

// 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);
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)
{
struct NVGstate* state = nvg__getState(ctx);
float scale = nvg__getFontScale(state) * ctx->devicePxRatio;
float invscale = 1.0f / scale;

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);
fonsSetFont(ctx->fs, state->fontId);

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

Loading…
Cancel
Save