advance vector graphics support, update cesium theme

Signed-off-by: Slice <sergey.slice@gmail.com>
This commit is contained in:
Slice 2023-07-19 23:39:43 +03:00
parent 9c3e5436ac
commit 5fb19df839
5 changed files with 592 additions and 184 deletions

528
CloverPackage/CloverV2/themespkg/cesium/theme.svg Executable file → Normal file

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 375 KiB

After

Width:  |  Height:  |  Size: 375 KiB

View File

@ -61,16 +61,18 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
NSVGimage *SVGimage;
NSVGparser *p = (NSVGparser *)SVGParser;
NSVGrasterizer* rast = nsvgCreateRasterizer();
SVGimage = p->image;
SVGimage = p->image; // полное изображение темы
NSVGshape *shape;
NSVGgroup *group;
NSVGimage *IconImage;
NSVGimage *IconImage; // отдельная иконка, которую нужно выделить из общей кучи
NSVGshape *shapeNext, *shapesTail = NULL, *shapePrev;
NSVGparser* p2 = nsvg__createParser();
IconImage = p2->image;
IconImage->clip.count = 0;
shape = SVGimage->shapes;
shapePrev = NULL;
// int ClipCount = 0;
while (shape) {
group = shape->group;
shapeNext = shape->next;
@ -90,13 +92,16 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
(Id == BUILTIN_ICON_BANNER)) {
shape->debug = true;
} */
// if (BootCampStyle && (strstr(IconName, "selection_big") != NULL)) {
// shape->opacity = 0.f;
// }
int prevCount = IconImage->clip.count;
for (int i=0; i<shape->clip.count; i++) {
IconImage->clip.index[prevCount+i] = shape->clip.index[i];
IconImage->clip.count++;
}
if (BootCampStyle && IconNameX.contains("selection_big")) {
shape->opacity = 0.f;
}
// if (strstr(shape->id, "BoundingRect") != NULL) {
if (XString8().takeValueFrom(shape->id).contains("BoundingRect")) {
//there is bounds after nsvgParse()
IconImage->width = shape->bounds[2] - shape->bounds[0];
@ -129,7 +134,7 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
}
shape->flags = NSVG_VIS_VISIBLE;
// Add to tail
// ClipCount += shape->clip.count;
if (IconImage->shapes == NULL)
IconImage->shapes = shape;
else
@ -146,39 +151,37 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
else {
shapePrev = shape;
}
shape = shapeNext;
// ClipCount += shape->clip.count;
shape = shapeNext;
} //while shape
shapesTail->next = NULL;
//add clipPaths //xxx
NSVGclipPath* clipPaths = SVGimage->clipPaths;
NSVGclipPath* clipNext = NULL;
while (clipPaths) {
// NSVGclipPath* clipPaths = SVGimage->clipPaths;
// NSVGclipPath* clipNext = NULL;
// while (clipPaths) {
// ClipCount += clipPaths->shapes->clip.count;
if (!clipPaths->shapes) {
break;
}
group = clipPaths->shapes->group;
clipNext = clipPaths->next;
while (group) {
// if (strcmp(group->id, IconNameX.c_str()) == 0) {
// break;
// }
if (IconNameX == XString8().takeValueFrom(group->id)) {
break;
}
group = group->parent;
}
if (group) {
DBG("found clipPaths for %s\n", IconNameX.c_str());
// if (!clipPaths->shapes) {
// break;
// }
// group = clipPaths->shapes->group;
// clipNext = clipPaths->next;
// while (group) {
// if (IconNameX == XString8().takeValueFrom(group->id)) {
// break;
// }
// group = group->parent;
// }
// if (group) {
// DBG("found clipPath for %s\n", IconNameX.c_str());
// IconImage->clipPaths = (NSVGclipPath*)AllocateCopyPool(sizeof(NSVGclipPath), SVGimage->clipPaths);
// break;
// }
// clipPaths = clipNext;
// }
// DBG("found %d clips for %s\n", IconImage->clip.count, IconNameX.c_str());
// if (IconImage->clip.count) { //Id == BUILTIN_ICON_BANNER) {
IconImage->clipPaths = SVGimage->clipPaths;
break;
}
clipPaths = clipNext;
}
// DBG("found %d clips for %s\n", ClipCount, IconName);
// if (ClipCount) { //Id == BUILTIN_ICON_BANNER) {
// IconImage->clipPaths = SVGimage->clipPaths;
// }
// }
float bounds[4];
nsvg__imageBounds(IconImage, bounds);
@ -189,23 +192,28 @@ EFI_STATUS XTheme::ParseSVGXIcon(INTN Id, const XString8& IconNameX, OUT XImage*
BannerPosX = 1; //one pixel
}
BannerPosY = (int)(bounds[1] * Scale);
DBG("Banner position at parse [%lld,%lld]\n", BannerPosX, BannerPosY);
// DBG("Banner position at parse [%lld,%lld]\n", BannerPosX, BannerPosY);
}
float Height = IconImage->height * Scale;
float Width = IconImage->width * Scale;
// DBG("icon %s width=%f height=%f\n", IconNameX.c_str(), Width, Height);
int iWidth = (int)(Width + 0.5f);
int iHeight = (int)(Height + 0.5f);
// EG_IMAGE *NewImage = egCreateFilledImage(iWidth, iHeight, true, &MenuBackgroundPixel);
if (Height < 0 || Width < 0) {
nsvgDeleteRasterizer(rast);
return EFI_NOT_FOUND;
}
// DBG("icon %s width=%f height=%f\n", IconNameX.c_str(), Width, Height);
int iWidth = ((int)(Width+0.5f) + 7) & ~0x07u;
int iHeight = ((int)(Height+0.5f) + 7) & ~0x07u;
XImage NewImage(iWidth, iHeight); //empty
if (IconImage->shapes == NULL) {
*Image = NewImage;
// DBG("return empty with status=%s\n", efiStrError(Status));
// DBG("return empty with status=%s\n", efiStrError(Status));
nsvgDeleteRasterizer(rast);
return Status;
}
IconImage->scale = Scale;
// DBG("begin rasterize %s\n", IconNameX.c_str());
// DBG("begin rasterize %s\n", IconNameX.c_str());
float tx = 0.f, ty = 0.f;
if ((Id != BUILTIN_ICON_BACKGROUND) &&
(Id != BUILTIN_ICON_ANIME) &&
@ -548,7 +556,7 @@ void testSVG()
UINT8 *FileData = NULL;
UINTN FileDataLength = 0;
INTN Width = 400, Height = 400;
INTN Width = 192, Height = 192;
#if TEST_MATH
//Test mathematique

View File

@ -1009,13 +1009,16 @@ static void nsvg__addShape(NSVGparser* p)
p->plist = NULL;
shape->clip.count = attr->clipPathCount;
if (shape->clip.count > 0) {
shape->clip.index = (NSVGclipPathIndex*)AllocateCopyPool(attr->clipPathCount * sizeof(NSVGclipPathIndex),
p->clipPathStack);
if (shape->clip.index == NULL) {
FreePool(shape);
return;
}
// if (shape->clip.count > 0) {
// shape->clip.index = (NSVGclipPathIndex*)AllocateCopyPool(attr->clipPathCount * sizeof(NSVGclipPathIndex),
// p->clipPathStack);
// if (shape->clip.index == NULL) {
// FreePool(shape);
// return;
// }
// }
for (int i=0; i<shape->clip.count; i++) {
shape->clip.index[i] = p->clipPathStack[i];
}
nsvg__getLocalBounds(shape->bounds, shape); //(dest, src)
@ -1030,9 +1033,9 @@ static void nsvg__addShape(NSVGparser* p)
shape->fill.paint.gradientLink = nsvg__createGradientLink(attr->fillGradient);
if (shape->fill.paint.gradientLink == NULL) {
shape->fill.type = NSVG_PAINT_NONE;
if (shape->clip.index) {
FreePool(shape->clip.index);
}
// if (shape->clip.index) {
// FreePool(shape->clip.index);
// }
FreePool(shape);
return;
}
@ -1059,9 +1062,9 @@ static void nsvg__addShape(NSVGparser* p)
shape->stroke.paint.gradientLink = nsvg__createGradientLink(attr->strokeGradient);
if (shape->stroke.paint.gradientLink == NULL) {
shape->fill.type = NSVG_PAINT_NONE;
if (shape->clip.index) {
FreePool(shape->clip.index);
}
// if (shape->clip.index) {
// FreePool(shape->clip.index);
// }
FreePool(shape);
return;
}
@ -4416,9 +4419,11 @@ void nsvg__imageBounds(NSVGimage* image, float* bounds)
int count = 0;
clipPath = image->clipPaths;
while (clipPath != NULL) {
if (clipPath->index == 0) { // this is bottom image
//check max bound only for this image
count = nsvg__shapesBound(clipPath->shapes, bounds);
for (int i = 0; i < image->clip.count; i++) {
if (clipPath->index == image->clip.index[i]) {
count += nsvg__shapesBound(clipPath->shapes, bounds);
break;
}
}
clipPath = clipPath->next;
}
@ -4429,6 +4434,7 @@ void nsvg__imageBounds(NSVGimage* image, float* bounds)
bounds[2] = bounds[3] = 1.0f;
}
}
// units like "px" is not used so just exclude it
NSVGparser* nsvgParse(char* input, /* const char* units,*/ float dpi, float opacity)
{
@ -4465,11 +4471,11 @@ NSVGparser* nsvgParse(char* input, /* const char* units,*/ float dpi, float opac
#if 1
memcpy(p->image->realBounds, bounds, 4*sizeof(float));
DumpFloat2("image real bounds", bounds, 4);
// DumpFloat2("image real bounds", bounds, 4);
p->image->width = bounds[2] - bounds[0];
p->image->height = bounds[3] - bounds[1];
#endif
DBG("scaled width=%f height=%f\n", p->image->width, p->image->height);
// DBG("scaled width=%f height=%f\n", p->image->width, p->image->height);
return p;
}
@ -4484,9 +4490,6 @@ void nsvg__deleteShapes(NSVGshape* shape)
nsvg__deletePaint(&shape->fill);
nsvg__deletePaint(&shape->stroke);
}
if (shape->clip.index) {
FreePool(shape->clip.index);
}
FreePool(shape);
shape = snext;
}
@ -4517,31 +4520,6 @@ void nsvgDelete(NSVGimage* image)
}
FreePool(image);
}
/*
NSVGpath* nsvgDuplicatePath(NSVGpath* p)
{
NSVGpath* res = NULL;
if (p == NULL)
return NULL;
res = (NSVGpath*)AllocateZeroPool(sizeof(NSVGpath));
if (res == NULL) return NULL;
res->pts = (float*)AllocatePool(p->npts*2*sizeof(float));
if (res->pts == NULL) {
FreePool(res);
return NULL;
}
memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2);
res->npts = p->npts;
memcpy(res->bounds, p->bounds, sizeof(p->bounds));
res->closed = p->closed;
return res;
}
*/

View File

@ -54,6 +54,11 @@ extern "C" {
#define kMaxIDLength 64
#define kMaxTextLength 256
#define NSVG_MAX_ATTR 2048
#define NSVG_MAX_CLIP_PATHS 1024 // also note NSVGclipPathIndex
enum NSVGpaintType {
NSVG_PAINT_NONE = 0,
NSVG_PAINT_COLOR = 1,
@ -135,7 +140,7 @@ typedef unsigned short NSVGclipPathIndex;
typedef struct NSVGclip
{
NSVGclipPathIndex* index; // Array of clip path indices (of related NSVGimage).
NSVGclipPathIndex index[NSVG_MAX_CLIP_PATHS]; // Array of clip path indices (of related NSVGimage).
NSVGclipPathIndex count; // Number of clip paths in this set.
char pad[6];
} NSVGclip;
@ -212,11 +217,9 @@ typedef struct NSVGimage
NSVGpath* paths; // Linked list of paths in the image.
XBool isFont;
NSVGclipPath* clipPaths;
NSVGclip clip;
} NSVGimage;
#define NSVG_MAX_ATTR 2048
#define NSVG_MAX_CLIP_PATHS 1024 // also note NSVGclipPathIndex
enum NSVGgradientUnits {
NSVG_USER_SPACE = 0,
NSVG_OBJECT_SPACE = 1

View File

@ -1366,7 +1366,6 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r,
NSVGactiveEdge *z = *step;
if (z->ey <= scany) {
*step = z->next; // delete from list
// NSVG__assert(z->valid);
nsvg__freeActive(r, z);
} else {
z->x += z->dx; // advance to position for current scanline
@ -1425,7 +1424,6 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r,
if (xmin < 0) xmin = 0;
if (xmax > r->width-1) xmax = r->width-1;
if (xmin <= xmax) {
// 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++) {
UINT8* stencil = &r->stencil[r->stencilSize * clip->index[i] + y * r->stencilStride];
@ -1542,9 +1540,6 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
nsvg__xformMultiply(cache->xform, grad->xform);
if (grad->nstops == 0) {
//for (i = 0; i < 256; i++) {
// cache->colors[i] = 0;
//}
SetMem(cache->colors, sizeof(cache->colors), 0);
} else if (grad->nstops == 1) {
for (int i = 0; i < 256; i++) {
@ -1565,8 +1560,7 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
}
for (int i = 0; i < grad->nstops-1; i++) {
// ca = nsvg__applyOpacity(grad->stops[i].color, opacity); //= color begin
// cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity); //= color end
ca = grad->stops[i].color;
cb = grad->stops[i+1].color;
ua = nsvg__clampf(grad->stops[i].offset, 0, 1); //=0
@ -1582,11 +1576,7 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
u += du;
}
}
// if (shape->debug) {
// DBG("Color cache [0,50,100,150,200,250]:%X,%X,%X,%X,%X,%X\n",
// cache->colors[0], cache->colors[50], cache->colors[100], cache->colors[150],
// cache->colors[200], cache->colors[250]);
// }
for (int i = ib; i < 256; i++) { //tail
cache->colors[i] = cb;
// cache->colors2[i] = cb;
@ -1594,47 +1584,7 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, NSVGshape*
}
}
/*
static void dumpEdges(NSVGrasterizer* r, const char* name)
{
float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
NSVGedge *e = NULL;
int i;
if (r->nedges == 0) return;
FILE* fp = fopen(name, "w");
if (fp == NULL) return;
xmin = xmax = r->edges[0].x0;
ymin = ymax = r->edges[0].y0;
for (i = 0; i < r->nedges; i++) {
e = &r->edges[i];
xmin = nsvg__minf(xmin, e->x0);
xmin = nsvg__minf(xmin, e->x1);
xmax = nsvg__maxf(xmax, e->x0);
xmax = nsvg__maxf(xmax, e->x1);
ymin = nsvg__minf(ymin, e->y0);
ymin = nsvg__minf(ymin, e->y1);
ymax = nsvg__maxf(ymax, e->y0);
ymax = nsvg__maxf(ymax, e->y1);
}
fprintf(fp, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));
for (i = 0; i < r->nedges; i++) {
e = &r->edges[i];
fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);
}
for (i = 0; i < r->npoints; i++) {
if (i+1 < r->npoints)
fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#f00;\" />", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);
fprintf(fp ,"<circle cx=\"%f\" cy=\"%f\" r=\"1\" style=\"fill:%s;\" />", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0");
}
fprintf(fp, "</svg>");
fclose(fp);
}
*/
static void nsvg__rasterizeShapes(NSVGrasterizer* r,
NSVGshape* shapes, float tx, float ty, float scalex, float scaley,
@ -1670,7 +1620,7 @@ static void nsvg__rasterizeShapes(NSVGrasterizer* r,
continue;
memcpy(&xform[0], shape->xform, sizeof(float)*6);
// nsvg__xformMultiply(xform, xform2);
xform[0] *= scalex;
xform[1] *= scaley;
xform[2] *= scalex;
@ -1707,10 +1657,12 @@ static void renderShape(NSVGrasterizer* r,
NSVGcachedPaint cache;
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]);
// }
// NSVGclip& clip = shape->clip;
// DBG("renderShape %s with clips", shape->id);
// for (int i=0; i < clip.count; i++) {
// DBG(" %d", clip.index[i]);
// }
// DBG("\n");
if (shape->fill.type != NSVG_PAINT_NONE) {
nsvg__resetPool(r);
@ -1773,8 +1725,7 @@ void nsvg__rasterizeClipPaths(
UINTN oldSize = r->stencilSize * clipPathCount;
r->stencilStride = w / 8 + (w % 8 != 0 ? 1 : 0);
r->stencilSize = h * r->stencilStride;
// r->stencil = (unsigned char*)realloc(
// r->stencil, r->stencilSize * clipPathCount);
if (oldSize == 0) {
r->stencil = (unsigned char*)AllocateZeroPool(r->stencilSize * clipPathCount);
if (r->stencil == NULL) return;
@ -1799,7 +1750,7 @@ void nsvgRasterize(NSVGrasterizer* r,
{
tx -= image->realBounds[0] * scalex;
ty -= image->realBounds[1] * scaley;
DBG(" image will be scaled by [%f]\n", scalex);
// DBG(" image %s will be scaled by [%f]\n", image->id, scalex);
// DumpFloat(" image real bounds ", image->realBounds, 4);
nsvg__rasterizeClipPaths(r, image, w, h, tx, ty, scalex, scaley);