Browse Source

Merge branch 'master' of https://github.com/memononen/nanovg

shared-context
Andrew Belt 4 years ago
parent
commit
d201a1cf69
8 changed files with 2106 additions and 236 deletions
  1. +28
    -0
      .github/workflows/ci.yml
  2. +23
    -21
      example/demo.c
  3. +11
    -11
      example/perf.c
  4. +39
    -22
      src/fontstash.h
  5. +46
    -8
      src/nanovg.c
  6. +14
    -2
      src/nanovg.h
  7. +18
    -7
      src/nanovg_gl.h
  8. +1927
    -165
      src/stb_truetype.h

+ 28
- 0
.github/workflows/ci.yml View File

@@ -0,0 +1,28 @@
name: CI

on: [push]

env:
BUILD_TYPE: release

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest]

steps:
- uses: actions/checkout@v2

- name: Install required packages
run: sudo apt-get install premake4 build-essential libglfw3-dev libglew-dev pkg-config

- name: Premake
run: premake4 gmake

# due to glew problems with in the current ubuntu-latest, we don't build the examples (yet)
# https://github.com/openai/mujoco-py/issues/383 has the same problem for reference
# this doesn't happen in focal
- name: Make
run: cd build && make nanovg

+ 23
- 21
example/demo.c View File

@@ -25,7 +25,7 @@
#define ICON_TRASH 0xE729

//static float minf(float a, float b) { return a < b ? a : b; }
static float maxf(float a, float b) { return a > b ? a : b; }
//static float maxf(float a, float b) { return a > b ? a : b; }
//static float absf(float a) { return a >= 0.0f ? a : -a; }
static float clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }

@@ -98,7 +98,7 @@ void drawWindow(NVGcontext* vg, const char* title, float x, float y, float w, fl
nvgStrokeColor(vg, nvgRGBA(0,0,0,32));
nvgStroke(vg);

nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgFontFace(vg, "sans-bold");
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);

@@ -137,7 +137,7 @@ void drawSearchBox(NVGcontext* vg, const char* text, float x, float y, float w,
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
nvgText(vg, x+h*0.55f, y+h*0.55f, cpToUTF8(ICON_SEARCH,icon), NULL);

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,32));

@@ -168,7 +168,7 @@ void drawDropDown(NVGcontext* vg, const char* text, float x, float y, float w, f
nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
nvgStroke(vg);

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,160));
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
@@ -185,7 +185,7 @@ void drawLabel(NVGcontext* vg, const char* text, float x, float y, float w, floa
{
NVG_NOTUSED(w);

nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,128));

@@ -214,7 +214,7 @@ void drawEditBox(NVGcontext* vg, const char* text, float x, float y, float w, fl

drawEditBoxBase(vg, x,y, w,h);

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,64));
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
@@ -230,13 +230,13 @@ void drawEditBoxNum(NVGcontext* vg,

uw = nvgTextBounds(vg, 0,0, units, NULL, NULL);

nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,64));
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
nvgText(vg, x+w-h*0.3f,y+h*0.5f,units, NULL);

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,128));
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);
@@ -249,7 +249,7 @@ void drawCheckBox(NVGcontext* vg, const char* text, float x, float y, float w, f
char icon[8];
NVG_NOTUSED(w);

nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgFontFace(vg, "sans");
nvgFillColor(vg, nvgRGBA(255,255,255,160));

@@ -262,7 +262,7 @@ void drawCheckBox(NVGcontext* vg, const char* text, float x, float y, float w, f
nvgFillPaint(vg, bg);
nvgFill(vg);

nvgFontSize(vg, 40);
nvgFontSize(vg, 33);
nvgFontFace(vg, "icons");
nvgFillColor(vg, nvgRGBA(255,255,255,128));
nvgTextAlign(vg,NVG_ALIGN_CENTER|NVG_ALIGN_MIDDLE);
@@ -291,7 +291,7 @@ void drawButton(NVGcontext* vg, int preicon, const char* text, float x, float y,
nvgStrokeColor(vg, nvgRGBA(0,0,0,48));
nvgStroke(vg);

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans-bold");
tw = nvgTextBounds(vg, 0,0, text, NULL, NULL);
if (preicon != 0) {
@@ -309,7 +309,7 @@ void drawButton(NVGcontext* vg, int preicon, const char* text, float x, float y,
nvgText(vg, x+w*0.5f-tw*0.5f-iw*0.75f, y+h*0.5f, cpToUTF8(preicon,icon), NULL);
}

nvgFontSize(vg, 20.0f);
nvgFontSize(vg, 17.0f);
nvgFontFace(vg, "sans-bold");
nvgTextAlign(vg,NVG_ALIGN_LEFT|NVG_ALIGN_MIDDLE);
nvgFillColor(vg, nvgRGBA(0,0,0,160));
@@ -868,13 +868,15 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height,
float caretx, px;
float bounds[4];
float a;
const char* hoverText = "Hover your mouse over the text to see calculated caret position.";
float gx,gy;
int gutter = 0;
const char* boxText = "Testing\nsome multiline\ntext.";
NVG_NOTUSED(height);

nvgSave(vg);

nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgFontFace(vg, "sans");
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgTextMetrics(vg, NULL, NULL, &lineh);
@@ -891,7 +893,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height,

nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(255,255,255,hit?64:16));
nvgRect(vg, x, y, row->width, lineh);
nvgRect(vg, x + row->minx, y, row->maxx - row->minx, lineh);
nvgFill(vg);

nvgFillColor(vg, nvgRGBA(255,255,255,255));
@@ -928,7 +930,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height,
if (gutter) {
char txt[16];
snprintf(txt, sizeof(txt), "%d", gutter);
nvgFontSize(vg, 13.0f);
nvgFontSize(vg, 12.0f);
nvgTextAlign(vg, NVG_ALIGN_RIGHT|NVG_ALIGN_MIDDLE);

nvgTextBounds(vg, gx,gy, txt, NULL, bounds);
@@ -944,16 +946,16 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height,

y += 20.0f;

nvgFontSize(vg, 13.0f);
nvgFontSize(vg, 11.0f);
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgTextLineHeight(vg, 1.2f);

nvgTextBoxBounds(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL, bounds);
nvgTextBoxBounds(vg, x,y, 150, hoverText, NULL, bounds);

// Fade the tooltip out when close to it.
gx = fabsf((mx - (bounds[0]+bounds[2])*0.5f) / (bounds[0] - bounds[2]));
gy = fabsf((my - (bounds[1]+bounds[3])*0.5f) / (bounds[1] - bounds[3]));
a = maxf(gx, gy) - 0.5f;
gx = clampf(mx, bounds[0], bounds[2]) - mx;
gy = clampf(my, bounds[1], bounds[3]) - my;
a = sqrtf(gx*gx + gy*gy) / 30.0f;
a = clampf(a, 0, 1);
nvgGlobalAlpha(vg, a);

@@ -967,7 +969,7 @@ void drawParagraph(NVGcontext* vg, float x, float y, float width, float height,
nvgFill(vg);

nvgFillColor(vg, nvgRGBA(0,0,0,220));
nvgTextBox(vg, x,y, 150, "Hover your mouse over the text to see calculated caret position.", NULL);
nvgTextBox(vg, x,y, 150, hoverText, NULL);

nvgRestore(vg);
}


+ 11
- 11
example/perf.c View File

@@ -151,36 +151,36 @@ void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps)
nvgFontFace(vg, "sans");

if (fps->name[0] != '\0') {
nvgFontSize(vg, 14.0f);
nvgFontSize(vg, 12.0f);
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,192));
nvgText(vg, x+3,y+1, fps->name, NULL);
nvgText(vg, x+3,y+3, fps->name, NULL);
}

if (fps->style == GRAPH_RENDER_FPS) {
nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f FPS", 1.0f / avg);
nvgText(vg, x+w-3,y+1, str, NULL);
nvgText(vg, x+w-3,y+3, str, NULL);

nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM);
nvgFontSize(vg, 13.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BASELINE);
nvgFillColor(vg, nvgRGBA(240,240,240,160));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+h-1, str, NULL);
nvgText(vg, x+w-3,y+h-3, str, NULL);
}
else if (fps->style == GRAPH_RENDER_PERCENT) {
nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.1f %%", avg * 1.0f);
nvgText(vg, x+w-3,y+1, str, NULL);
nvgText(vg, x+w-3,y+3, str, NULL);
} else {
nvgFontSize(vg, 18.0f);
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+1, str, NULL);
nvgText(vg, x+w-3,y+3, str, NULL);
}
}

+ 39
- 22
src/fontstash.h View File

@@ -102,8 +102,8 @@ int fonsExpandAtlas(FONScontext* s, int width, int height);
int fonsResetAtlas(FONScontext* stash, int width, int height);

// Add fonts
int fonsAddFont(FONScontext* s, const char* name, const char* path);
int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData);
int fonsAddFont(FONScontext* s, const char* name, const char* path, int fontIndex);
int fonsAddFontMem(FONScontext* s, const char* name, unsigned char* data, int ndata, int freeData, int fontIndex);
int fonsGetFontByName(FONScontext* s, const char* name);

// State handling
@@ -175,13 +175,13 @@ int fons__tt_done(FONScontext *context)
return ftError == 0;
}

int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex)
{
FT_Error ftError;
FONS_NOTUSED(context);

//font->font.userdata = stash;
ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, 0, &font->font);
ftError = FT_New_Memory_Face(ftLibrary, (const FT_Byte*)data, dataSize, fontIndex, &font->font);
return ftError == 0;
}

@@ -194,7 +194,7 @@ void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, i

float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
{
return size / (font->font->ascender - font->font->descender);
return size / font->font->units_per_EM;
}

int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
@@ -210,9 +210,9 @@ int fons__tt_buildGlyphBitmap(FONSttFontImpl *font, int glyph, float size, float
FT_Fixed advFixed;
FONS_NOTUSED(scale);

ftError = FT_Set_Pixel_Sizes(font->font, 0, (FT_UInt)(size * (float)font->font->units_per_EM / (float)(font->font->ascender - font->font->descender)));
ftError = FT_Set_Pixel_Sizes(font->font, 0, size);
if (ftError) return 0;
ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT);
ftError = FT_Load_Glyph(font->font, glyph, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT);
if (ftError) return 0;
ftError = FT_Get_Advance(font->font, glyph, FT_LOAD_NO_SCALE, &advFixed);
if (ftError) return 0;
@@ -231,7 +231,7 @@ void fons__tt_renderGlyphBitmap(FONSttFontImpl *font, unsigned char *output, int
{
FT_GlyphSlot ftGlyph = font->font->glyph;
int ftGlyphOffset = 0;
int x, y;
unsigned int x, y;
FONS_NOTUSED(outWidth);
FONS_NOTUSED(outHeight);
FONS_NOTUSED(scaleX);
@@ -278,13 +278,18 @@ int fons__tt_done(FONScontext *context)
return 1;
}

int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize)
int fons__tt_loadFont(FONScontext *context, FONSttFontImpl *font, unsigned char *data, int dataSize, int fontIndex)
{
int stbError;
int offset, stbError;
FONS_NOTUSED(dataSize);

font->font.userdata = context;
stbError = stbtt_InitFont(&font->font, data, 0);
offset = stbtt_GetFontOffsetForIndex(data, fontIndex);
if (offset == -1) {
stbError = 0;
} else {
stbError = stbtt_InitFont(&font->font, data, offset);
}
return stbError;
}

@@ -295,7 +300,7 @@ void fons__tt_getFontVMetrics(FONSttFontImpl *font, int *ascent, int *descent, i

float fons__tt_getPixelHeightScale(FONSttFontImpl *font, float size)
{
return stbtt_ScaleForPixelHeight(&font->font, size);
return stbtt_ScaleForMappingEmToPixels(&font->font, size);
}

int fons__tt_getGlyphIndex(FONSttFontImpl *font, int codepoint)
@@ -792,6 +797,17 @@ int fonsAddFallbackFont(FONScontext* stash, int base, int fallback)
return 0;
}

void fonsResetFallbackFont(FONScontext* stash, int base)
{
int i;

FONSfont* baseFont = stash->fonts[base];
baseFont->nfallbacks = 0;
baseFont->nglyphs = 0;
for (i = 0; i < FONS_HASH_LUT_SIZE; i++)
baseFont->lut[i] = -1;
}

void fonsSetSize(FONScontext* stash, float size)
{
fons__getState(stash)->size = size;
@@ -890,7 +906,7 @@ error:
return FONS_INVALID;
}

int fonsAddFont(FONScontext* stash, const char* name, const char* path)
int fonsAddFont(FONScontext* stash, const char* name, const char* path, int fontIndex)
{
FILE* fp = 0;
int dataSize = 0;
@@ -908,9 +924,9 @@ int fonsAddFont(FONScontext* stash, const char* name, const char* path)
readed = fread(data, 1, dataSize, fp);
fclose(fp);
fp = 0;
if (readed != dataSize) goto error;
if (readed != (size_t)dataSize) goto error;

return fonsAddFontMem(stash, name, data, dataSize, 1);
return fonsAddFontMem(stash, name, data, dataSize, 1, fontIndex);

error:
if (data) free(data);
@@ -918,7 +934,7 @@ error:
return FONS_INVALID;
}

int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData)
int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, int dataSize, int freeData, int fontIndex)
{
int i, ascent, descent, fh, lineGap;
FONSfont* font;
@@ -943,15 +959,16 @@ int fonsAddFontMem(FONScontext* stash, const char* name, unsigned char* data, in

// Init font
stash->nscratch = 0;
if (!fons__tt_loadFont(stash, &font->font, data, dataSize)) goto error;
if (!fons__tt_loadFont(stash, &font->font, data, dataSize, fontIndex)) goto error;

// Store normalized line height. The real line height is got
// by multiplying the lineh by font size.
fons__tt_getFontVMetrics( &font->font, &ascent, &descent, &lineGap);
ascent += lineGap;
fh = ascent - descent;
font->ascender = (float)ascent / (float)fh;
font->descender = (float)descent / (float)fh;
font->lineh = (float)(fh + lineGap) / (float)fh;
font->lineh = font->ascender - font->descender;

return idx;

@@ -1208,8 +1225,8 @@ static void fons__getQuad(FONScontext* stash, FONSfont* font,
y1 = (float)(glyph->y1-1);

if (stash->params.flags & FONS_ZERO_TOPLEFT) {
rx = (float)(int)(*x + xoff);
ry = (float)(int)(*y + yoff);
rx = floorf(*x + xoff);
ry = floorf(*y + yoff);

q->x0 = rx;
q->y0 = ry;
@@ -1221,8 +1238,8 @@ static void fons__getQuad(FONScontext* stash, FONSfont* font,
q->s1 = x1 * stash->itw;
q->t1 = y1 * stash->ith;
} else {
rx = (float)(int)(*x + xoff);
ry = (float)(int)(*y - yoff);
rx = floorf(*x + xoff);
ry = floorf(*y - yoff);

q->x0 = rx;
q->y0 = ry;


+ 46
- 8
src/nanovg.c View File

@@ -24,8 +24,11 @@
#include "nanovg.h"
#define FONTSTASH_IMPLEMENTATION
#include "fontstash.h"

#ifndef NVG_NO_STB
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#endif

#ifdef _MSC_VER
#pragma warning(disable: 4100) // unreferenced formal parameter
@@ -793,6 +796,7 @@ void nvgFillPaint(NVGcontext* ctx, NVGpaint paint)
nvgTransformMultiply(state->fill.xform, state->xform);
}

#ifndef NVG_NO_STB
int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags)
{
int w, h, n, image;
@@ -821,6 +825,7 @@ int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int
stbi_image_free(img);
return image;
}
#endif

int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data)
{
@@ -2296,14 +2301,24 @@ void nvgStroke(NVGcontext* ctx)
}

// Add fonts
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* path)
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename)
{
return fonsAddFont(ctx->fs, name, filename, 0);
}

int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex)
{
return fonsAddFont(ctx->fs, name, path);
return fonsAddFont(ctx->fs, name, filename, fontIndex);
}

int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData)
{
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData);
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, 0);
}

int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex)
{
return fonsAddFontMem(ctx->fs, name, data, ndata, freeData, fontIndex);
}

int nvgFindFont(NVGcontext* ctx, const char* name)
@@ -2324,6 +2339,16 @@ int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallba
return nvgAddFallbackFontId(ctx, nvgFindFont(ctx, baseFont), nvgFindFont(ctx, fallbackFont));
}

void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont)
{
fonsResetFallbackFont(ctx->fs, baseFont);
}

void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont)
{
nvgResetFallbackFontsId(ctx, nvgFindFont(ctx, baseFont));
}

// State setting
void nvgFontSize(NVGcontext* ctx, float size)
{
@@ -2435,12 +2460,18 @@ static void nvg__renderText(NVGcontext* ctx, NVGvertex* verts, int nverts)
paint.outerColor.rgba[i] *= state->tint.rgba[i];
}

ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts);
ctx->params.renderTriangles(ctx->params.userPtr, &paint, state->compositeOperation, &state->scissor, verts, nverts, ctx->fringeWidth);

ctx->drawCallCount++;
ctx->textTriCount += nverts/3;
}

static int nvg__isTransformFlipped(const float *xform)
{
float det = xform[0] * xform[3] - xform[2] * xform[1];
return( det < 0);
}

float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end)
{
NVGstate* state = nvg__getState(ctx);
@@ -2451,6 +2482,7 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
float invscale = 1.0f / scale;
int cverts = 0;
int nverts = 0;
int isFlipped = nvg__isTransformFlipped(state->xform);

if (end == NULL)
end = string + strlen(string);
@@ -2484,6 +2516,12 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
break;
}
prevIter = iter;
if(isFlipped) {
float tmp;

tmp = q.y0; q.y0 = q.y1; q.y1 = tmp;
tmp = q.t0; q.t0 = q.t1; q.t1 = tmp;
}
// Transform corners.
nvgTransformPoint(&c[0],&c[1], state->xform, q.x0*invscale, q.y0*invscale);
nvgTransformPoint(&c[2],&c[3], state->xform, q.x1*invscale, q.y0*invscale);
@@ -2696,7 +2734,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa
rowStartX = iter.x;
rowStart = iter.str;
rowEnd = iter.next;
rowWidth = iter.nextx - rowStartX; // q.x1 - rowStartX;
rowWidth = iter.nextx - rowStartX;
rowMinX = q.x0 - rowStartX;
rowMaxX = q.x1 - rowStartX;
wordStart = iter.str;
@@ -2726,7 +2764,7 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa
if ((ptype == NVG_SPACE && (type == NVG_CHAR || type == NVG_CJK_CHAR)) || type == NVG_CJK_CHAR) {
wordStart = iter.str;
wordStartX = iter.x;
wordMinX = q.x0 - rowStartX;
wordMinX = q.x0;
}

// Break to new line when a character is beyond break width.
@@ -2763,13 +2801,13 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa
nrows++;
if (nrows >= maxRows)
return nrows;
// Update row
rowStartX = wordStartX;
rowStart = wordStart;
rowEnd = iter.next;
rowWidth = iter.nextx - rowStartX;
rowMinX = wordMinX;
rowMinX = wordMinX - rowStartX;
rowMaxX = q.x1 - rowStartX;
// No change to the word start
}
// Set null break point
breakEnd = rowStart;


+ 14
- 2
src/nanovg.h View File

@@ -415,7 +415,7 @@ NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h,
NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr,
NVGcolor icol, NVGcolor ocol);

// Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
// Creates and returns an image pattern. Parameters (ox,oy) specify the left-top location of the image pattern,
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey,
@@ -547,10 +547,16 @@ void nvgStroke(NVGcontext* ctx);
// Returns handle to the font.
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename);

// fontIndex specifies which font face to load from a .ttf/.ttc file.
int nvgCreateFontAtIndex(NVGcontext* ctx, const char* name, const char* filename, const int fontIndex);

// Creates font by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);

// fontIndex specifies which font face to load from a .ttf/.ttc file.
int nvgCreateFontMemAtIndex(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData, const int fontIndex);

// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
int nvgFindFont(NVGcontext* ctx, const char* name);

@@ -560,6 +566,12 @@ int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont);
// Adds a fallback font by name.
int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont);

// Resets fallback fonts by handle.
void nvgResetFallbackFontsId(NVGcontext* ctx, int baseFont);

// Resets fallback fonts by name.
void nvgResetFallbackFonts(NVGcontext* ctx, const char* baseFont);

// Sets the font size of current text style.
void nvgFontSize(NVGcontext* ctx, float size);

@@ -659,7 +671,7 @@ struct NVGparams {
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts, float fringe);
void (*renderDelete)(void* uptr);
};
typedef struct NVGparams NVGparams;


+ 18
- 7
src/nanovg_gl.h View File

@@ -268,6 +268,8 @@ struct GLNVGcontext {
GLuint stencilFuncMask;
GLNVGblend blendFunc;
#endif

int dummyTex;
};
typedef struct GLNVGcontext GLNVGcontext;

@@ -500,6 +502,8 @@ static void glnvg__getUniforms(GLNVGshader* shader)
#endif
}

static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);

static int glnvg__renderCreate(void* uptr)
{
GLNVGcontext* gl = (GLNVGcontext*)uptr;
@@ -700,6 +704,10 @@ static int glnvg__renderCreate(void* uptr)
#endif
gl->fragSize = sizeof(GLNVGfragUniforms) + align - sizeof(GLNVGfragUniforms) % align;

// Some platforms does not allow to have samples to unset textures.
// Create empty one which is bound when there's no texture specified.
gl->dummyTex = glnvg__renderCreateTexture(gl, NVG_TEXTURE_ALPHA, 1, 1, 0, NULL);

glnvg__checkError(gl, "create done");

glFinish();
@@ -973,6 +981,7 @@ static GLNVGfragUniforms* nvg__fragUniformPtr(GLNVGcontext* gl, int i);

static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
{
GLNVGtexture* tex = NULL;
#if NANOVG_GL_USE_UNIFORMBUFFER
glBindBufferRange(GL_UNIFORM_BUFFER, GLNVG_FRAG_BINDING, gl->fragBuf, uniformOffset, sizeof(GLNVGfragUniforms));
#else
@@ -981,12 +990,14 @@ static void glnvg__setUniforms(GLNVGcontext* gl, int uniformOffset, int image)
#endif

if (image != 0) {
GLNVGtexture* tex = glnvg__findTexture(gl, image);
glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0);
glnvg__checkError(gl, "tex paint tex");
} else {
glnvg__bindTexture(gl, 0);
tex = glnvg__findTexture(gl, image);
}
// If no image is set, use empty texture
if (tex == NULL) {
tex = glnvg__findTexture(gl, gl->dummyTex);
}
glnvg__bindTexture(gl, tex != NULL ? tex->tex : 0);
glnvg__checkError(gl, "tex paint tex");
}

static void glnvg__renderViewport(void* uptr, float width, float height, float devicePixelRatio)
@@ -1481,7 +1492,7 @@ error:
}

static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor,
const NVGvertex* verts, int nverts)
const NVGvertex* verts, int nverts, float fringe)
{
GLNVGcontext* gl = (GLNVGcontext*)uptr;
GLNVGcall* call = glnvg__allocCall(gl);
@@ -1504,7 +1515,7 @@ static void glnvg__renderTriangles(void* uptr, NVGpaint* paint, NVGcompositeOper
call->uniformOffset = glnvg__allocFragUniforms(gl, 1);
if (call->uniformOffset == -1) goto error;
frag = nvg__fragUniformPtr(gl, call->uniformOffset);
glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, 1.0f, -1.0f);
glnvg__convertPaint(gl, frag, paint, scissor, 1.0f, fringe, -1.0f);
frag->type = NSVG_SHADER_IMG;

return;


+ 1927
- 165
src/stb_truetype.h
File diff suppressed because it is too large
View File


Loading…
Cancel
Save