altsvgrast.h 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  1. //
  2. // "$Id: altsvgrast.h 12415 2017-09-03 13:20:52Z manolo $"
  3. //
  4. /* Modified by FLTK from original sources to support non-square X,Y axes scaling */
  5. /*
  6. * Copyright (c) 2013-14 Mikko Mononen [email protected]
  7. *
  8. * This software is provided 'as-is', without any express or implied
  9. * warranty. In no event will the authors be held liable for any damages
  10. * arising from the use of this software.
  11. *
  12. * Permission is granted to anyone to use this software for any purpose,
  13. * including commercial applications, and to alter it and redistribute it
  14. * freely, subject to the following restrictions:
  15. *
  16. * 1. The origin of this software must not be misrepresented; you must not
  17. * claim that you wrote the original software. If you use this software
  18. * in a product, an acknowledgment in the product documentation would be
  19. * appreciated but is not required.
  20. * 2. Altered source versions must be plainly marked as such, and must not be
  21. * misrepresented as being the original software.
  22. * 3. This notice may not be removed or altered from any source distribution.
  23. *
  24. * The polygon rasterization is heavily based on stb_truetype rasterizer
  25. * by Sean Barrett - http://nothings.org/
  26. *
  27. */
  28. #ifndef NANOSVGRAST_H
  29. #define NANOSVGRAST_H
  30. #ifdef __cplusplus
  31. extern "C" {
  32. #endif
  33. typedef struct NSVGrasterizer NSVGrasterizer;
  34. /* Example Usage:
  35. // Load SVG
  36. struct SNVGImage* image = nsvgParseFromFile("test.svg.");
  37. // Create rasterizer (can be used to render multiple images).
  38. struct NSVGrasterizer* rast = nsvgCreateRasterizer();
  39. // Allocate memory for image
  40. unsigned char* img = malloc(w*h*4);
  41. // Rasterize
  42. nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
  43. // For non-square X,Y scaling, use
  44. nsvgAltRasterize(rast, image, 0,0,1,1, img, w, h, w*4);
  45. */
  46. // Allocated rasterizer context.
  47. NSVGrasterizer* nsvgCreateRasterizer();
  48. // Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
  49. // r - pointer to rasterizer context
  50. // image - pointer to image to rasterize
  51. // tx,ty - image offset (applied after scaling)
  52. // scale - image scale (assumes square aspect ratio)
  53. // dst - pointer to destination image data, 4 bytes per pixel (RGBA)
  54. // w - width of the image to render
  55. // h - height of the image to render
  56. // stride - number of bytes per scaleline in the destination buffer
  57. void nsvgRasterize(NSVGrasterizer* r,
  58. NSVGimage* image, float tx, float ty, float scale,
  59. unsigned char* dst, int w, int h, int stride);
  60. // As above, but allow X and Y axes to scale independently for non-square aspects
  61. void nsvgAltRasterize(NSVGrasterizer* r,
  62. NSVGimage* image, float tx, float ty,
  63. float sx, float sy,
  64. unsigned char* dst, int w, int h, int stride);
  65. // Deletes rasterizer context.
  66. void nsvgDeleteRasterizer(NSVGrasterizer*);
  67. #ifdef __cplusplus
  68. }
  69. #endif
  70. #endif // NANOSVGRAST_H
  71. #ifdef NANOSVGRAST_IMPLEMENTATION
  72. #include <math.h>
  73. #define NSVG__SUBSAMPLES 5
  74. #define NSVG__FIXSHIFT 10
  75. #define NSVG__FIX (1 << NSVG__FIXSHIFT)
  76. #define NSVG__FIXMASK (NSVG__FIX-1)
  77. #define NSVG__MEMPAGE_SIZE 1024
  78. typedef struct NSVGedge {
  79. float x0,y0, x1,y1;
  80. int dir;
  81. struct NSVGedge* next;
  82. } NSVGedge;
  83. typedef struct NSVGpoint {
  84. float x, y;
  85. float dx, dy;
  86. float len;
  87. float dmx, dmy;
  88. unsigned char flags;
  89. } NSVGpoint;
  90. typedef struct NSVGactiveEdge {
  91. int x,dx;
  92. float ey;
  93. int dir;
  94. struct NSVGactiveEdge *next;
  95. } NSVGactiveEdge;
  96. typedef struct NSVGmemPage {
  97. unsigned char mem[NSVG__MEMPAGE_SIZE];
  98. int size;
  99. struct NSVGmemPage* next;
  100. } NSVGmemPage;
  101. typedef struct NSVGcachedPaint {
  102. char type;
  103. char spread;
  104. float xform[6];
  105. unsigned int colors[256];
  106. } NSVGcachedPaint;
  107. struct NSVGrasterizer
  108. {
  109. float px, py;
  110. float tessTol;
  111. float distTol;
  112. NSVGedge* edges;
  113. int nedges;
  114. int cedges;
  115. NSVGpoint* points;
  116. int npoints;
  117. int cpoints;
  118. NSVGpoint* points2;
  119. int npoints2;
  120. int cpoints2;
  121. NSVGactiveEdge* freelist;
  122. NSVGmemPage* pages;
  123. NSVGmemPage* curpage;
  124. unsigned char* scanline;
  125. int cscanline;
  126. unsigned char* bitmap;
  127. int width, height, stride;
  128. };
  129. NSVGrasterizer* nsvgCreateRasterizer()
  130. {
  131. NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
  132. if (r == NULL) goto error;
  133. memset(r, 0, sizeof(NSVGrasterizer));
  134. r->tessTol = 0.25f;
  135. r->distTol = 0.01f;
  136. return r;
  137. error:
  138. nsvgDeleteRasterizer(r);
  139. return NULL;
  140. }
  141. void nsvgDeleteRasterizer(NSVGrasterizer* r)
  142. {
  143. NSVGmemPage* p;
  144. if (r == NULL) return;
  145. p = r->pages;
  146. while (p != NULL) {
  147. NSVGmemPage* next = p->next;
  148. free(p);
  149. p = next;
  150. }
  151. if (r->edges) free(r->edges);
  152. if (r->points) free(r->points);
  153. if (r->points2) free(r->points2);
  154. if (r->scanline) free(r->scanline);
  155. free(r);
  156. }
  157. static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)
  158. {
  159. NSVGmemPage *newp;
  160. // If using existing chain, return the next page in chain
  161. if (cur != NULL && cur->next != NULL) {
  162. return cur->next;
  163. }
  164. // Alloc new page
  165. newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage));
  166. if (newp == NULL) return NULL;
  167. memset(newp, 0, sizeof(NSVGmemPage));
  168. // Add to linked list
  169. if (cur != NULL)
  170. cur->next = newp;
  171. else
  172. r->pages = newp;
  173. return newp;
  174. }
  175. static void nsvg__resetPool(NSVGrasterizer* r)
  176. {
  177. NSVGmemPage* p = r->pages;
  178. while (p != NULL) {
  179. p->size = 0;
  180. p = p->next;
  181. }
  182. r->curpage = r->pages;
  183. }
  184. static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)
  185. {
  186. unsigned char* buf;
  187. if (size > NSVG__MEMPAGE_SIZE) return NULL;
  188. if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
  189. r->curpage = nsvg__nextPage(r, r->curpage);
  190. }
  191. buf = &r->curpage->mem[r->curpage->size];
  192. r->curpage->size += size;
  193. return buf;
  194. }
  195. static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
  196. {
  197. float dx = x2 - x1;
  198. float dy = y2 - y1;
  199. return dx*dx + dy*dy < tol*tol;
  200. }
  201. static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)
  202. {
  203. NSVGpoint* pt;
  204. if (r->npoints > 0) {
  205. pt = &r->points[r->npoints-1];
  206. if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {
  207. pt->flags = (unsigned char)(pt->flags | flags);
  208. return;
  209. }
  210. }
  211. if (r->npoints+1 > r->cpoints) {
  212. r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  213. r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  214. if (r->points == NULL) return;
  215. }
  216. pt = &r->points[r->npoints];
  217. pt->x = x;
  218. pt->y = y;
  219. pt->flags = (unsigned char)flags;
  220. r->npoints++;
  221. }
  222. static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
  223. {
  224. if (r->npoints+1 > r->cpoints) {
  225. r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  226. r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  227. if (r->points == NULL) return;
  228. }
  229. r->points[r->npoints] = pt;
  230. r->npoints++;
  231. }
  232. static void nsvg__duplicatePoints(NSVGrasterizer* r)
  233. {
  234. if (r->npoints > r->cpoints2) {
  235. r->cpoints2 = r->npoints;
  236. r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);
  237. if (r->points2 == NULL) return;
  238. }
  239. memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);
  240. r->npoints2 = r->npoints;
  241. }
  242. static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)
  243. {
  244. NSVGedge* e;
  245. // Skip horizontal edges
  246. if (y0 == y1)
  247. return;
  248. if (r->nedges+1 > r->cedges) {
  249. r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
  250. r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges);
  251. if (r->edges == NULL) return;
  252. }
  253. e = &r->edges[r->nedges];
  254. r->nedges++;
  255. if (y0 < y1) {
  256. e->x0 = x0;
  257. e->y0 = y0;
  258. e->x1 = x1;
  259. e->y1 = y1;
  260. e->dir = 1;
  261. } else {
  262. e->x0 = x1;
  263. e->y0 = y1;
  264. e->x1 = x0;
  265. e->y1 = y0;
  266. e->dir = -1;
  267. }
  268. }
  269. static float nsvg__normalize(float *x, float* y)
  270. {
  271. float d = sqrtf((*x)*(*x) + (*y)*(*y));
  272. if (d > 1e-6f) {
  273. float id = 1.0f / d;
  274. *x *= id;
  275. *y *= id;
  276. }
  277. return d;
  278. }
  279. static float nsvg__absf(float x) { return x < 0 ? -x : x; }
  280. static void nsvg__flattenCubicBez(NSVGrasterizer* r,
  281. float x1, float y1, float x2, float y2,
  282. float x3, float y3, float x4, float y4,
  283. int level, int type)
  284. {
  285. float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
  286. float dx,dy,d2,d3;
  287. if (level > 10) return;
  288. x12 = (x1+x2)*0.5f;
  289. y12 = (y1+y2)*0.5f;
  290. x23 = (x2+x3)*0.5f;
  291. y23 = (y2+y3)*0.5f;
  292. x34 = (x3+x4)*0.5f;
  293. y34 = (y3+y4)*0.5f;
  294. x123 = (x12+x23)*0.5f;
  295. y123 = (y12+y23)*0.5f;
  296. dx = x4 - x1;
  297. dy = y4 - y1;
  298. d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx));
  299. d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx));
  300. if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
  301. nsvg__addPathPoint(r, x4, y4, type);
  302. return;
  303. }
  304. x234 = (x23+x34)*0.5f;
  305. y234 = (y23+y34)*0.5f;
  306. x1234 = (x123+x234)*0.5f;
  307. y1234 = (y123+y234)*0.5f;
  308. nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);
  309. nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);
  310. }
  311. static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float sx, float sy)
  312. {
  313. int i, j;
  314. NSVGpath* path;
  315. for (path = shape->paths; path != NULL; path = path->next) {
  316. r->npoints = 0;
  317. // Flatten path
  318. nsvg__addPathPoint(r, path->pts[0]*sx, path->pts[1]*sy, 0);
  319. for (i = 0; i < path->npts-1; i += 3) {
  320. float* p = &path->pts[i*2];
  321. nsvg__flattenCubicBez(r, p[0]*sx,p[1]*sy, p[2]*sx,p[3]*sy, p[4]*sx,p[5]*sy, p[6]*sx,p[7]*sy, 0, 0);
  322. }
  323. // Close path
  324. nsvg__addPathPoint(r, path->pts[0]*sx, path->pts[1]*sy, 0);
  325. // Build edges
  326. for (i = 0, j = r->npoints-1; i < r->npoints; j = i++)
  327. nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
  328. }
  329. }
  330. enum NSVGpointFlags
  331. {
  332. NSVG_PT_CORNER = 0x01,
  333. NSVG_PT_BEVEL = 0x02,
  334. NSVG_PT_LEFT = 0x04
  335. };
  336. static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  337. {
  338. float w = lineWidth * 0.5f;
  339. float dx = p1->x - p0->x;
  340. float dy = p1->y - p0->y;
  341. float len = nsvg__normalize(&dx, &dy);
  342. float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;
  343. float dlx = dy, dly = -dx;
  344. float lx = px - dlx*w, ly = py - dly*w;
  345. float rx = px + dlx*w, ry = py + dly*w;
  346. left->x = lx; left->y = ly;
  347. right->x = rx; right->y = ry;
  348. }
  349. static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  350. {
  351. float w = lineWidth * 0.5f;
  352. float px = p->x, py = p->y;
  353. float dlx = dy, dly = -dx;
  354. float lx = px - dlx*w, ly = py - dly*w;
  355. float rx = px + dlx*w, ry = py + dly*w;
  356. nsvg__addEdge(r, lx, ly, rx, ry);
  357. if (connect) {
  358. nsvg__addEdge(r, left->x, left->y, lx, ly);
  359. nsvg__addEdge(r, rx, ry, right->x, right->y);
  360. }
  361. left->x = lx; left->y = ly;
  362. right->x = rx; right->y = ry;
  363. }
  364. static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  365. {
  366. float w = lineWidth * 0.5f;
  367. float px = p->x - dx*w, py = p->y - dy*w;
  368. float dlx = dy, dly = -dx;
  369. float lx = px - dlx*w, ly = py - dly*w;
  370. float rx = px + dlx*w, ry = py + dly*w;
  371. nsvg__addEdge(r, lx, ly, rx, ry);
  372. if (connect) {
  373. nsvg__addEdge(r, left->x, left->y, lx, ly);
  374. nsvg__addEdge(r, rx, ry, right->x, right->y);
  375. }
  376. left->x = lx; left->y = ly;
  377. right->x = rx; right->y = ry;
  378. }
  379. #ifndef NSVG_PI
  380. #define NSVG_PI (3.14159265358979323846264338327f)
  381. #endif
  382. static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)
  383. {
  384. int i;
  385. float w = lineWidth * 0.5f;
  386. float px = p->x, py = p->y;
  387. float dlx = dy, dly = -dx;
  388. float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
  389. for (i = 0; i < ncap; i++) {
  390. float a = (float)i/(float)(ncap-1)*NSVG_PI;
  391. float ax = cosf(a) * w, ay = sinf(a) * w;
  392. float x = px - dlx*ax - dx*ay;
  393. float y = py - dly*ax - dy*ay;
  394. if (i > 0)
  395. nsvg__addEdge(r, prevx, prevy, x, y);
  396. prevx = x;
  397. prevy = y;
  398. if (i == 0) {
  399. lx = x; ly = y;
  400. } else if (i == ncap-1) {
  401. rx = x; ry = y;
  402. }
  403. }
  404. if (connect) {
  405. nsvg__addEdge(r, left->x, left->y, lx, ly);
  406. nsvg__addEdge(r, rx, ry, right->x, right->y);
  407. }
  408. left->x = lx; left->y = ly;
  409. right->x = rx; right->y = ry;
  410. }
  411. static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  412. {
  413. float w = lineWidth * 0.5f;
  414. float dlx0 = p0->dy, dly0 = -p0->dx;
  415. float dlx1 = p1->dy, dly1 = -p1->dx;
  416. float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
  417. float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
  418. float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
  419. float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);
  420. nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  421. nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  422. nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  423. nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  424. left->x = lx1; left->y = ly1;
  425. right->x = rx1; right->y = ry1;
  426. }
  427. static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  428. {
  429. float w = lineWidth * 0.5f;
  430. float dlx0 = p0->dy, dly0 = -p0->dx;
  431. float dlx1 = p1->dy, dly1 = -p1->dx;
  432. float lx0, rx0, lx1, rx1;
  433. float ly0, ry0, ly1, ry1;
  434. if (p1->flags & NSVG_PT_LEFT) {
  435. lx0 = lx1 = p1->x - p1->dmx * w;
  436. ly0 = ly1 = p1->y - p1->dmy * w;
  437. nsvg__addEdge(r, lx1, ly1, left->x, left->y);
  438. rx0 = p1->x + (dlx0 * w);
  439. ry0 = p1->y + (dly0 * w);
  440. rx1 = p1->x + (dlx1 * w);
  441. ry1 = p1->y + (dly1 * w);
  442. nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  443. nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  444. } else {
  445. lx0 = p1->x - (dlx0 * w);
  446. ly0 = p1->y - (dly0 * w);
  447. lx1 = p1->x - (dlx1 * w);
  448. ly1 = p1->y - (dly1 * w);
  449. nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  450. nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  451. rx0 = rx1 = p1->x + p1->dmx * w;
  452. ry0 = ry1 = p1->y + p1->dmy * w;
  453. nsvg__addEdge(r, right->x, right->y, rx1, ry1);
  454. }
  455. left->x = lx1; left->y = ly1;
  456. right->x = rx1; right->y = ry1;
  457. }
  458. static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)
  459. {
  460. int i, n;
  461. float w = lineWidth * 0.5f;
  462. float dlx0 = p0->dy, dly0 = -p0->dx;
  463. float dlx1 = p1->dy, dly1 = -p1->dx;
  464. float a0 = atan2f(dly0, dlx0);
  465. float a1 = atan2f(dly1, dlx1);
  466. float da = a1 - a0;
  467. float lx, ly, rx, ry;
  468. if (da < NSVG_PI) da += NSVG_PI*2;
  469. if (da > NSVG_PI) da -= NSVG_PI*2;
  470. n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
  471. if (n < 2) n = 2;
  472. if (n > ncap) n = ncap;
  473. lx = left->x;
  474. ly = left->y;
  475. rx = right->x;
  476. ry = right->y;
  477. for (i = 0; i < n; i++) {
  478. float u = (float)i/(float)(n-1);
  479. float a = a0 + u*da;
  480. float ax = cosf(a) * w, ay = sinf(a) * w;
  481. float lx1 = p1->x - ax, ly1 = p1->y - ay;
  482. float rx1 = p1->x + ax, ry1 = p1->y + ay;
  483. nsvg__addEdge(r, lx1, ly1, lx, ly);
  484. nsvg__addEdge(r, rx, ry, rx1, ry1);
  485. lx = lx1; ly = ly1;
  486. rx = rx1; ry = ry1;
  487. }
  488. left->x = lx; left->y = ly;
  489. right->x = rx; right->y = ry;
  490. }
  491. static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)
  492. {
  493. float w = lineWidth * 0.5f;
  494. float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
  495. float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);
  496. nsvg__addEdge(r, lx, ly, left->x, left->y);
  497. nsvg__addEdge(r, right->x, right->y, rx, ry);
  498. left->x = lx; left->y = ly;
  499. right->x = rx; right->y = ry;
  500. }
  501. static int nsvg__curveDivs(float r, float arc, float tol)
  502. {
  503. float da = acosf(r / (r + tol)) * 2.0f;
  504. int divs = (int)ceilf(arc / da);
  505. if (divs < 2) divs = 2;
  506. return divs;
  507. }
  508. static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth)
  509. {
  510. int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle.
  511. NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0};
  512. NSVGpoint* p0, *p1;
  513. int j, s, e;
  514. // Build stroke edges
  515. if (closed) {
  516. // Looping
  517. p0 = &points[npoints-1];
  518. p1 = &points[0];
  519. s = 0;
  520. e = npoints;
  521. } else {
  522. // Add cap
  523. p0 = &points[0];
  524. p1 = &points[1];
  525. s = 1;
  526. e = npoints-1;
  527. }
  528. if (closed) {
  529. nsvg__initClosed(&left, &right, p0, p1, lineWidth);
  530. firstLeft = left;
  531. firstRight = right;
  532. } else {
  533. // Add cap
  534. float dx = p1->x - p0->x;
  535. float dy = p1->y - p0->y;
  536. nsvg__normalize(&dx, &dy);
  537. if (lineCap == NSVG_CAP_BUTT)
  538. nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  539. else if (lineCap == NSVG_CAP_SQUARE)
  540. nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  541. else if (lineCap == NSVG_CAP_ROUND)
  542. nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
  543. }
  544. for (j = s; j < e; ++j) {
  545. if (p1->flags & NSVG_PT_CORNER) {
  546. if (lineJoin == NSVG_JOIN_ROUND)
  547. nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
  548. else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
  549. nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
  550. else
  551. nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
  552. } else {
  553. nsvg__straightJoin(r, &left, &right, p1, lineWidth);
  554. }
  555. p0 = p1++;
  556. }
  557. if (closed) {
  558. // Loop it
  559. nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
  560. nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
  561. } else {
  562. // Add cap
  563. float dx = p1->x - p0->x;
  564. float dy = p1->y - p0->y;
  565. nsvg__normalize(&dx, &dy);
  566. if (lineCap == NSVG_CAP_BUTT)
  567. nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  568. else if (lineCap == NSVG_CAP_SQUARE)
  569. nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  570. else if (lineCap == NSVG_CAP_ROUND)
  571. nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
  572. }
  573. }
  574. static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)
  575. {
  576. int i, j;
  577. NSVGpoint* p0, *p1;
  578. p0 = &r->points[r->npoints-1];
  579. p1 = &r->points[0];
  580. for (i = 0; i < r->npoints; i++) {
  581. // Calculate segment direction and length
  582. p0->dx = p1->x - p0->x;
  583. p0->dy = p1->y - p0->y;
  584. p0->len = nsvg__normalize(&p0->dx, &p0->dy);
  585. // Advance
  586. p0 = p1++;
  587. }
  588. // calculate joins
  589. p0 = &r->points[r->npoints-1];
  590. p1 = &r->points[0];
  591. for (j = 0; j < r->npoints; j++) {
  592. float dlx0, dly0, dlx1, dly1, dmr2, cross;
  593. dlx0 = p0->dy;
  594. dly0 = -p0->dx;
  595. dlx1 = p1->dy;
  596. dly1 = -p1->dx;
  597. // Calculate extrusions
  598. p1->dmx = (dlx0 + dlx1) * 0.5f;
  599. p1->dmy = (dly0 + dly1) * 0.5f;
  600. dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;
  601. if (dmr2 > 0.000001f) {
  602. float s2 = 1.0f / dmr2;
  603. if (s2 > 600.0f) {
  604. s2 = 600.0f;
  605. }
  606. p1->dmx *= s2;
  607. p1->dmy *= s2;
  608. }
  609. // Clear flags, but keep the corner.
  610. p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
  611. // Keep track of left turns.
  612. cross = p1->dx * p0->dy - p0->dx * p1->dy;
  613. if (cross > 0.0f)
  614. p1->flags |= NSVG_PT_LEFT;
  615. // Check to see if the corner needs to be beveled.
  616. if (p1->flags & NSVG_PT_CORNER) {
  617. if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {
  618. p1->flags |= NSVG_PT_BEVEL;
  619. }
  620. }
  621. p0 = p1++;
  622. }
  623. }
  624. static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float sx, float sy)
  625. {
  626. int i, j, closed;
  627. NSVGpath* path;
  628. NSVGpoint* p0, *p1;
  629. float miterLimit = shape->miterLimit;
  630. int lineJoin = shape->strokeLineJoin;
  631. int lineCap = shape->strokeLineCap;
  632. const float sw = (sx + sy) / 2; // average scaling factor
  633. const float lineWidth = shape->strokeWidth * sw; // FIXME (?)
  634. for (path = shape->paths; path != NULL; path = path->next) {
  635. // Flatten path
  636. r->npoints = 0;
  637. nsvg__addPathPoint(r, path->pts[0]*sx, path->pts[1]*sy, NSVG_PT_CORNER);
  638. for (i = 0; i < path->npts-1; i += 3) {
  639. float* p = &path->pts[i*2];
  640. nsvg__flattenCubicBez(r, p[0]*sx,p[1]*sy, p[2]*sx,p[3]*sy, p[4]*sx,p[5]*sy, p[6]*sx,p[7]*sy, 0, NSVG_PT_CORNER);
  641. }
  642. if (r->npoints < 2)
  643. continue;
  644. closed = path->closed;
  645. // If the first and last points are the same, remove the last, mark as closed path.
  646. p0 = &r->points[r->npoints-1];
  647. p1 = &r->points[0];
  648. if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {
  649. r->npoints--;
  650. p0 = &r->points[r->npoints-1];
  651. closed = 1;
  652. }
  653. if (shape->strokeDashCount > 0) {
  654. int idash = 0, dashState = 1;
  655. float totalDist = 0, dashLen, allDashLen, dashOffset;
  656. NSVGpoint cur;
  657. if (closed)
  658. nsvg__appendPathPoint(r, r->points[0]);
  659. // Duplicate points -> points2.
  660. nsvg__duplicatePoints(r);
  661. r->npoints = 0;
  662. cur = r->points2[0];
  663. nsvg__appendPathPoint(r, cur);
  664. // Figure out dash offset.
  665. allDashLen = 0;
  666. for (j = 0; j < shape->strokeDashCount; j++)
  667. allDashLen += shape->strokeDashArray[j];
  668. if (shape->strokeDashCount & 1)
  669. allDashLen *= 2.0f;
  670. // Find location inside pattern
  671. dashOffset = fmodf(shape->strokeDashOffset, allDashLen);
  672. if (dashOffset < 0.0f)
  673. dashOffset += allDashLen;
  674. while (dashOffset > shape->strokeDashArray[idash]) {
  675. dashOffset -= shape->strokeDashArray[idash];
  676. idash = (idash + 1) % shape->strokeDashCount;
  677. }
  678. dashLen = (shape->strokeDashArray[idash] - dashOffset) * sw;
  679. for (j = 1; j < r->npoints2; ) {
  680. float dx = r->points2[j].x - cur.x;
  681. float dy = r->points2[j].y - cur.y;
  682. float dist = sqrtf(dx*dx + dy*dy);
  683. if ((totalDist + dist) > dashLen) {
  684. // Calculate intermediate point
  685. float d = (dashLen - totalDist) / dist;
  686. float x = cur.x + dx * d;
  687. float y = cur.y + dy * d;
  688. nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
  689. // Stroke
  690. if (r->npoints > 1 && dashState) {
  691. nsvg__prepareStroke(r, miterLimit, lineJoin);
  692. nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  693. }
  694. // Advance dash pattern
  695. dashState = !dashState;
  696. idash = (idash+1) % shape->strokeDashCount;
  697. dashLen = shape->strokeDashArray[idash] * sw;
  698. // Restart
  699. cur.x = x;
  700. cur.y = y;
  701. cur.flags = NSVG_PT_CORNER;
  702. totalDist = 0.0f;
  703. r->npoints = 0;
  704. nsvg__appendPathPoint(r, cur);
  705. } else {
  706. totalDist += dist;
  707. cur = r->points2[j];
  708. nsvg__appendPathPoint(r, cur);
  709. j++;
  710. }
  711. }
  712. // Stroke any leftover path
  713. if (r->npoints > 1 && dashState)
  714. nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  715. } else {
  716. nsvg__prepareStroke(r, miterLimit, lineJoin);
  717. nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
  718. }
  719. }
  720. }
  721. static int nsvg__cmpEdge(const void *p, const void *q)
  722. {
  723. const NSVGedge* a = (const NSVGedge*)p;
  724. const NSVGedge* b = (const NSVGedge*)q;
  725. if (a->y0 < b->y0) return -1;
  726. if (a->y0 > b->y0) return 1;
  727. return 0;
  728. }
  729. static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)
  730. {
  731. NSVGactiveEdge* z;
  732. if (r->freelist != NULL) {
  733. // Restore from freelist.
  734. z = r->freelist;
  735. r->freelist = z->next;
  736. } else {
  737. // Alloc new edge.
  738. z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge));
  739. if (z == NULL) return NULL;
  740. }
  741. float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  742. // STBTT_assert(e->y0 <= start_point);
  743. // round dx down to avoid going too far
  744. if (dxdy < 0)
  745. z->dx = (int)(-floorf(NSVG__FIX * -dxdy));
  746. else
  747. z->dx = (int)floorf(NSVG__FIX * dxdy);
  748. z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
  749. // z->x -= off_x * FIX;
  750. z->ey = e->y1;
  751. z->next = 0;
  752. z->dir = e->dir;
  753. return z;
  754. }
  755. static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
  756. {
  757. z->next = r->freelist;
  758. r->freelist = z;
  759. }
  760. static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
  761. {
  762. int i = x0 >> NSVG__FIXSHIFT;
  763. int j = x1 >> NSVG__FIXSHIFT;
  764. if (i < *xmin) *xmin = i;
  765. if (j > *xmax) *xmax = j;
  766. if (i < len && j >= 0) {
  767. if (i == j) {
  768. // x0,x1 are the same pixel, so compute combined coverage
  769. scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
  770. } else {
  771. if (i >= 0) // add antialiasing for x0
  772. scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
  773. else
  774. i = -1; // clip
  775. if (j < len) // add antialiasing for x1
  776. scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
  777. else
  778. j = len; // clip
  779. for (++i; i < j; ++i) // fill pixels between x0 and x1
  780. scanline[i] = (unsigned char)(scanline[i] + maxWeight);
  781. }
  782. }
  783. }
  784. // note: this routine clips fills that extend off the edges... ideally this
  785. // wouldn't happen, but it could happen if the truetype glyph bounding boxes
  786. // are wrong, or if the user supplies a too-small bitmap
  787. static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
  788. {
  789. // non-zero winding fill
  790. int x0 = 0, w = 0;
  791. if (fillRule == NSVG_FILLRULE_NONZERO) {
  792. // Non-zero
  793. while (e != NULL) {
  794. if (w == 0) {
  795. // if we're currently at zero, we need to record the edge start point
  796. x0 = e->x; w += e->dir;
  797. } else {
  798. int x1 = e->x; w += e->dir;
  799. // if we went to zero, we need to draw
  800. if (w == 0)
  801. nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  802. }
  803. e = e->next;
  804. }
  805. } else if (fillRule == NSVG_FILLRULE_EVENODD) {
  806. // Even-odd
  807. while (e != NULL) {
  808. if (w == 0) {
  809. // if we're currently at zero, we need to record the edge start point
  810. x0 = e->x; w = 1;
  811. } else {
  812. int x1 = e->x; w = 0;
  813. nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  814. }
  815. e = e->next;
  816. }
  817. }
  818. }
  819. static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }
  820. static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  821. {
  822. return (r) | (g << 8) | (b << 16) | (a << 24);
  823. }
  824. static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
  825. {
  826. int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  827. int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
  828. int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
  829. int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
  830. int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
  831. return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  832. }
  833. static unsigned int nsvg__applyOpacity(unsigned int c, float u)
  834. {
  835. int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  836. int r = (c) & 0xff;
  837. int g = (c>>8) & 0xff;
  838. int b = (c>>16) & 0xff;
  839. int a = (((c>>24) & 0xff)*iu) >> 8;
  840. return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  841. }
  842. static inline int nsvg__div255(int x)
  843. {
  844. return ((x+1) * 257) >> 16;
  845. }
  846. static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
  847. float tx, float ty, float sx, float sy, NSVGcachedPaint* cache)
  848. {
  849. if (cache->type == NSVG_PAINT_COLOR) {
  850. int i, cr, cg, cb, ca;
  851. cr = cache->colors[0] & 0xff;
  852. cg = (cache->colors[0] >> 8) & 0xff;
  853. cb = (cache->colors[0] >> 16) & 0xff;
  854. ca = (cache->colors[0] >> 24) & 0xff;
  855. for (i = 0; i < count; i++) {
  856. int r,g,b;
  857. int a = nsvg__div255((int)cover[0] * ca);
  858. int ia = 255 - a;
  859. // Premultiply
  860. r = nsvg__div255(cr * a);
  861. g = nsvg__div255(cg * a);
  862. b = nsvg__div255(cb * a);
  863. // Blend over
  864. r += nsvg__div255(ia * (int)dst[0]);
  865. g += nsvg__div255(ia * (int)dst[1]);
  866. b += nsvg__div255(ia * (int)dst[2]);
  867. a += nsvg__div255(ia * (int)dst[3]);
  868. dst[0] = (unsigned char)r;
  869. dst[1] = (unsigned char)g;
  870. dst[2] = (unsigned char)b;
  871. dst[3] = (unsigned char)a;
  872. cover++;
  873. dst += 4;
  874. }
  875. } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
  876. // TODO: spread modes.
  877. // TODO: plenty of opportunities to optimize.
  878. float fx, fy, dx, gy;
  879. float* t = cache->xform;
  880. int i, cr, cg, cb, ca;
  881. unsigned int c;
  882. fx = ((float)x - tx) / sx;
  883. fy = ((float)y - ty) / sy;
  884. dx = 1.0f / sx;
  885. for (i = 0; i < count; i++) {
  886. int r,g,b,a,ia;
  887. gy = fx*t[1] + fy*t[3] + t[5];
  888. c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
  889. cr = (c) & 0xff;
  890. cg = (c >> 8) & 0xff;
  891. cb = (c >> 16) & 0xff;
  892. ca = (c >> 24) & 0xff;
  893. a = nsvg__div255((int)cover[0] * ca);
  894. ia = 255 - a;
  895. // Premultiply
  896. r = nsvg__div255(cr * a);
  897. g = nsvg__div255(cg * a);
  898. b = nsvg__div255(cb * a);
  899. // Blend over
  900. r += nsvg__div255(ia * (int)dst[0]);
  901. g += nsvg__div255(ia * (int)dst[1]);
  902. b += nsvg__div255(ia * (int)dst[2]);
  903. a += nsvg__div255(ia * (int)dst[3]);
  904. dst[0] = (unsigned char)r;
  905. dst[1] = (unsigned char)g;
  906. dst[2] = (unsigned char)b;
  907. dst[3] = (unsigned char)a;
  908. cover++;
  909. dst += 4;
  910. fx += dx;
  911. }
  912. } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {
  913. // TODO: spread modes.
  914. // TODO: plenty of opportunities to optimize.
  915. // TODO: focus (fx,fy)
  916. float fx, fy, dx, gx, gy, gd;
  917. float* t = cache->xform;
  918. int i, cr, cg, cb, ca;
  919. unsigned int c;
  920. fx = ((float)x - tx) / sx;
  921. fy = ((float)y - ty) / sy;
  922. dx = 1.0f / sx;
  923. for (i = 0; i < count; i++) {
  924. int r,g,b,a,ia;
  925. gx = fx*t[0] + fy*t[2] + t[4];
  926. gy = fx*t[1] + fy*t[3] + t[5];
  927. gd = sqrtf(gx*gx + gy*gy);
  928. c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
  929. cr = (c) & 0xff;
  930. cg = (c >> 8) & 0xff;
  931. cb = (c >> 16) & 0xff;
  932. ca = (c >> 24) & 0xff;
  933. a = nsvg__div255((int)cover[0] * ca);
  934. ia = 255 - a;
  935. // Premultiply
  936. r = nsvg__div255(cr * a);
  937. g = nsvg__div255(cg * a);
  938. b = nsvg__div255(cb * a);
  939. // Blend over
  940. r += nsvg__div255(ia * (int)dst[0]);
  941. g += nsvg__div255(ia * (int)dst[1]);
  942. b += nsvg__div255(ia * (int)dst[2]);
  943. a += nsvg__div255(ia * (int)dst[3]);
  944. dst[0] = (unsigned char)r;
  945. dst[1] = (unsigned char)g;
  946. dst[2] = (unsigned char)b;
  947. dst[3] = (unsigned char)a;
  948. cover++;
  949. dst += 4;
  950. fx += dx;
  951. }
  952. }
  953. }
  954. static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float sx, float sy, NSVGcachedPaint* cache, char fillRule)
  955. {
  956. NSVGactiveEdge *active = NULL;
  957. int y, s;
  958. int e = 0;
  959. int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline
  960. int xmin, xmax;
  961. for (y = 0; y < r->height; y++) {
  962. memset(r->scanline, 0, r->width);
  963. xmin = r->width;
  964. xmax = 0;
  965. for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
  966. // find center of pixel for this scanline
  967. float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
  968. NSVGactiveEdge **step = &active;
  969. // update all active edges;
  970. // remove all active edges that terminate before the center of this scanline
  971. while (*step) {
  972. NSVGactiveEdge *z = *step;
  973. if (z->ey <= scany) {
  974. *step = z->next; // delete from list
  975. // NSVG__assert(z->valid);
  976. nsvg__freeActive(r, z);
  977. } else {
  978. z->x += z->dx; // advance to position for current scanline
  979. step = &((*step)->next); // advance through list
  980. }
  981. }
  982. // resort the list if needed
  983. for (;;) {
  984. int changed = 0;
  985. step = &active;
  986. while (*step && (*step)->next) {
  987. if ((*step)->x > (*step)->next->x) {
  988. NSVGactiveEdge* t = *step;
  989. NSVGactiveEdge* q = t->next;
  990. t->next = q->next;
  991. q->next = t;
  992. *step = q;
  993. changed = 1;
  994. }
  995. step = &(*step)->next;
  996. }
  997. if (!changed) break;
  998. }
  999. // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
  1000. while (e < r->nedges && r->edges[e].y0 <= scany) {
  1001. if (r->edges[e].y1 > scany) {
  1002. NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
  1003. if (z == NULL) break;
  1004. // find insertion point
  1005. if (active == NULL) {
  1006. active = z;
  1007. } else if (z->x < active->x) {
  1008. // insert at front
  1009. z->next = active;
  1010. active = z;
  1011. } else {
  1012. // find thing to insert AFTER
  1013. NSVGactiveEdge* p = active;
  1014. while (p->next && p->next->x < z->x)
  1015. p = p->next;
  1016. // at this point, p->next->x is NOT < z->x
  1017. z->next = p->next;
  1018. p->next = z;
  1019. }
  1020. }
  1021. e++;
  1022. }
  1023. // now process all active edges in non-zero fashion
  1024. if (active != NULL)
  1025. nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
  1026. }
  1027. // Blit
  1028. if (xmin < 0) xmin = 0;
  1029. if (xmax > r->width-1) xmax = r->width-1;
  1030. if (xmin <= xmax) {
  1031. nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, sx, sy, cache);
  1032. }
  1033. }
  1034. }
  1035. static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)
  1036. {
  1037. int x,y;
  1038. // Unpremultiply
  1039. for (y = 0; y < h; y++) {
  1040. unsigned char *row = &image[y*stride];
  1041. for (x = 0; x < w; x++) {
  1042. int r = row[0], g = row[1], b = row[2], a = row[3];
  1043. if (a != 0) {
  1044. row[0] = (unsigned char)(r*255/a);
  1045. row[1] = (unsigned char)(g*255/a);
  1046. row[2] = (unsigned char)(b*255/a);
  1047. }
  1048. row += 4;
  1049. }
  1050. }
  1051. // Defringe
  1052. for (y = 0; y < h; y++) {
  1053. unsigned char *row = &image[y*stride];
  1054. for (x = 0; x < w; x++) {
  1055. int r = 0, g = 0, b = 0, a = row[3], n = 0;
  1056. if (a == 0) {
  1057. if (x-1 > 0 && row[-1] != 0) {
  1058. r += row[-4];
  1059. g += row[-3];
  1060. b += row[-2];
  1061. n++;
  1062. }
  1063. if (x+1 < w && row[7] != 0) {
  1064. r += row[4];
  1065. g += row[5];
  1066. b += row[6];
  1067. n++;
  1068. }
  1069. if (y-1 > 0 && row[-stride+3] != 0) {
  1070. r += row[-stride];
  1071. g += row[-stride+1];
  1072. b += row[-stride+2];
  1073. n++;
  1074. }
  1075. if (y+1 < h && row[stride+3] != 0) {
  1076. r += row[stride];
  1077. g += row[stride+1];
  1078. b += row[stride+2];
  1079. n++;
  1080. }
  1081. if (n > 0) {
  1082. row[0] = (unsigned char)(r/n);
  1083. row[1] = (unsigned char)(g/n);
  1084. row[2] = (unsigned char)(b/n);
  1085. }
  1086. }
  1087. row += 4;
  1088. }
  1089. }
  1090. }
  1091. static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)
  1092. {
  1093. int i, j;
  1094. NSVGgradient* grad;
  1095. cache->type = paint->type;
  1096. if (paint->type == NSVG_PAINT_COLOR) {
  1097. cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
  1098. return;
  1099. }
  1100. grad = paint->gradient;
  1101. cache->spread = grad->spread;
  1102. memcpy(cache->xform, grad->xform, sizeof(float)*6);
  1103. if (grad->nstops == 0) {
  1104. for (i = 0; i < 256; i++)
  1105. cache->colors[i] = 0;
  1106. } if (grad->nstops == 1) {
  1107. for (i = 0; i < 256; i++)
  1108. cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
  1109. } else {
  1110. unsigned int ca, cb = 0;
  1111. float ua, ub, du, u;
  1112. int ia, ib, count;
  1113. ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
  1114. ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
  1115. ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
  1116. ia = (int)(ua * 255.0f);
  1117. ib = (int)(ub * 255.0f);
  1118. for (i = 0; i < ia; i++) {
  1119. cache->colors[i] = ca;
  1120. }
  1121. for (i = 0; i < grad->nstops-1; i++) {
  1122. ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
  1123. cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
  1124. ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
  1125. ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
  1126. ia = (int)(ua * 255.0f);
  1127. ib = (int)(ub * 255.0f);
  1128. count = ib - ia;
  1129. if (count <= 0) continue;
  1130. u = 0;
  1131. du = 1.0f / (float)count;
  1132. for (j = 0; j < count; j++) {
  1133. cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
  1134. u += du;
  1135. }
  1136. }
  1137. for (i = ib; i < 256; i++)
  1138. cache->colors[i] = cb;
  1139. }
  1140. }
  1141. /*
  1142. static void dumpEdges(NSVGrasterizer* r, const char* name)
  1143. {
  1144. float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
  1145. NSVGedge *e = NULL;
  1146. int i;
  1147. if (r->nedges == 0) return;
  1148. FILE* fp = fopen(name, "w");
  1149. if (fp == NULL) return;
  1150. xmin = xmax = r->edges[0].x0;
  1151. ymin = ymax = r->edges[0].y0;
  1152. for (i = 0; i < r->nedges; i++) {
  1153. e = &r->edges[i];
  1154. xmin = nsvg__minf(xmin, e->x0);
  1155. xmin = nsvg__minf(xmin, e->x1);
  1156. xmax = nsvg__maxf(xmax, e->x0);
  1157. xmax = nsvg__maxf(xmax, e->x1);
  1158. ymin = nsvg__minf(ymin, e->y0);
  1159. ymin = nsvg__minf(ymin, e->y1);
  1160. ymax = nsvg__maxf(ymax, e->y0);
  1161. ymax = nsvg__maxf(ymax, e->y1);
  1162. }
  1163. fprintf(fp, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));
  1164. for (i = 0; i < r->nedges; i++) {
  1165. e = &r->edges[i];
  1166. fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);
  1167. }
  1168. for (i = 0; i < r->npoints; i++) {
  1169. if (i+1 < r->npoints)
  1170. 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);
  1171. 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");
  1172. }
  1173. fprintf(fp, "</svg>");
  1174. fclose(fp);
  1175. }
  1176. */
  1177. void nsvgAltRasterize(NSVGrasterizer* r,
  1178. NSVGimage* image, float tx, float ty,
  1179. float sx, float sy,
  1180. unsigned char* dst, int w, int h, int stride)
  1181. {
  1182. NSVGshape *shape = NULL;
  1183. NSVGedge *e = NULL;
  1184. NSVGcachedPaint cache;
  1185. int i;
  1186. r->bitmap = dst;
  1187. r->width = w;
  1188. r->height = h;
  1189. r->stride = stride;
  1190. if (w > r->cscanline) {
  1191. r->cscanline = w;
  1192. r->scanline = (unsigned char*)realloc(r->scanline, w);
  1193. if (r->scanline == NULL) return;
  1194. }
  1195. for (i = 0; i < h; i++)
  1196. memset(&dst[i*stride], 0, w*4);
  1197. for (shape = image->shapes; shape != NULL; shape = shape->next) {
  1198. if (!(shape->flags & NSVG_FLAGS_VISIBLE))
  1199. continue;
  1200. if (shape->fill.type != NSVG_PAINT_NONE) {
  1201. nsvg__resetPool(r);
  1202. r->freelist = NULL;
  1203. r->nedges = 0;
  1204. nsvg__flattenShape(r, shape, sx, sy);
  1205. // Scale and translate edges
  1206. for (i = 0; i < r->nedges; i++) {
  1207. e = &r->edges[i];
  1208. e->x0 = tx + e->x0;
  1209. e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
  1210. e->x1 = tx + e->x1;
  1211. e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
  1212. }
  1213. // Rasterize edges
  1214. qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
  1215. // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
  1216. nsvg__initPaint(&cache, &shape->fill, shape->opacity);
  1217. nsvg__rasterizeSortedEdges(r, tx,ty, sx, sy, &cache, shape->fillRule);
  1218. }
  1219. if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * sx) > 0.01f) {
  1220. nsvg__resetPool(r);
  1221. r->freelist = NULL;
  1222. r->nedges = 0;
  1223. nsvg__flattenShapeStroke(r, shape, sx, sy);
  1224. // dumpEdges(r, "edge.svg");
  1225. // Scale and translate edges
  1226. for (i = 0; i < r->nedges; i++) {
  1227. e = &r->edges[i];
  1228. e->x0 = tx + e->x0;
  1229. e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
  1230. e->x1 = tx + e->x1;
  1231. e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
  1232. }
  1233. // Rasterize edges
  1234. qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
  1235. // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
  1236. nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
  1237. nsvg__rasterizeSortedEdges(r, tx,ty,sx, sy, &cache, NSVG_FILLRULE_NONZERO);
  1238. }
  1239. }
  1240. nsvg__unpremultiplyAlpha(dst, w, h, stride);
  1241. r->bitmap = NULL;
  1242. r->width = 0;
  1243. r->height = 0;
  1244. r->stride = 0;
  1245. }
  1246. void nsvgRasterize(NSVGrasterizer* r,
  1247. NSVGimage* image, float tx, float ty, float scale,
  1248. unsigned char* dst, int w, int h, int stride)
  1249. {
  1250. nsvgAltRasterize(r,image, tx, ty, scale, scale, dst, w, h, stride);
  1251. }
  1252. #endif // NANOSVGRAST_IMPLEMENTATION
  1253. //
  1254. // End of "$Id: altsvgrast.h 12415 2017-09-03 13:20:52Z manolo $".
  1255. //