some text formatting

Signed-off-by: Slice <sergey.slice@gmail.com>
This commit is contained in:
Slice 2023-07-16 19:45:53 +03:00
parent 7bec54ee89
commit 9c3e5436ac
4 changed files with 135 additions and 99 deletions

View File

@ -76,6 +76,7 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
shapeNext = shape->next; shapeNext = shape->next;
while (group) { while (group) {
if (strcmp(group->id, IconNameX.c_str()) == 0) { if (strcmp(group->id, IconNameX.c_str()) == 0) {
strncpy(IconImage->id, group->id, 63);
break; break;
} }
group = group->next; group = group->next;

View File

@ -46,7 +46,7 @@
#include "BmLib.h" #include "BmLib.h"
#ifndef DEBUG_ALL #ifndef DEBUG_ALL
#define DEBUG_SVG 0 #define DEBUG_SVG 1
#else #else
#define DEBUG_SVG DEBUG_ALL #define DEBUG_SVG DEBUG_ALL
#endif #endif
@ -980,7 +980,7 @@ static void nsvg__addShape(NSVGparser* p)
NSVGattrib* attr = nsvg__getAttr(p); NSVGattrib* attr = nsvg__getAttr(p);
float scale; float scale;
NSVGshape* shape; NSVGshape* shape;
int i; // int i;
if (p->plist == NULL /*&& !p->isText*/ ) if (p->plist == NULL /*&& !p->isText*/ )
return; return;
@ -990,13 +990,13 @@ static void nsvg__addShape(NSVGparser* p)
memcpy(shape->id, attr->id, sizeof shape->id); memcpy(shape->id, attr->id, sizeof shape->id);
memcpy(shape->title, attr->title, sizeof shape->title); memcpy(shape->title, attr->title, sizeof shape->title);
// DBG("shapeID=%s\n", shape->id); // DBG("parse shapeID=%s\n", shape->id);
shape->group = attr->group; shape->group = attr->group;
scale = nsvg__getAverageScale(attr->xform); //ssss scale = nsvg__getAverageScale(attr->xform); //ssss
shape->strokeWidth = attr->strokeWidth * scale; shape->strokeWidth = attr->strokeWidth * scale;
shape->strokeDashOffset = attr->strokeDashOffset * scale; shape->strokeDashOffset = attr->strokeDashOffset * scale;
shape->strokeDashCount = (char)attr->strokeDashCount; shape->strokeDashCount = (char)attr->strokeDashCount;
for (i = 0; i < attr->strokeDashCount; i++) for (int i = 0; i < attr->strokeDashCount; i++)
shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
shape->strokeLineJoin = attr->strokeLineJoin; shape->strokeLineJoin = attr->strokeLineJoin;
shape->strokeLineCap = attr->strokeLineCap; shape->strokeLineCap = attr->strokeLineCap;
@ -1089,7 +1089,8 @@ static void nsvg__addShape(NSVGparser* p)
if (p->clipPath != NULL) { if (p->clipPath != NULL) {
shape->next = p->clipPath->shapes; shape->next = p->clipPath->shapes;
p->clipPath->shapes = shape; p->clipPath->shapes = shape;
} else if (p->symbolFlag) { } else
if (p->symbolFlag) {
if (p->symbols->shapes == NULL) if (p->symbols->shapes == NULL)
p->symbols->shapes = shape; p->symbols->shapes = shape;
else else
@ -1112,7 +1113,7 @@ static void nsvg__addPath(NSVGparser* p, char closed)
NSVGpath* path = NULL; NSVGpath* path = NULL;
float bounds[4]; float bounds[4];
float* curve; float* curve;
int i; // int i;
if (p->npts < 4) if (p->npts < 4)
return; return;
@ -1138,7 +1139,7 @@ static void nsvg__addPath(NSVGparser* p, char closed)
memcpy(path->pts, p->pts, p->npts * 2 * sizeof(float)); memcpy(path->pts, p->pts, p->npts * 2 * sizeof(float));
// Find bounds // Find bounds
for (i = 0; i < path->npts-1; i += 3) { for (int i = 0; i < path->npts-1; i += 3) {
curve = &path->pts[i*2]; curve = &path->pts[i*2];
nsvg__curveBounds(bounds, curve); nsvg__curveBounds(bounds, curve);
if (i == 0) { if (i == 0) {
@ -2863,7 +2864,7 @@ static void nsvg__parseTextSpan(NSVGparser* p, char** dict)
NSVGtext* text = p->text; NSVGtext* text = p->text;
float x = 0.f, y = 0.f, r = 0.f; float x = 0.f, y = 0.f, r = 0.f;
int i; int i;
DBG("parse textSpan\n"); // DBG("parse textSpan\n");
//there should be text->next with own attribs //there should be text->next with own attribs
for (i = 0; dict[i]; i += 2) { for (i = 0; dict[i]; i += 2) {
if (strcmp(dict[i], "x") == 0) { if (strcmp(dict[i], "x") == 0) {
@ -2921,7 +2922,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
NSVGattrib* attr = nsvg__getAttr(p); NSVGattrib* attr = nsvg__getAttr(p);
int i; int i;
DBG("text found\n"); // DBG("text found\n");
NSVGtext* text = (NSVGtext*)AllocateZeroPool(sizeof(NSVGtext)); NSVGtext* text = (NSVGtext*)AllocateZeroPool(sizeof(NSVGtext));
if (!text) { if (!text) {
return; return;
@ -2938,7 +2939,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
nsvg__parseAttr(p, dict[i], dict[i + 1]); nsvg__parseAttr(p, dict[i], dict[i + 1]);
} }
} }
DBG("text: x=%f y=%f attr:Style=%hhX, size=%f, id=%s\n", x, y, attr->fontFace->fontStyle, attr->fontFace->fontSize, attr->id); // DBG("text: x=%f y=%f attr:Style=%hhX, size=%f, id=%s\n", x, y, attr->fontFace->fontStyle, attr->fontFace->fontSize, attr->id);
text->x = x; text->x = x;
text->y = y; text->y = y;
text->fontSize = attr->fontFace->fontSize; text->fontSize = attr->fontFace->fontSize;
@ -2957,7 +2958,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
if (text->fontStyle < 0x30) { if (text->fontStyle < 0x30) {
text->fontStyle = 'n'; text->fontStyle = 'n';
} }
DBG("required font %s required style=%c\n", text->fontFace->fontFamily, text->fontStyle); // DBG("required font %s required style=%c\n", text->fontFace->fontFamily, text->fontStyle);
//if the font is not registered then we have to load new one //if the font is not registered then we have to load new one
NSVGfont *fontSVG = NULL; NSVGfont *fontSVG = NULL;
NSVGfontChain *fontChain = fontsDB; NSVGfontChain *fontChain = fontsDB;
@ -2965,10 +2966,10 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
while (fontChain) { while (fontChain) {
fontSVG = fontChain->font; fontSVG = fontChain->font;
if (fontSVG) { if (fontSVG) {
DBG("probe fontFamily=%s fontStyle=%c\n", fontSVG->fontFamily, fontSVG->fontStyle); // DBG("probe fontFamily=%s fontStyle=%c\n", fontSVG->fontFamily, fontSVG->fontStyle);
if (strcmp(fontSVG->fontFamily, text->fontFace->fontFamily) == 0) { if (strcmp(fontSVG->fontFamily, text->fontFace->fontFamily) == 0) {
fontChainSimilar = fontChain; fontChainSimilar = fontChain;
DBG("font %s found\n", fontSVG->fontFamily); // DBG("font %s found\n", fontSVG->fontFamily);
if (fontSVG->fontStyle == text->fontStyle) { if (fontSVG->fontStyle == text->fontStyle) {
break; break;
} }
@ -2995,7 +2996,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
p1 = nsvgParse((CHAR8*)FileData, 72, 1.0f); //later we will free parser p1 p1 = nsvgParse((CHAR8*)FileData, 72, 1.0f); //later we will free parser p1
if (!p1) { if (!p1) {
DBG("font %s not parsed\n", text->fontFace->fontFamily); // DBG("font %s not parsed\n", text->fontFace->fontFamily);
} else { } else {
fontSVG = fontsDB->font; //last added during parse file data fontSVG = fontsDB->font; //last added during parse file data
text->font = fontSVG; text->font = fontSVG;
@ -3003,11 +3004,11 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
FreePool(FileData); //after load FreePool(FileData); //after load
FileData = NULL; FileData = NULL;
} else { } else {
DBG("set embedded font\n"); // DBG("set embedded font\n");
text->font = p->font; //else embedded if present which is also double fontChain text->font = p->font; //else embedded if present which is also double fontChain
} }
} else { } else {
DBG("set found font %s\n", fontSVG->fontFamily); // DBG("set found font %s\n", fontSVG->fontFamily);
text->font = fontSVG; //the font found in fontChain text->font = fontSVG; //the font found in fontChain
} }
@ -3025,7 +3026,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
textFace[1].size = (INTN)text->fontSize; textFace[1].size = (INTN)text->fontSize;
textFace[1].color = text->fontColor; textFace[1].color = text->fontColor;
textFace[1].valid = true; textFace[1].valid = true;
DBG("set message->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize); // DBG("set message->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
} }
break; break;
} else if (!ThemeX.Daylight && strcmp(group->id, "MessageRow_night") == 0) { } else if (!ThemeX.Daylight && strcmp(group->id, "MessageRow_night") == 0) {
@ -3037,7 +3038,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
textFace[1].size = (INTN)text->fontSize; textFace[1].size = (INTN)text->fontSize;
textFace[1].color = text->fontColor; textFace[1].color = text->fontColor;
textFace[1].valid = true; textFace[1].valid = true;
DBG("set message_night->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize); // DBG("set message_night->font=%s color=%X size=%f as in MessageRow\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
break; break;
} else if (strcmp(group->id, "MenuRows") == 0) { } else if (strcmp(group->id, "MenuRows") == 0) {
if (!textFace[2].valid) { if (!textFace[2].valid) {
@ -3045,7 +3046,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
textFace[2].size = (INTN)text->fontSize; textFace[2].size = (INTN)text->fontSize;
textFace[2].color = text->fontColor; textFace[2].color = text->fontColor;
textFace[2].valid = true; textFace[2].valid = true;
DBG("set menu->font=%s color=%X size=%f as in MenuRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize); // DBG("set menu->font=%s color=%X size=%f as in MenuRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
} }
break; break;
} else if (!ThemeX.Daylight && strcmp(group->id, "MenuRows_night") == 0) { } else if (!ThemeX.Daylight && strcmp(group->id, "MenuRows_night") == 0) {
@ -3060,7 +3061,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
textFace[0].size = (INTN)text->fontSize; textFace[0].size = (INTN)text->fontSize;
textFace[0].color = text->fontColor; textFace[0].color = text->fontColor;
textFace[0].valid = true; textFace[0].valid = true;
DBG("set help->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize); // DBG("set help->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
} }
break; break;
} else if (!ThemeX.Daylight && strstr(group->id, "HelpRows_night") != NULL) { } else if (!ThemeX.Daylight && strstr(group->id, "HelpRows_night") != NULL) {
@ -3068,7 +3069,7 @@ static void nsvg__parseText(NSVGparser* p, char** dict)
textFace[0].size = (INTN)text->fontSize; textFace[0].size = (INTN)text->fontSize;
textFace[0].color = text->fontColor; textFace[0].color = text->fontColor;
textFace[0].valid = true; textFace[0].valid = true;
DBG("set help_night->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize); // DBG("set help_night->font=%s color=%X size=%f as in HelpRows\n", fontSVG->fontFamily, text->fontColor, text->fontSize);
break; break;
} }
group = group->next; group = group->next;
@ -3689,7 +3690,7 @@ static void nsvg__parseFont(NSVGparser* p, char** dict)
if (!font->horizAdvX) { if (!font->horizAdvX) {
font->horizAdvX = 1000; font->horizAdvX = 1000;
} }
DBG("found font id=%s family=%s\n", font->id, font->fontFamily); // DBG("found font id=%s family=%s\n", font->id, font->fontFamily);
NSVGfontChain* fontChain = (decltype(fontChain))AllocatePool(sizeof(*fontChain)); NSVGfontChain* fontChain = (decltype(fontChain))AllocatePool(sizeof(*fontChain));
fontChain->font = font; fontChain->font = font;
@ -3703,7 +3704,7 @@ static void nsvg__parseFontFace(NSVGparser* p, char** dict)
{ {
int i; int i;
if (!p) { if (!p) {
DBG("no parser\n"); // DBG("no parser\n");
return; return;
} }
NSVGfont* font = p->font; //if present??? assumed good svg structure NSVGfont* font = p->font; //if present??? assumed good svg structure
@ -3714,7 +3715,7 @@ static void nsvg__parseFontFace(NSVGparser* p, char** dict)
for (i = 0; dict[i]; i += 2) { for (i = 0; dict[i]; i += 2) {
if (strcmp(dict[i], "font-family") == 0) { if (strcmp(dict[i], "font-family") == 0) {
AsciiStrCpyS(font->fontFamily, 64, dict[i+1]); AsciiStrCpyS(font->fontFamily, 64, dict[i+1]);
DBG("font-family %s\n", font->fontFamily); // DBG("font-family %s\n", font->fontFamily);
} }
else if (strcmp(dict[i], "font-weight") == 0) { else if (strcmp(dict[i], "font-weight") == 0) {
float fontWeight = 0.0f; float fontWeight = 0.0f;

View File

@ -43,6 +43,7 @@
#define NANOSVG_H #define NANOSVG_H
extern "C" { extern "C" {
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
} }
#include "libeg.h" #include "libeg.h"
@ -130,13 +131,13 @@ typedef struct NSVGpath
struct NSVGpath* next; // Pointer to next path, or NULL if last element. struct NSVGpath* next; // Pointer to next path, or NULL if last element.
} NSVGpath; } NSVGpath;
typedef unsigned char NSVGclipPathIndex; typedef unsigned short NSVGclipPathIndex;
typedef struct NSVGclip typedef struct NSVGclip
{ {
NSVGclipPathIndex* index; // Array of clip path indices (of related NSVGimage). NSVGclipPathIndex* index; // Array of clip path indices (of related NSVGimage).
NSVGclipPathIndex count; // Number of clip paths in this set. NSVGclipPathIndex count; // Number of clip paths in this set.
char pad[7]; char pad[6];
} NSVGclip; } NSVGclip;
@ -174,7 +175,7 @@ typedef struct NSVGshape
char strokeLineJoin; // Stroke join type. char strokeLineJoin; // Stroke join type.
char strokeLineCap; // Stroke cap type. char strokeLineCap; // Stroke cap type.
char fillRule; // Fill rule, see NSVGfillRule. char fillRule; // Fill rule, see NSVGfillRule.
unsigned char flags; // Logical or of NSVG_FLAGS_* flags UINT8 flags; // Logical or of NSVG_FLAGS_* flags
XBool isText; XBool isText;
XBool debug; XBool debug;
XBool isSymbol; XBool isSymbol;
@ -201,6 +202,7 @@ typedef struct NSVGclipPath
typedef struct NSVGimage typedef struct NSVGimage
{ {
char id[kMaxIDLength]; // Unique id of this image
float width; // Width of the image. float width; // Width of the image.
float height; // Height of the image. float height; // Height of the image.
float realBounds[4]; float realBounds[4];
@ -212,8 +214,8 @@ typedef struct NSVGimage
NSVGclipPath* clipPaths; NSVGclipPath* clipPaths;
} NSVGimage; } NSVGimage;
#define NSVG_MAX_ATTR 1024 #define NSVG_MAX_ATTR 2048
#define NSVG_MAX_CLIP_PATHS 255 // also note NSVGclipPathIndex #define NSVG_MAX_CLIP_PATHS 1024 // also note NSVGclipPathIndex
enum NSVGgradientUnits { enum NSVGgradientUnits {
NSVG_USER_SPACE = 0, NSVG_USER_SPACE = 0,
@ -302,6 +304,7 @@ typedef struct NSVGattrib
char hasStroke; char hasStroke;
char visible; char visible;
NSVGclipPathIndex clipPathCount; NSVGclipPathIndex clipPathCount;
NSVGclipPathIndex clipPathStack[NSVG_MAX_CLIP_PATHS];
NSVGgroup* group; NSVGgroup* group;
// NSVGpattern* pattern; // NSVGpattern* pattern;
} NSVGattrib; } NSVGattrib;
@ -480,7 +483,7 @@ NSVGrasterizer* nsvgCreateRasterizer(void);
// stride - number of bytes per scaleline in the destination buffer // stride - number of bytes per scaleline in the destination buffer
void nsvgRasterize(NSVGrasterizer* r, void nsvgRasterize(NSVGrasterizer* r,
NSVGimage* image, float tx, float ty, float scalex, float scaley, NSVGimage* image, float tx, float ty, float scalex, float scaley,
unsigned char* dst, int w, int h, int stride); UINT8* dst, int w, int h, int stride);
// Deletes rasterizer context. // Deletes rasterizer context.
void nsvgDeleteRasterizer(NSVGrasterizer*); void nsvgDeleteRasterizer(NSVGrasterizer*);
@ -503,7 +506,7 @@ typedef struct NSVGpoint {
float dx, dy; float dx, dy;
float len; float len;
float dmx, dmy; float dmx, dmy;
unsigned char flags; UINT8 flags;
char pad[3]; char pad[3];
} NSVGpoint; } NSVGpoint;
@ -515,7 +518,7 @@ typedef struct NSVGactiveEdge {
} NSVGactiveEdge; } NSVGactiveEdge;
typedef struct NSVGmemPage { typedef struct NSVGmemPage {
unsigned char mem[NSVG__MEMPAGE_SIZE]; UINT8 mem[NSVG__MEMPAGE_SIZE];
int size; int size;
struct NSVGmemPage* next; struct NSVGmemPage* next;
} NSVGmemPage; } NSVGmemPage;
@ -533,9 +536,17 @@ typedef struct NSVGcachedPaint {
} NSVGcachedPaint; } NSVGcachedPaint;
typedef void (*NSVGscanlineFunction)( typedef void (*NSVGscanlineFunction)(
unsigned char* dst, int count, unsigned char* cover, int x, int y, UINT8* dst, int count, UINT8* cover, int x, int y,
/* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache); /* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache);
typedef struct NSVGstencil
{
UINT8* square;
int width, height, stride;
NSVGclipPathIndex index;
struct NSVGstencil* next;
} NSVGstencil;
struct NSVGrasterizer struct NSVGrasterizer
{ {
float px, py; float px, py;
@ -559,16 +570,18 @@ struct NSVGrasterizer
NSVGmemPage* pages; NSVGmemPage* pages;
NSVGmemPage* curpage; NSVGmemPage* curpage;
unsigned char* scanline; UINT8* scanline;
int cscanline; int cscanline;
NSVGscanlineFunction fscanline; NSVGscanlineFunction fscanline;
unsigned char* stencil; UINT8* stencil;
int stencilSize; int stencilSize;
int stencilStride; int stencilStride;
unsigned char* bitmap; UINT8* bitmap;
int width, height, stride; int width, height, stride;
NSVGstencil* stencilList;
}; };
extern NSVGfontChain *fontsDB; extern NSVGfontChain *fontsDB;

View File

@ -29,7 +29,7 @@
// Create rasterizer (can be used to render multiple images). // Create rasterizer (can be used to render multiple images).
struct NSVGrasterizer* rast = nsvgCreateRasterizer(); struct NSVGrasterizer* rast = nsvgCreateRasterizer();
// Allocate memory for image // Allocate memory for image
unsigned char* img = malloc(w*h*4); UINT8* img = malloc(w*h*4);
// Rasterize // Rasterize
scaleX = width_to_see / design_width scaleX = width_to_see / design_width
nsvgRasterize(rast, image, 0,0, scaleX, scaleY, img, w, h, w*4); nsvgRasterize(rast, image, 0,0, scaleX, scaleY, img, w, h, w*4);
@ -38,9 +38,10 @@
#include "nanosvg.h" #include "nanosvg.h"
#include "FloatLib.h" #include "FloatLib.h"
#include "XImage.h" #include "XImage.h"
#include "../Platform/Utils.h"
#ifndef DEBUG_ALL #ifndef DEBUG_ALL
#define DEBUG_SVG 0 #define DEBUG_SVG 1
#else #else
#define DEBUG_SVG DEBUG_ALL #define DEBUG_SVG DEBUG_ALL
#endif #endif
@ -125,6 +126,7 @@ NSVGrasterizer* nsvgCreateRasterizer()
if (r == NULL) return NULL; if (r == NULL) return NULL;
r->tessTol = 0.1f; //0.25f; r->tessTol = 0.1f; //0.25f;
r->distTol = 0.01f; r->distTol = 0.01f;
r->stencilList = NULL;
return r; return r;
} }
@ -147,6 +149,14 @@ void nsvgDeleteRasterizer(NSVGrasterizer* r)
if (r->scanline) FreePool(r->scanline); if (r->scanline) FreePool(r->scanline);
if (r->stencil) FreePool(r->stencil); if (r->stencil) FreePool(r->stencil);
NSVGstencil* s = r->stencilList;
while ( s != NULL) {
NSVGstencil* next = s->next;
if (s->square) FreePool(s->square);
FreePool(s);
s = next;
}
FreePool(r); FreePool(r);
} }
@ -183,9 +193,9 @@ static void nsvg__resetPool(NSVGrasterizer* r)
r->curpage = r->pages; r->curpage = r->pages;
} }
static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size) static UINT8* nsvg__alloc(NSVGrasterizer* r, int size)
{ {
unsigned char* buf; UINT8* buf;
if (size > NSVG__MEMPAGE_SIZE) return NULL; if (size > NSVG__MEMPAGE_SIZE) return NULL;
if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) { if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
r->curpage = nsvg__nextPage(r, r->curpage); r->curpage = nsvg__nextPage(r, r->curpage);
@ -217,7 +227,7 @@ static void nsvg__addPathPoint(NSVGrasterizer* r, NSVGpoint* pt, float* t, int f
if (r->npoints > 0) { if (r->npoints > 0) {
pt1 = &r->points[r->npoints-1]; pt1 = &r->points[r->npoints-1];
if (nsvg__ptEquals(pt1, &pt2, r->distTol)) { if (nsvg__ptEquals(pt1, &pt2, r->distTol)) {
r->points[r->npoints-1].flags |= (unsigned char)flags; r->points[r->npoints-1].flags |= (UINT8)flags;
return; return;
} }
} }
@ -237,7 +247,7 @@ static void nsvg__addPathPoint(NSVGrasterizer* r, NSVGpoint* pt, float* t, int f
pt1->x = pt2.x; pt1->x = pt2.x;
pt1->y = pt2.y; pt1->y = pt2.y;
pt1->flags = (unsigned char)flags; pt1->flags = (UINT8)flags;
r->npoints++; r->npoints++;
} }
@ -965,7 +975,7 @@ static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
r->freelist = z; r->freelist = z;
} }
static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax) static void nsvg__fillScanline(UINT8* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
{ {
int i = x0 >> NSVG__FIXSHIFT; int i = x0 >> NSVG__FIXSHIFT;
int j = x1 >> NSVG__FIXSHIFT; int j = x1 >> NSVG__FIXSHIFT;
@ -974,20 +984,20 @@ static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1,
if (i < len && j >= 0) { if (i < len && j >= 0) {
if (i == j) { if (i == j) {
// x0,x1 are the same pixel, so compute combined coverage // x0,x1 are the same pixel, so compute combined coverage
scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); scanline[i] = (UINT8)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
} else { } else {
if (i >= 0) // add antialiasing for x0 if (i >= 0) // add antialiasing for x0
scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); scanline[i] = (UINT8)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
else else
i = -1; // clip i = -1; // clip
if (j < len) // add antialiasing for x1 if (j < len) // add antialiasing for x1
scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); scanline[j] = (UINT8)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
else else
j = len; // clip j = len; // clip
for (++i; i < j; ++i) // fill pixels between x0 and x1 for (++i; i < j; ++i) // fill pixels between x0 and x1
scanline[i] = (unsigned char)(scanline[i] + maxWeight); scanline[i] = (UINT8)(scanline[i] + maxWeight);
} }
} }
} }
@ -995,7 +1005,7 @@ static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1,
// note: this routine clips fills that extend off the edges... ideally this // note: this routine clips fills that extend off the edges... ideally this
// wouldn't happen, but it could happen if the truetype glyph bounding boxes // wouldn't happen, but it could happen if the truetype glyph bounding boxes
// are wrong, or if the user supplies a too-small bitmap // are wrong, or if the user supplies a too-small bitmap
static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) static void nsvg__fillActiveEdges(UINT8* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
{ {
// non-zero winding fill // non-zero winding fill
int x0 = 0, w = 0; int x0 = 0, w = 0;
@ -1034,7 +1044,7 @@ static float nsvg__clampf(float a, float mn, float mx)
return a < mn ? mn : (a > mx ? mx : a); return a < mn ? mn : (a > mx ? mx : a);
} }
static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a) static UINT32 nsvg__RGBA(UINT8 r, UINT8 g, UINT8 b, UINT8 a)
{ {
return (b) | (g << 8) | (r << 16) | (a << 24); return (b) | (g << 8) | (r << 16) | (a << 24);
} }
@ -1048,7 +1058,7 @@ static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u, fl
int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8; int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
int r = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8; int r = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
int a = ((((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) * ia) >> 16; int a = ((((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) * ia) >> 16;
return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); return nsvg__RGBA((UINT8)r, (UINT8)g, (UINT8)b, (UINT8)a);
} }
static unsigned int nsvg__applyOpacity(unsigned int c, float u) static unsigned int nsvg__applyOpacity(unsigned int c, float u)
@ -1058,7 +1068,7 @@ static unsigned int nsvg__applyOpacity(unsigned int c, float u)
int g = (c>>8) & 0xff; int g = (c>>8) & 0xff;
int r = (c>>16) & 0xff; int r = (c>>16) & 0xff;
int a = (((c>>24) & 0xff)*iu) >> 8; int a = (((c>>24) & 0xff)*iu) >> 8;
return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a); return nsvg__RGBA((UINT8)r, (UINT8)g, (UINT8)b, (UINT8)a);
} }
static inline int nsvg__div255(int x) static inline int nsvg__div255(int x)
@ -1067,7 +1077,7 @@ static inline int nsvg__div255(int x)
} }
static void nsvg__scanlineBit( static void nsvg__scanlineBit(
unsigned char* row, int count, unsigned char* cover, int x, int y, UINT8* row, int count, UINT8* cover, int x, int y,
/* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache) /* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache)
{ {
//xxx where is security check that x/8 and (x+count)/8 is inside row[] index? //xxx where is security check that x/8 and (x+count)/8 is inside row[] index?
@ -1078,11 +1088,11 @@ static void nsvg__scanlineBit(
} }
} }
static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* cover, int x, int y, static void nsvg__scanlineSolid(UINT8* row, int count, UINT8* cover, int x, int y,
/* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache) /* float tx, float ty, float scalex, float scaley, */ NSVGcachedPaint* cache)
{ {
// static int once = 0; // static int once = 0;
unsigned char* dst = row + x*4; UINT8* dst = row + x*4;
if (cache->type == NSVG_PAINT_COLOR) { if (cache->type == NSVG_PAINT_COLOR) {
int cr, cg, cb, ca; int cr, cg, cb, ca;
cr = cache->colors[0] & 0xff; cr = cache->colors[0] & 0xff;
@ -1105,10 +1115,10 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
b += nsvg__div255(ia * (int)dst[2]); b += nsvg__div255(ia * (int)dst[2]);
a += nsvg__div255(ia * (int)dst[3]); a += nsvg__div255(ia * (int)dst[3]);
dst[0] = (unsigned char)r; dst[0] = (UINT8)r;
dst[1] = (unsigned char)g; dst[1] = (UINT8)g;
dst[2] = (unsigned char)b; dst[2] = (UINT8)b;
dst[3] = (unsigned char)a; dst[3] = (UINT8)a;
cover++; cover++;
dst += 4; dst += 4;
@ -1148,10 +1158,10 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
g += nsvg__div255(ia * (int)dst[1]); g += nsvg__div255(ia * (int)dst[1]);
b += nsvg__div255(ia * (int)dst[2]); b += nsvg__div255(ia * (int)dst[2]);
a += nsvg__div255(ia * (int)dst[3]); a += nsvg__div255(ia * (int)dst[3]);
dst[0] = (unsigned char)r; dst[0] = (UINT8)r;
dst[1] = (unsigned char)g; dst[1] = (UINT8)g;
dst[2] = (unsigned char)b; dst[2] = (UINT8)b;
dst[3] = (unsigned char)a; dst[3] = (UINT8)a;
cover++; cover++;
dst += 4; dst += 4;
@ -1198,10 +1208,10 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
b += nsvg__div255(ia * (int)dst[2]); b += nsvg__div255(ia * (int)dst[2]);
a += nsvg__div255(ia * (int)dst[3]); a += nsvg__div255(ia * (int)dst[3]);
dst[0] = (unsigned char)r; dst[0] = (UINT8)r;
dst[1] = (unsigned char)g; dst[1] = (UINT8)g;
dst[2] = (unsigned char)b; dst[2] = (UINT8)b;
dst[3] = (unsigned char)a; dst[3] = (UINT8)a;
cover++; cover++;
dst += 4; dst += 4;
@ -1254,10 +1264,10 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
b += nsvg__div255(ia * (int)dst[2]); b += nsvg__div255(ia * (int)dst[2]);
a += nsvg__div255(ia * (int)dst[3]); a += nsvg__div255(ia * (int)dst[3]);
dst[0] = (unsigned char)r; dst[0] = (UINT8)r;
dst[1] = (unsigned char)g; dst[1] = (UINT8)g;
dst[2] = (unsigned char)b; dst[2] = (UINT8)b;
dst[3] = (unsigned char)a; dst[3] = (UINT8)a;
cover++; cover++;
dst += 4; dst += 4;
@ -1307,10 +1317,10 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
b += nsvg__div255(ia * (int)dst[2]); b += nsvg__div255(ia * (int)dst[2]);
a += nsvg__div255(ia * (int)dst[3]); a += nsvg__div255(ia * (int)dst[3]);
dst[0] = (unsigned char)r; dst[0] = (UINT8)r;
dst[1] = (unsigned char)g; dst[1] = (UINT8)g;
dst[2] = (unsigned char)b; dst[2] = (UINT8)b;
dst[3] = (unsigned char)a; dst[3] = (UINT8)a;
cover++; cover++;
dst += 4; dst += 4;
@ -1321,6 +1331,16 @@ static void nsvg__scanlineSolid(unsigned char* row, int count, unsigned char* co
} }
} }
UINT8* FindStencil(NSVGrasterizer *r, int index)
{
NSVGstencil* sl = r->stencilList;
while (sl != NULL) {
if (sl->index == index) return sl->square;
sl = sl->next;
}
return NULL;
}
static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r,
/* float tx, float ty, float scalex, float scaley, */ /* float tx, float ty, float scalex, float scaley, */
NSVGcachedPaint* cache, char fillRule, NSVGclip* clip) NSVGcachedPaint* cache, char fillRule, NSVGclip* clip)
@ -1408,31 +1428,34 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r,
// nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scalex, scaley, cache); // nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scalex, scaley, cache);
for (int i = 0; i < clip->count; i++) { for (int i = 0; i < clip->count; i++) {
unsigned char* stencil = &r->stencil[r->stencilSize * clip->index[i] + y * r->stencilStride]; UINT8* stencil = &r->stencil[r->stencilSize * clip->index[i] + y * r->stencilStride];
// UINT8* stencil = FindStencil(r, clip->index[i]);
if (stencil) {
for (int j = xmin; j <= xmax; j++) { for (int j = xmin; j <= xmax; j++) {
if (((stencil[j / 8] >> (j % 8)) & 1) == 0) { if (((stencil[j / 8] >> (j % 8)) & 1) == 0) {
r->scanline[j] = 0; r->scanline[j] = 0;
} }
} }
} }
}
r->fscanline(&r->bitmap[y * r->stride], xmax-xmin+1, &r->scanline[xmin], xmin, y,/* tx,ty, scalex, scaley, */ cache); r->fscanline(&r->bitmap[y * r->stride], xmax-xmin+1, &r->scanline[xmin], xmin, y,/* tx,ty, scalex, scaley, */ cache);
} }
} }
} }
static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) static void nsvg__unpremultiplyAlpha(UINT8* image, int w, int h, int stride)
{ {
// Unpremultiply // Unpremultiply
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
unsigned char *row = &image[y*stride]; UINT8 *row = &image[y*stride];
for (int x = 0; x < w; x++) { for (int x = 0; x < w; x++) {
int r = row[0], g = row[1], b = row[2], a = row[3]; int r = row[0], g = row[1], b = row[2], a = row[3];
if (a != 0) { if (a != 0) {
row[0] = (unsigned char)(r*255/a); row[0] = (UINT8)(r*255/a);
row[1] = (unsigned char)(g*255/a); row[1] = (UINT8)(g*255/a);
row[2] = (unsigned char)(b*255/a); row[2] = (UINT8)(b*255/a);
} }
row += 4; row += 4;
} }
@ -1440,7 +1463,7 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int str
// Defringe // Defringe
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
unsigned char *row = &image[y*stride]; UINT8 *row = &image[y*stride];
for (int x = 0; x < w; x++) { for (int x = 0; x < w; x++) {
int r = 0, g = 0, b = 0, a = row[3], n = 0; int r = 0, g = 0, b = 0, a = row[3], n = 0;
if (a == 0) { if (a == 0) {
@ -1469,9 +1492,9 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int str
n++; n++;
} }
if (n > 0) { if (n > 0) {
row[0] = (unsigned char)(r/n); row[0] = (UINT8)(r/n);
row[1] = (unsigned char)(g/n); row[1] = (UINT8)(g/n);
row[2] = (unsigned char)(b/n); row[2] = (UINT8)(b/n);
} }
} }
row += 4; row += 4;
@ -1615,7 +1638,7 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
static void nsvg__rasterizeShapes(NSVGrasterizer* r, static void nsvg__rasterizeShapes(NSVGrasterizer* r,
NSVGshape* shapes, float tx, float ty, float scalex, float scaley, NSVGshape* shapes, float tx, float ty, float scalex, float scaley,
unsigned char* dst, int w, int h, int stride, UINT8* dst, int w, int h, int stride,
NSVGscanlineFunction fscanline) NSVGscanlineFunction fscanline)
{ {
NSVGshape *shape = NULL, *shapeLink = NULL; NSVGshape *shape = NULL, *shapeLink = NULL;
@ -1632,9 +1655,9 @@ static void nsvg__rasterizeShapes(NSVGrasterizer* r,
int oldw = r->cscanline; int oldw = r->cscanline;
r->cscanline = w; r->cscanline = w;
if (oldw == 0) { if (oldw == 0) {
r->scanline = (unsigned char*)AllocatePool(w); r->scanline = (UINT8*)AllocatePool(w);
} else { } else {
r->scanline = (unsigned char*)ReallocatePool(oldw, w, r->scanline); r->scanline = (UINT8*)ReallocatePool(oldw, w, r->scanline);
} }
if (r->scanline == NULL) return; if (r->scanline == NULL) return;
} }
@ -1684,6 +1707,10 @@ static void renderShape(NSVGrasterizer* r,
NSVGcachedPaint cache; NSVGcachedPaint cache;
SetMem(&cache, sizeof(NSVGcachedPaint), 0); SetMem(&cache, sizeof(NSVGcachedPaint), 0);
// NSVGclip& clip = shape->clip;
// for (int i=0; i < clip.count; i++) {
// DBG("renderShape %s with clip %d\n", shape->id, clip.index[i]);
// }
if (shape->fill.type != NSVG_PAINT_NONE) { if (shape->fill.type != NSVG_PAINT_NONE) {
nsvg__resetPool(r); nsvg__resetPool(r);
@ -1731,10 +1758,9 @@ void nsvg__rasterizeClipPaths(
NSVGrasterizer* r, NSVGimage* image, int w, int h, NSVGrasterizer* r, NSVGimage* image, int w, int h,
float tx, float ty, float scalex, float scaley) float tx, float ty, float scalex, float scaley)
{ {
NSVGclipPath* clipPath;
int clipPathCount = 0; int clipPathCount = 0;
clipPath = image->clipPaths; NSVGclipPath* clipPath = image->clipPaths;
if (clipPath == NULL) { if (clipPath == NULL) {
r->stencil = NULL; r->stencil = NULL;
return; return;
@ -1769,16 +1795,11 @@ void nsvg__rasterizeClipPaths(
void nsvgRasterize(NSVGrasterizer* r, void nsvgRasterize(NSVGrasterizer* r,
NSVGimage* image, float tx, float ty, float scalex, float scaley, NSVGimage* image, float tx, float ty, float scalex, float scaley,
unsigned char* dst, int w, int h, int stride) UINT8* dst, int w, int h, int stride)
{ {
// int i;
// for (i = 0; i < h; i++)
// memset(&dst[i*stride], 0, w*4); //dst prepared before
tx -= image->realBounds[0] * scalex; tx -= image->realBounds[0] * scalex;
ty -= image->realBounds[1] * scaley; ty -= image->realBounds[1] * scaley;
// DBG(" image will be shifted by [%f,%f]\n", tx, ty); DBG(" image will be scaled by [%f]\n", scalex);
// DumpFloat(" image real bounds ", image->realBounds, 4); // DumpFloat(" image real bounds ", image->realBounds, 4);
nsvg__rasterizeClipPaths(r, image, w, h, tx, ty, scalex, scaley); nsvg__rasterizeClipPaths(r, image, w, h, tx, ty, scalex, scaley);