Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds basic text parsing #94

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 107 additions & 15 deletions src/nanosvg.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ typedef struct NSVGpaint {
};
} NSVGpaint;

#define kMaxIDLength 64
#define kMaxTextLength 256

typedef struct NSVGpath
{
float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
Expand All @@ -135,7 +138,7 @@ typedef struct NSVGpath

typedef struct NSVGshape
{
char id[64]; // Optional 'id' attr of the shape or its group
char id[kMaxIDLength]; // Optional 'id' attr of the shape or its group
NSVGpaint fill; // Fill paint
NSVGpaint stroke; // Stroke paint
float opacity; // Opacity of the shape.
Expand All @@ -151,6 +154,11 @@ typedef struct NSVGshape
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
NSVGpath* paths; // Linked list of paths in the image.
struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
char fontFamily[64];
char fontWeight[64];
float fontSize;
char isText;
char textData[kMaxTextLength];
} NSVGshape;

typedef struct NSVGimage
Expand Down Expand Up @@ -408,7 +416,7 @@ typedef struct NSVGgradientData

typedef struct NSVGattrib
{
char id[64];
char id[kMaxIDLength];
float xform[6];
unsigned int fillColor;
unsigned int strokeColor;
Expand All @@ -426,6 +434,8 @@ typedef struct NSVGattrib
float miterLimit;
char fillRule;
float fontSize;
char fontFamily[64];
char fontWeight[64];
unsigned int stopColor;
float stopOpacity;
float stopOffset;
Expand All @@ -450,6 +460,7 @@ typedef struct NSVGparser
float dpi;
char pathFlag;
char defsFlag;
char isText;
} NSVGparser;

static void nsvg__xformIdentity(float* t)
Expand Down Expand Up @@ -636,6 +647,7 @@ static NSVGparser* nsvg__createParser()
p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
p->attr[0].hasFill = 1;
p->attr[0].visible = 1;
p->isText = 0;

return p;

Expand Down Expand Up @@ -935,7 +947,7 @@ static void nsvg__addShape(NSVGparser* p)
NSVGpath* path;
int i;

if (p->plist == NULL)
if (p->plist == NULL && (p->isText == 0))
return;

shape = (NSVGshape*)malloc(sizeof(NSVGshape));
Expand All @@ -955,21 +967,48 @@ static void nsvg__addShape(NSVGparser* p)
shape->fillRule = attr->fillRule;
shape->opacity = attr->opacity;

// Text
shape->isText = p->isText;
shape->fontSize = attr->fontSize;
memcpy(shape->fontFamily, attr->fontFamily, sizeof shape->fontFamily);
memcpy(shape->fontWeight, attr->fontFamily, sizeof shape->fontWeight);

shape->paths = p->plist;
p->plist = NULL;

// Calculate shape bounds
shape->bounds[0] = shape->paths->bounds[0];
shape->bounds[1] = shape->paths->bounds[1];
shape->bounds[2] = shape->paths->bounds[2];
shape->bounds[3] = shape->paths->bounds[3];
for (path = shape->paths->next; path != NULL; path = path->next) {
shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
if(p->isText == 1) {

float values[2];

float inv[6], localBounds[4];
nsvg__xformInverse(inv, attr->xform);

//End
values[0] = (inv[2] + inv[4]);
values[1] = (inv[3] + inv[5]);

nsvg__getLocalBounds(localBounds, shape, attr->xform);

shape->bounds[0] = attr->xform[4];
shape->bounds[1] = attr->xform[5];
shape->bounds[2] = attr->xform[4];
shape->bounds[3] = attr->xform[5];
} else if (shape->paths) {

shape->bounds[0] = shape->paths->bounds[0];
shape->bounds[1] = shape->paths->bounds[1];
shape->bounds[2] = shape->paths->bounds[2];
shape->bounds[3] = shape->paths->bounds[3];
for (path = shape->paths->next; path != NULL; path = path->next) {
shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
}
}


// Set fill
if (attr->hasFill == 0) {
shape->fill.type = NSVG_PAINT_NONE;
Expand Down Expand Up @@ -1711,6 +1750,12 @@ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
attr->stopOpacity = nsvg__parseOpacity(value);
} else if (strcmp(name, "offset") == 0) {
attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
} else if (strcmp(name, "font-family") == 0) {
strncpy(attr->fontFamily, value, 63);
attr->id[63] = '\0';
} else if (strcmp(name, "font-weight") == 0) {
strncpy(attr->fontWeight, value, 63);
attr->id[63] = '\0';
} else if (strcmp(name, "id") == 0) {
strncpy(attr->id, value, 63);
attr->id[63] = '\0';
Expand Down Expand Up @@ -2126,7 +2171,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
const char* tmp[4];
char closedFlag;
int i;
char item[64];
char item[kMaxIDLength];

for (i = 0; attr[i]; i += 2) {
if (strcmp(attr[i], "d") == 0) {
Expand Down Expand Up @@ -2302,6 +2347,34 @@ static void nsvg__parseRect(NSVGparser* p, const char** attr)
}
}

static void nsvg__parseText(NSVGparser* p, const char** attr)
{
float x = 0.0f;
float y = 0.0f;
float r = 0.0f;
float xform[6];

int i;

for (i = 0; attr[i]; i += 2) {
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
if (strcmp(attr[i], "transform") == 0)
{
nsvg__parseTransform(xform, attr[i+1]);
x = nsvg__parseCoordinate(p, attr[i+1], xform[4], 0);
y = nsvg__parseCoordinate(p, attr[i+1], xform[5], 0);
}
if (strcmp(attr[i], "font-size") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)) );

}
}
p->isText = 1;

nsvg__addShape(p);
}

static void nsvg__parseCircle(NSVGparser* p, const char** attr)
{
float cx = 0.0f;
Expand Down Expand Up @@ -2599,6 +2672,10 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr)
if (strcmp(el, "g") == 0) {
nsvg__pushAttr(p);
nsvg__parseAttribs(p, attr);
} else if (strcmp(el, "text") == 0) {
nsvg__pushAttr(p);
nsvg__parseText(p, attr);
nsvg__popAttr(p);
} else if (strcmp(el, "path") == 0) {
if (p->pathFlag) // Do not allow nested paths.
return;
Expand Down Expand Up @@ -2657,8 +2734,23 @@ static void nsvg__endElement(void* ud, const char* el)

static void nsvg__content(void* ud, const char* s)
{
NSVG_NOTUSED(ud);
NSVG_NOTUSED(s);
NSVGparser* p = (NSVGparser*)ud;

NSVGshape * lastShape = NULL;
for (NSVGshape * shape = p->image->shapes; shape != NULL; shape = shape->next) {

lastShape = shape;
}

size_t length = strlen(s);

if (length > 0 && p && lastShape && !strcmp(lastShape->textData, "") )
{
memcpy(lastShape->textData, s, length * sizeof(char) );
}

// NSVG_NOTUSED(ud);
// NSVG_NOTUSED(s);
// empty
}

Expand Down