nanosvgrast.h 37 KB

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