Browse Source

Added multi-line text drawing

- fixed some warnings
- changed nvgLetterSpacing() to nvgTextLetterSpacing()
- added nvgTextBox()
- added nvgTextLineHeight()
- added some documentation
shared-context
Mikko Mononen 11 years ago
parent
commit
635f4a4afb
3 changed files with 107 additions and 33 deletions
  1. +10
    -0
      example/demo.c
  2. +63
    -10
      src/nanovg.c
  3. +34
    -23
      src/nanovg.h

+ 10
- 0
example/demo.c View File

@@ -818,6 +818,7 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
int nrows, i, nglyphs, j; int nrows, i, nglyphs, j;
float lineh; float lineh;
float caretx, px; float caretx, px;
NVG_NOTUSED(height);


nvgSave(vg); nvgSave(vg);


@@ -872,6 +873,15 @@ void drawParagraph(struct NVGcontext* vg, float x, float y, float width, float h
start = rows[nrows-1].next; start = rows[nrows-1].next;
} }


y += 10.0f;

nvgFillColor(vg, nvgRGBA(0,0,0,220));
nvgFontSize(vg, 12.0f);
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgTextLineHeight(vg, 1.2f);

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

nvgRestore(vg); nvgRestore(vg);
} }




+ 63
- 10
src/nanovg.c View File

@@ -66,6 +66,7 @@ struct NVGstate {
struct NVGscissor scissor; struct NVGscissor scissor;
float fontSize; float fontSize;
float letterSpacing; float letterSpacing;
float lineHeight;
float fontBlur; float fontBlur;
int textAlign; int textAlign;
int fontId; int fontId;
@@ -290,13 +291,23 @@ struct NVGcolor nvgRGBf(float r, float g, float b)


struct NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) struct NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{ {
struct NVGcolor color = {r/255.0f, g/255.0f, b/255.0f, a/255.0f};
struct NVGcolor color;
// Use longer initialization to suppress warning.
color.r = r / 255.0f;
color.g = g / 255.0f;
color.b = b / 255.0f;
color.a = a / 255.0f;
return color; return color;
} }


struct NVGcolor nvgRGBAf(float r, float g, float b, float a) struct NVGcolor nvgRGBAf(float r, float g, float b, float a)
{ {
struct NVGcolor color = {r, g, b, a};
struct NVGcolor color;
// Use longer initialization to suppress warning.
color.r = r;
color.g = g;
color.b = b;
color.a = a;
return color; return color;
} }


@@ -466,6 +477,7 @@ void nvgReset(struct NVGcontext* ctx)


state->fontSize = 16.0f; state->fontSize = 16.0f;
state->letterSpacing = 0.0f; state->letterSpacing = 0.0f;
state->lineHeight = 0.0f;
state->fontBlur = 0.0f; state->fontBlur = 0.0f;
state->textAlign = NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE; state->textAlign = NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE;
state->fontId = 0; state->fontId = 0;
@@ -574,7 +586,7 @@ int nvgCreateImage(struct NVGcontext* ctx, const char* filename)
return image; return image;
} }


int nvgCreateImageMem(struct NVGcontext* ctx, unsigned char* data, int ndata, int freeData)
int nvgCreateImageMem(struct NVGcontext* ctx, unsigned char* data, int ndata)
{ {
int w, h, n, image; int w, h, n, image;
unsigned char* img = stbi_load_from_memory(data, ndata, &w, &h, &n, 4); unsigned char* img = stbi_load_from_memory(data, ndata, &w, &h, &n, 4);
@@ -616,7 +628,7 @@ struct NVGpaint nvgLinearGradient(struct NVGcontext* ctx,
struct NVGpaint p; struct NVGpaint p;
float dx, dy, d; float dx, dy, d;
const float large = 1e5; const float large = 1e5;
NVG_NOTUSED(ctx);
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));


// Calculate transform aligned to the line // Calculate transform aligned to the line
@@ -655,7 +667,7 @@ struct NVGpaint nvgRadialGradient(struct NVGcontext* ctx,
struct NVGpaint p; struct NVGpaint p;
float r = (inr+outr)*0.5f; float r = (inr+outr)*0.5f;
float f = (outr-inr); float f = (outr-inr);
NVG_NOTUSED(ctx);
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));


nvg__xformIdentity(p.xform); nvg__xformIdentity(p.xform);
@@ -680,7 +692,7 @@ struct NVGpaint nvgBoxGradient(struct NVGcontext* ctx,
struct NVGcolor icol, struct NVGcolor ocol) struct NVGcolor icol, struct NVGcolor ocol)
{ {
struct NVGpaint p; struct NVGpaint p;
NVG_NOTUSED(ctx);
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));


nvg__xformIdentity(p.xform); nvg__xformIdentity(p.xform);
@@ -706,7 +718,7 @@ struct NVGpaint nvgImagePattern(struct NVGcontext* ctx,
int image, int repeat) int image, int repeat)
{ {
struct NVGpaint p; struct NVGpaint p;
NVG_NOTUSED(ctx);
memset(&p, 0, sizeof(p)); memset(&p, 0, sizeof(p));


nvg__xformRotate(p.xform, angle); nvg__xformRotate(p.xform, angle);
@@ -1873,16 +1885,22 @@ void nvgFontSize(struct NVGcontext* ctx, float size)
state->fontSize = size; state->fontSize = size;
} }


void nvgLetterSpacing(struct NVGcontext* ctx, float spacing)
void nvgFontBlur(struct NVGcontext* ctx, float blur)
{
struct NVGstate* state = nvg__getState(ctx);
state->fontBlur = blur;
}

void nvgTextLetterSpacing(struct NVGcontext* ctx, float spacing)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
state->letterSpacing = spacing; state->letterSpacing = spacing;
} }


void nvgFontBlur(struct NVGcontext* ctx, float blur)
void nvgTextLineHeight(struct NVGcontext* ctx, float lineHeight)
{ {
struct NVGstate* state = nvg__getState(ctx); struct NVGstate* state = nvg__getState(ctx);
state->fontBlur = blur;
state->lineHeight = lineHeight;
} }


void nvgTextAlign(struct NVGcontext* ctx, int align) void nvgTextAlign(struct NVGcontext* ctx, int align)
@@ -1984,6 +2002,41 @@ float nvgText(struct NVGcontext* ctx, float x, float y, const char* string, cons
return iter.x; return iter.x;
} }


float nvgTextBox(struct NVGcontext* ctx, float x, float y, float width, const char* string, const char* end)
{
struct NVGstate* state = nvg__getState(ctx);
struct NVGtextRow rows[2];
int nrows = 0, i;
int oldAlign = state->textAlign;
int haling = state->textAlign & (NVG_ALIGN_LEFT | NVG_ALIGN_CENTER | NVG_ALIGN_RIGHT);
int valign = state->textAlign & (NVG_ALIGN_TOP | NVG_ALIGN_MIDDLE | NVG_ALIGN_BOTTOM | NVG_ALIGN_BASELINE);
float lineh = 0;

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

nvgTextMetrics(ctx, NULL, NULL, &lineh);

state->textAlign = NVG_ALIGN_LEFT | valign;

while ((nrows = nvgTextBreakLines(ctx, string, end, width, rows, 2))) {
for (i = 0; i < nrows; i++) {
struct NVGtextRow* row = &rows[i];
if (haling & NVG_ALIGN_LEFT)
nvgText(ctx, x, y, row->start, row->end);
else if (haling & NVG_ALIGN_CENTER)
nvgText(ctx, x + width*0.5f - row->width*0.5f, y, row->start, row->end);
else if (haling & NVG_ALIGN_RIGHT)
nvgText(ctx, x + width - row->width, y, row->start, row->end);
y += lineh * state->lineHeight;
}
string = rows[nrows-1].next;
}

state->textAlign = oldAlign;

return 0; // TODO
}

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);


+ 34
- 23
src/nanovg.h View File

@@ -27,20 +27,16 @@ extern "C" {


struct NVGcontext; struct NVGcontext;


struct NVGcolor
{
union
{
struct NVGcolor {
union {
float rgba[4]; float rgba[4];
struct
{
struct {
float r,g,b,a; float r,g,b,a;
}; };
}; };
}; };


struct NVGpaint
{
struct NVGpaint {
float xform[6]; float xform[6];
float extent[2]; float extent[2];
float radius; float radius;
@@ -91,6 +87,19 @@ enum NVGalpha {
NVG_PREMULTIPLIED_ALPHA, NVG_PREMULTIPLIED_ALPHA,
}; };


struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x- coordinate of the position of the glyph .
};

struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
float width; // Width of the row.
};


// Begin drawing a new frame // Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame() // Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
// nvgBeginFrame() defines the size of the window to render to in relation currently // nvgBeginFrame() defines the size of the window to render to in relation currently
@@ -243,9 +252,9 @@ void nvgScale(struct NVGcontext* ctx, float x, float y);
// Returns handle to the image. // Returns handle to the image.
int nvgCreateImage(struct NVGcontext* ctx, const char* filename); int nvgCreateImage(struct NVGcontext* ctx, const char* filename);


// Creates image by loading it from the specified memory chunk.
// Creates image by loading it from the specified chunk of memory.
// Returns handle to the image. // Returns handle to the image.
int nvgCreateImageMem(struct NVGcontext* ctx, unsigned char* data, int ndata, int freeData);
int nvgCreateImageMem(struct NVGcontext* ctx, unsigned char* data, int ndata);


// Creates image from specified image data. // Creates image from specified image data.
// Returns handle to the image. // Returns handle to the image.
@@ -394,12 +403,15 @@ int nvgFindFont(struct NVGcontext* ctx, const char* name);
// Sets the font size of current text style. // Sets the font size of current text style.
void nvgFontSize(struct NVGcontext* ctx, float size); void nvgFontSize(struct NVGcontext* ctx, float size);


// Sets the letter spacing of current text style.
void nvgLetterSpacing(struct NVGcontext* ctx, float spacing);

// Sets the blur of current text style. // Sets the blur of current text style.
void nvgFontBlur(struct NVGcontext* ctx, float blur); void nvgFontBlur(struct NVGcontext* ctx, float blur);


// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(struct NVGcontext* ctx, float spacing);

// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(struct NVGcontext* ctx, float lineHeight);

// Sets the text align of current text style, see NVGaling for options. // Sets the text align of current text style, see NVGaling for options.
void nvgTextAlign(struct NVGcontext* ctx, int align); void nvgTextAlign(struct NVGcontext* ctx, int align);


@@ -412,6 +424,11 @@ void nvgFontFace(struct NVGcontext* ctx, const char* font);
// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn. // Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
float nvgText(struct NVGcontext* ctx, float x, float y, const char* string, const char* end); float nvgText(struct NVGcontext* ctx, float x, float y, const char* string, const char* end);


// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
float nvgTextBox(struct NVGcontext* ctx, float x, float y, float width, const char* string, const char* end);

// Measures the specified text string. Parameter bounds should be a pointer to float[4] if // Measures the specified text string. Parameter bounds should be a pointer to float[4] if
// the bounding box of the text should be returned. Returns the width of the measured text. // the bounding box of the text should be returned. Returns the width of the measured text.
// Current transform does not affect the measured values. // Current transform does not affect the measured values.
@@ -421,18 +438,12 @@ float nvgTextBounds(struct NVGcontext* ctx, const char* string, const char* end,
// Current transform does not affect the measured values. // Current transform does not affect the measured values.
void nvgTextMetrics(struct NVGcontext* ctx, float* ascender, float* descender, float* lineh); void nvgTextMetrics(struct NVGcontext* ctx, float* ascender, float* descender, float* lineh);


struct NVGglyphPosition {
const char* str;
float x;
};
// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
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 NVGtextRow {
const char* start;
const char* end;
const char* next;
float width;
};
// Breaks the specified text into lines. If end is specified only the sub-string will be used.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
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);


// //


Loading…
Cancel
Save