Skip to content

Commit 652aa29

Browse files
committed
good clipPath
Signed-off-by: Slice <sergey.slice@gmail.com>
1 parent cf2fc83 commit 652aa29

2 files changed

Lines changed: 253 additions & 133 deletions

File tree

rEFIt_UEFI/libeg/nanosvg.cpp

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,7 @@ static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, bool dump); //
971971
static NSVGgradient* nsvg__createGradient(NSVGparser* p, NSVGshape* shape, NSVGgradientLink* link, char* paintType)
972972
{
973973
// NSVGattrib* attr = nsvg__getAttr(p);
974+
DBG("createGradient: START for shape %s\n", shape->id);
974975
NSVGgradientData* data = NULL;
975976
NSVGgradientData* ref = NULL;
976977
NSVGgradientStop* stops = NULL;
@@ -1084,7 +1085,7 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, NSVGshape* shape, NSVGg
10841085
grad->nstops = nstops;
10851086

10861087
*paintType = data->type;
1087-
1088+
DBG("createGradient: END\n");
10881089
return grad;
10891090
}
10901091

@@ -1144,6 +1145,27 @@ static void nsvg__addShape(NSVGparser* p)
11441145
shape = (NSVGshape*)nsvg__alloczero(sizeof(NSVGshape), S8Printf("nsvg__addShape %s", attr->id));
11451146
if (shape == NULL) return;
11461147

1148+
// Проверяем, есть ли реальные ссылки на clipPath
1149+
// if (attr->clipList) {
1150+
// // Проверяем, используется ли этот clipPath
1151+
// NSVGclipNode* node = attr->clipList;
1152+
// XBool hasValidClip = false;
1153+
// while (node) {
1154+
// NSVGclipPath* clipPath = nsvg__findClipPath(p, NULL); // нужна функция поиска по индексу
1155+
// if (clipPath && clipPath->shapes) {
1156+
// hasValidClip = true;
1157+
// break;
1158+
// }
1159+
// node = node->next;
1160+
// }
1161+
//
1162+
// if (hasValidClip) {
1163+
// shape->clipList = attr->clipList;
1164+
// } else {
1165+
// DBG("Skipping unused clipPath for shape %s\n", shape->id);
1166+
// }
1167+
// }
1168+
11471169
memcpy(shape->id, attr->id, sizeof shape->id);
11481170
memcpy(shape->title, attr->title, sizeof shape->title);
11491171
// DBG("parse shapeID=%s\n", shape->id);
@@ -2612,11 +2634,10 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args,
26122634
float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
26132635
float sinrx, cosrx;
26142636
int fa, fs;
2615-
int ndivs;
2616-
float hda, kappa;
26172637

26182638
rx = fabsf(args[0]); // y radius
26192639
ry = fabsf(args[1]); // x radius
2640+
26202641
rotx = args[2] * NSVG_PI_DEG; // x rotation angle
26212642
fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc
26222643
fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction
@@ -2642,6 +2663,11 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args,
26422663
return;
26432664
}
26442665

2666+
// Если радиусы слишком большие по сравнению с расстоянием, ограничиваем их
2667+
float maxRadius = hypot(x2 - x1, y2 - y1) * 10.0f;
2668+
if (rx > maxRadius) rx = maxRadius;
2669+
if (ry > maxRadius) ry = maxRadius;
2670+
26452671
sinrx = sinf(rotx);
26462672
cosrx = cosf(rotx);
26472673

@@ -2666,25 +2692,7 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args,
26662692
// Вычисляем радикал более устойчивым способом
26672693
float radicand = (rx2 * ry2 - rx2 * y1p2 - ry2 * x1p2)
26682694
/ (rx2 * y1p2 + ry2 * x1p2);
2669-
2670-
// Защита от численных ошибок
2671-
if (radicand < 0.0f) {
2672-
// Если радикал отрицательный из-за ошибок округления, корректируем
2673-
if (radicand > -1e-6f) {
2674-
radicand = 0.0f;
2675-
}
2676-
else {
2677-
// Серьезная ошибка, корректируем радиусы
2678-
float scale = sqrtf((x1p2 / rx2 + y1p2 / ry2));
2679-
rx *= scale;
2680-
ry *= scale;
2681-
rx2 = rx * rx;
2682-
ry2 = ry * ry;
2683-
radicand = (rx2 * ry2 - rx2 * y1p2 - ry2 * x1p2)
2684-
/ (rx2 * y1p2 + ry2 * x1p2);
2685-
if (radicand < 0.0f) radicand = 0.0f;
2686-
}
2687-
}
2695+
if (radicand < 0.0f) radicand = 0.0f;
26882696

26892697
s = sqrtf(radicand);
26902698

@@ -2726,41 +2734,26 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args,
27262734
// Для больших радиусов нужно больше сегментов
27272735
float avgRadius = (rx + ry) * 0.5f;
27282736

2729-
ndivs = 4;
2730-
2731-
// Увеличиваем для больших углов
2732-
if (fabsf(da) > NSVG_PI * 0.5f) {
2733-
ndivs = 8;
2734-
}
2735-
if (fabsf(da) > NSVG_PI) {
2736-
ndivs = 16;
2737-
}
2738-
2739-
// Для больших радиусов увеличиваем точность
2740-
if (avgRadius > 50.0f) {
2741-
ndivs = (int) (ndivs * (avgRadius / 50.0f));
2737+
// Если дуга почти прямая (очень большой радиус), просто рисуем линию
2738+
if (avgRadius > 1000.0f && fabsf(da) < 0.05f) {
2739+
nsvg__lineTo(p, x2, y2);
2740+
*cpx = x2;
2741+
*cpy = y2;
2742+
return;
27422743
}
27432744

2744-
// Ограничиваем
2745+
int ndivs = (int)floorf(fabsf(da) / (NSVG_PI * 0.5f) + 0.5f);
27452746
if (ndivs < 4) ndivs = 4;
2746-
if (ndivs > 32) ndivs = 32;
27472747

2748-
// Вычисляем kappa - стандартная формула
2749-
hda = (da / (float) ndivs) * 0.5f;
2750-
if (fabsf(sinf(hda)) > 1e-10f) {
2751-
kappa = (4.0f / 3.0f) * (1.0f - cosf(hda)) / sinf(hda);
2752-
}
2753-
else {
2754-
kappa = 0.0f;
2755-
}
27562748

2757-
// ===== ОТЛАДКА ДУГ =====
2758-
// Выводим параметры дуги только для проблемных случаев
2759-
// (можно закомментировать после отладки)
2760-
if (fabsf(da) < 1.0f && avgRadius > 50.0f) {
2761-
DBG("ARC: rx=%f ry=%f rotx=%f fa=%d fs=%d\n", rx, ry, rotx, fa, fs); DBG(" x1=%f y1=%f x2=%f y2=%f\n", x1, y1, x2, y2); DBG(" cx=%f cy=%f da=%f ndivs=%d\n", cx, cy, da, ndivs); DBG(" a1=%f da=%f\n", a1, da);
2749+
// Вычисляем kappa - стандартная формула
2750+
float hda = (da / (float) ndivs) * 0.5f;
2751+
float kappa = (4.0f / 3.0f) * (1.0f - cosf(hda)) / sinf(hda);
2752+
if (fabsf(kappa) > 1e-6f) {
2753+
// используем kappa
2754+
} else {
2755+
kappa = 0.0f;
27622756
}
2763-
// ===== КОНЕЦ ОТЛАДКИ =====
27642757

27652758
for (int i = 0; i <= ndivs; i++) {
27662759
a = a1 + da * ((float) i / (float) ndivs);
@@ -2776,18 +2769,14 @@ static void nsvg__pathArcTo(NSVGparser *p, float *cpx, float *cpy, float *args,
27762769
ptany = tany;
27772770
}
27782771

2779-
// ... после вычисления x1p, y1p, cx, cy, da ...
2780-
2781-
DBG(" x1p=%f, y1p=%f\n", x1p, y1p); DBG(" cx=%f, cy=%f\n", cx, cy); DBG(" a1=%f, da=%f (degrees: %f)\n", a1, da, da * 180.0f / NSVG_PI); DBG(" ndivs=%d, kappa=%f\n", ndivs, kappa); DBG(" fa=%d, fs=%d\n", fa, fs);
2782-
// ===== КОНЕЦ ОТЛАДКИ =====
2783-
27842772
*cpx = x2;
27852773
*cpy = y2;
27862774
}
27872775

27882776

27892777
static void nsvg__parsePath(NSVGparser* p, char** attr, bool addShape)
27902778
{
2779+
DBG("nsvg__parsePath\n");
27912780
const char* s = NULL;
27922781
char cmd = '\0';
27932782
float args[30];

0 commit comments

Comments
 (0)