draw-path.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619
  1. // Copyright (C) 2004-2025 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include "draw-imp.h"
  24. #include <math.h>
  25. #include <float.h>
  26. #include <assert.h>
  27. #define MAX_DEPTH 8
  28. /*
  29. When stroking/filling, we now label the edges as we emit them.
  30. For filling, we walk the outline of the shape in order, so everything
  31. is labelled as '0'.
  32. For stroking, we walk up both sides of the stroke at once; the forward
  33. side (0), and the reverse side (1). When we get to the top, either
  34. both sides join back to where they started, or we cap them.
  35. The start cap is labelled 2, the end cap is labelled 0.
  36. These labels are ignored for edge based rasterization, but are required
  37. for edgebuffer based rasterization.
  38. Consider the following simplified ascii art diagram of a stroke from
  39. left to right with 3 sections.
  40. | 0 0 0
  41. | +----->-----+----->-----+----->-----+
  42. | | |
  43. | ^ 2 A B C v 0
  44. | | |
  45. | +-----<-----+-----<-----+-----<-----+
  46. | 1 1 1
  47. Edge 0 is sent in order (the top edge of A then B then C, left to right
  48. in the above diagram). Edge 1 is sent in reverse order (the bottom edge
  49. of A then B then C, still left to right in the above diagram, even though
  50. the sense of the line is right to left).
  51. Finally any caps required are sent, 0 and 2.
  52. It would be nicer if we could roll edge 2 into edge 1, but to do that
  53. we'd need to know in advance if a stroke was closed or not, so we have
  54. special case code in the edgebuffer based rasterizer to cope with this.
  55. */
  56. static void
  57. line(fz_context *ctx, fz_rasterizer *rast, fz_matrix ctm, float x0, float y0, float x1, float y1)
  58. {
  59. float tx0 = ctm.a * x0 + ctm.c * y0 + ctm.e;
  60. float ty0 = ctm.b * x0 + ctm.d * y0 + ctm.f;
  61. float tx1 = ctm.a * x1 + ctm.c * y1 + ctm.e;
  62. float ty1 = ctm.b * x1 + ctm.d * y1 + ctm.f;
  63. fz_insert_rasterizer(ctx, rast, tx0, ty0, tx1, ty1, 0);
  64. }
  65. static void
  66. bezier(fz_context *ctx, fz_rasterizer *rast, fz_matrix ctm, float flatness,
  67. float xa, float ya,
  68. float xb, float yb,
  69. float xc, float yc,
  70. float xd, float yd, int depth)
  71. {
  72. float dmax;
  73. float xab, yab;
  74. float xbc, ybc;
  75. float xcd, ycd;
  76. float xabc, yabc;
  77. float xbcd, ybcd;
  78. float xabcd, yabcd;
  79. /* termination check */
  80. dmax = fz_abs(xa - xb);
  81. dmax = fz_max(dmax, fz_abs(ya - yb));
  82. dmax = fz_max(dmax, fz_abs(xd - xc));
  83. dmax = fz_max(dmax, fz_abs(yd - yc));
  84. if (dmax < flatness || depth >= MAX_DEPTH)
  85. {
  86. line(ctx, rast, ctm, xa, ya, xd, yd);
  87. return;
  88. }
  89. xab = xa + xb;
  90. yab = ya + yb;
  91. xbc = xb + xc;
  92. ybc = yb + yc;
  93. xcd = xc + xd;
  94. ycd = yc + yd;
  95. xabc = xab + xbc;
  96. yabc = yab + ybc;
  97. xbcd = xbc + xcd;
  98. ybcd = ybc + ycd;
  99. xabcd = xabc + xbcd;
  100. yabcd = yabc + ybcd;
  101. xab *= 0.5f; yab *= 0.5f;
  102. /* xbc *= 0.5f; ybc *= 0.5f; */
  103. xcd *= 0.5f; ycd *= 0.5f;
  104. xabc *= 0.25f; yabc *= 0.25f;
  105. xbcd *= 0.25f; ybcd *= 0.25f;
  106. xabcd *= 0.125f; yabcd *= 0.125f;
  107. bezier(ctx, rast, ctm, flatness, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1);
  108. bezier(ctx, rast, ctm, flatness, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1);
  109. }
  110. static void
  111. quad(fz_context *ctx, fz_rasterizer *rast, fz_matrix ctm, float flatness,
  112. float xa, float ya,
  113. float xb, float yb,
  114. float xc, float yc, int depth)
  115. {
  116. float dmax;
  117. float xab, yab;
  118. float xbc, ybc;
  119. float xabc, yabc;
  120. /* termination check */
  121. dmax = fz_abs(xa - xb);
  122. dmax = fz_max(dmax, fz_abs(ya - yb));
  123. dmax = fz_max(dmax, fz_abs(xc - xb));
  124. dmax = fz_max(dmax, fz_abs(yc - yb));
  125. if (dmax < flatness || depth >= MAX_DEPTH)
  126. {
  127. line(ctx, rast, ctm, xa, ya, xc, yc);
  128. return;
  129. }
  130. xab = xa + xb;
  131. yab = ya + yb;
  132. xbc = xb + xc;
  133. ybc = yb + yc;
  134. xabc = xab + xbc;
  135. yabc = yab + ybc;
  136. xab *= 0.5f; yab *= 0.5f;
  137. xbc *= 0.5f; ybc *= 0.5f;
  138. xabc *= 0.25f; yabc *= 0.25f;
  139. quad(ctx, rast, ctm, flatness, xa, ya, xab, yab, xabc, yabc, depth + 1);
  140. quad(ctx, rast, ctm, flatness, xabc, yabc, xbc, ybc, xc, yc, depth + 1);
  141. }
  142. typedef struct
  143. {
  144. fz_rasterizer *rast;
  145. fz_matrix ctm;
  146. float flatness;
  147. fz_point b;
  148. fz_point c;
  149. }
  150. flatten_arg;
  151. static void
  152. flatten_moveto(fz_context *ctx, void *arg_, float x, float y)
  153. {
  154. flatten_arg *arg = (flatten_arg *)arg_;
  155. /* implicit closepath before moveto */
  156. if (arg->c.x != arg->b.x || arg->c.y != arg->b.y)
  157. line(ctx, arg->rast, arg->ctm, arg->c.x, arg->c.y, arg->b.x, arg->b.y);
  158. arg->c.x = arg->b.x = x;
  159. arg->c.y = arg->b.y = y;
  160. fz_gap_rasterizer(ctx, arg->rast);
  161. }
  162. static void
  163. flatten_lineto(fz_context *ctx, void *arg_, float x, float y)
  164. {
  165. flatten_arg *arg = (flatten_arg *)arg_;
  166. line(ctx, arg->rast, arg->ctm, arg->c.x, arg->c.y, x, y);
  167. arg->c.x = x;
  168. arg->c.y = y;
  169. }
  170. static void
  171. flatten_curveto(fz_context *ctx, void *arg_, float x1, float y1, float x2, float y2, float x3, float y3)
  172. {
  173. flatten_arg *arg = (flatten_arg *)arg_;
  174. bezier(ctx, arg->rast, arg->ctm, arg->flatness, arg->c.x, arg->c.y, x1, y1, x2, y2, x3, y3, 0);
  175. arg->c.x = x3;
  176. arg->c.y = y3;
  177. }
  178. static void
  179. flatten_quadto(fz_context *ctx, void *arg_, float x1, float y1, float x2, float y2)
  180. {
  181. flatten_arg *arg = (flatten_arg *)arg_;
  182. quad(ctx, arg->rast, arg->ctm, arg->flatness, arg->c.x, arg->c.y, x1, y1, x2, y2, 0);
  183. arg->c.x = x2;
  184. arg->c.y = y2;
  185. }
  186. static void
  187. flatten_close(fz_context *ctx, void *arg_)
  188. {
  189. flatten_arg *arg = (flatten_arg *)arg_;
  190. line(ctx, arg->rast, arg->ctm, arg->c.x, arg->c.y, arg->b.x, arg->b.y);
  191. arg->c.x = arg->b.x;
  192. arg->c.y = arg->b.y;
  193. }
  194. static void
  195. flatten_rectto(fz_context *ctx, void *arg_, float x0, float y0, float x1, float y1)
  196. {
  197. flatten_arg *arg = (flatten_arg *)arg_;
  198. fz_matrix ctm = arg->ctm;
  199. flatten_moveto(ctx, arg_, x0, y0);
  200. if (fz_antidropout_rasterizer(ctx, arg->rast))
  201. {
  202. /* In the case where we have an axis aligned rectangle, do some
  203. * horrid antidropout stuff. */
  204. if (ctm.b == 0 && ctm.c == 0)
  205. {
  206. float tx0 = ctm.a * x0 + ctm.e;
  207. float ty0 = ctm.d * y0 + ctm.f;
  208. float tx1 = ctm.a * x1 + ctm.e;
  209. float ty1 = ctm.d * y1 + ctm.f;
  210. fz_insert_rasterizer_rect(ctx, arg->rast, tx0, ty0, tx1, ty1);
  211. return;
  212. }
  213. else if (ctm.a == 0 && ctm.d == 0)
  214. {
  215. float tx0 = ctm.c * y0 + ctm.e;
  216. float ty0 = ctm.b * x0 + ctm.f;
  217. float tx1 = ctm.c * y1 + ctm.e;
  218. float ty1 = ctm.b * x1 + ctm.f;
  219. fz_insert_rasterizer_rect(ctx, arg->rast, tx0, ty1, tx1, ty0);
  220. return;
  221. }
  222. }
  223. flatten_lineto(ctx, arg_, x1, y0);
  224. flatten_lineto(ctx, arg_, x1, y1);
  225. flatten_lineto(ctx, arg_, x0, y1);
  226. flatten_close(ctx, arg_);
  227. }
  228. static const fz_path_walker flatten_proc =
  229. {
  230. flatten_moveto,
  231. flatten_lineto,
  232. flatten_curveto,
  233. flatten_close,
  234. flatten_quadto,
  235. NULL,
  236. NULL,
  237. flatten_rectto
  238. };
  239. static int
  240. do_flatten_fill(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, fz_matrix ctm, float flatness)
  241. {
  242. flatten_arg arg;
  243. arg.rast = rast;
  244. arg.ctm = ctm;
  245. arg.flatness = flatness;
  246. arg.b.x = arg.b.y = arg.c.x = arg.c.y = 0;
  247. fz_walk_path(ctx, path, &flatten_proc, &arg);
  248. if (arg.c.x != arg.b.x || arg.c.y != arg.b.y)
  249. line(ctx, rast, ctm, arg.c.x, arg.c.y, arg.b.x, arg.b.y);
  250. fz_gap_rasterizer(ctx, rast);
  251. return fz_is_empty_irect(fz_bound_rasterizer(ctx, rast));
  252. }
  253. int
  254. fz_flatten_fill_path(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, fz_matrix ctm, float flatness, fz_irect scissor, fz_irect *bbox)
  255. {
  256. int empty;
  257. fz_irect local_bbox;
  258. if (!bbox)
  259. bbox = &local_bbox;
  260. /* If we're given an empty scissor, sanitize it. This makes life easier
  261. * down the line. */
  262. if (fz_is_empty_irect(scissor))
  263. scissor.x1 = scissor.x0, scissor.y1 = scissor.y0;
  264. if (fz_reset_rasterizer(ctx, rast, scissor))
  265. {
  266. empty = do_flatten_fill(ctx, rast, path, ctm, flatness);
  267. if (empty)
  268. return *bbox = fz_empty_irect, 1;
  269. fz_postindex_rasterizer(ctx, rast);
  270. }
  271. empty = do_flatten_fill(ctx, rast, path, ctm, flatness);
  272. if (empty)
  273. return *bbox = fz_empty_irect, 1;
  274. *bbox = fz_intersect_irect(scissor, fz_bound_rasterizer(ctx, rast));
  275. return fz_is_empty_irect(*bbox);
  276. }
  277. typedef struct sctx
  278. {
  279. fz_rasterizer *rast;
  280. fz_matrix ctm;
  281. float flatness;
  282. const fz_stroke_state *stroke;
  283. int linejoin;
  284. float linewidth;
  285. float miterlimit;
  286. fz_point beg[2];
  287. fz_point seg[2];
  288. int sn;
  289. int not_just_moves;
  290. int from_bezier;
  291. fz_point cur;
  292. fz_rect rect;
  293. const float *dash_list;
  294. float dash_phase;
  295. int dash_len;
  296. float dash_total;
  297. int toggle, cap;
  298. int offset;
  299. float phase;
  300. fz_point dash_cur;
  301. fz_point dash_beg;
  302. float dirn_x;
  303. float dirn_y;
  304. } sctx;
  305. static void
  306. fz_add_line(fz_context *ctx, sctx *s, float x0, float y0, float x1, float y1, int rev)
  307. {
  308. float tx0 = s->ctm.a * x0 + s->ctm.c * y0 + s->ctm.e;
  309. float ty0 = s->ctm.b * x0 + s->ctm.d * y0 + s->ctm.f;
  310. float tx1 = s->ctm.a * x1 + s->ctm.c * y1 + s->ctm.e;
  311. float ty1 = s->ctm.b * x1 + s->ctm.d * y1 + s->ctm.f;
  312. fz_insert_rasterizer(ctx, s->rast, tx0, ty0, tx1, ty1, rev);
  313. }
  314. static void
  315. fz_add_horiz_rect(fz_context *ctx, sctx *s, float x0, float y0, float x1, float y1)
  316. {
  317. if (fz_antidropout_rasterizer(ctx, s->rast)) {
  318. if (s->ctm.b == 0 && s->ctm.c == 0)
  319. {
  320. float tx0 = s->ctm.a * x0 + s->ctm.e;
  321. float ty0 = s->ctm.d * y0 + s->ctm.f;
  322. float tx1 = s->ctm.a * x1 + s->ctm.e;
  323. float ty1 = s->ctm.d * y1 + s->ctm.f;
  324. fz_insert_rasterizer_rect(ctx, s->rast, tx1, ty1, tx0, ty0);
  325. return;
  326. }
  327. else if (s->ctm.a == 0 && s->ctm.d == 0)
  328. {
  329. float tx0 = s->ctm.c * y0 + s->ctm.e;
  330. float ty0 = s->ctm.b * x0 + s->ctm.f;
  331. float tx1 = s->ctm.c * y1 + s->ctm.e;
  332. float ty1 = s->ctm.b * x1 + s->ctm.f;
  333. fz_insert_rasterizer_rect(ctx, s->rast, tx1, ty0, tx0, ty1);
  334. return;
  335. }
  336. }
  337. fz_add_line(ctx, s, x0, y0, x1, y0, 0);
  338. fz_add_line(ctx, s, x1, y1, x0, y1, 1);
  339. }
  340. static void
  341. fz_add_vert_rect(fz_context *ctx, sctx *s, float x0, float y0, float x1, float y1)
  342. {
  343. if (fz_antidropout_rasterizer(ctx, s->rast))
  344. {
  345. if (s->ctm.b == 0 && s->ctm.c == 0)
  346. {
  347. float tx0 = s->ctm.a * x0 + s->ctm.e;
  348. float ty0 = s->ctm.d * y0 + s->ctm.f;
  349. float tx1 = s->ctm.a * x1 + s->ctm.e;
  350. float ty1 = s->ctm.d * y1 + s->ctm.f;
  351. fz_insert_rasterizer_rect(ctx, s->rast, tx0, ty1, tx1, ty0);
  352. return;
  353. }
  354. else if (s->ctm.a == 0 && s->ctm.d == 0)
  355. {
  356. float tx0 = s->ctm.c * y0 + s->ctm.e;
  357. float ty0 = s->ctm.b * x0 + s->ctm.f;
  358. float tx1 = s->ctm.c * y1 + s->ctm.e;
  359. float ty1 = s->ctm.b * x1 + s->ctm.f;
  360. fz_insert_rasterizer_rect(ctx, s->rast, tx0, ty0, tx1, ty1);
  361. return;
  362. }
  363. }
  364. fz_add_line(ctx, s, x1, y0, x0, y0, 0);
  365. fz_add_line(ctx, s, x0, y1, x1, y1, 1);
  366. }
  367. static void
  368. fz_add_arc(fz_context *ctx, sctx *s,
  369. float xc, float yc,
  370. float x0, float y0,
  371. float x1, float y1,
  372. int rev)
  373. {
  374. float th0, th1, r;
  375. float theta;
  376. float ox, oy, nx, ny;
  377. int n, i;
  378. r = fabsf(s->linewidth);
  379. theta = 2 * FZ_SQRT2 * sqrtf(s->flatness / r);
  380. th0 = atan2f(y0, x0);
  381. th1 = atan2f(y1, x1);
  382. if (r > 0)
  383. {
  384. if (th0 < th1)
  385. th0 += FZ_PI * 2;
  386. n = ceilf((th0 - th1) / theta);
  387. }
  388. else
  389. {
  390. if (th1 < th0)
  391. th1 += FZ_PI * 2;
  392. n = ceilf((th1 - th0) / theta);
  393. }
  394. if (rev)
  395. {
  396. ox = x1;
  397. oy = y1;
  398. for (i = n-1; i > 0; i--)
  399. {
  400. theta = th0 + (th1 - th0) * i / n;
  401. nx = cosf(theta) * r;
  402. ny = sinf(theta) * r;
  403. fz_add_line(ctx, s, xc + nx, yc + ny, xc + ox, yc + oy, rev);
  404. ox = nx;
  405. oy = ny;
  406. }
  407. fz_add_line(ctx, s, xc + x0, yc + y0, xc + ox, yc + oy, rev);
  408. }
  409. else
  410. {
  411. ox = x0;
  412. oy = y0;
  413. for (i = 1; i < n; i++)
  414. {
  415. theta = th0 + (th1 - th0) * i / n;
  416. nx = cosf(theta) * r;
  417. ny = sinf(theta) * r;
  418. fz_add_line(ctx, s, xc + ox, yc + oy, xc + nx, yc + ny, rev);
  419. ox = nx;
  420. oy = ny;
  421. }
  422. fz_add_line(ctx, s, xc + ox, yc + oy, xc + x1, yc + y1, rev);
  423. }
  424. }
  425. /* FLT_TINY * FLT_TINY is approximately FLT_EPSILON */
  426. #define FLT_TINY 3.4e-4F
  427. static int find_normal_vectors(float dx, float dy, float linewidth, float *dlx, float *dly)
  428. {
  429. if (dx == 0)
  430. {
  431. if (dy < FLT_TINY && dy > - FLT_TINY)
  432. goto tiny;
  433. else if (dy > 0)
  434. *dlx = linewidth;
  435. else
  436. *dlx = -linewidth;
  437. *dly = 0;
  438. }
  439. else if (dy == 0)
  440. {
  441. if (dx < FLT_TINY && dx > - FLT_TINY)
  442. goto tiny;
  443. else if (dx > 0)
  444. *dly = -linewidth;
  445. else
  446. *dly = linewidth;
  447. *dlx = 0;
  448. }
  449. else
  450. {
  451. float sq = dx * dx + dy * dy;
  452. float scale;
  453. if (sq < FLT_EPSILON)
  454. goto tiny;
  455. scale = linewidth / sqrtf(sq);
  456. *dlx = dy * scale;
  457. *dly = -dx * scale;
  458. }
  459. return 0;
  460. tiny:
  461. *dlx = 0;
  462. *dly = 0;
  463. return 1;
  464. }
  465. static void
  466. fz_add_line_join(fz_context *ctx, sctx *s, float ax, float ay, float bx, float by, float cx, float cy, int join_under)
  467. {
  468. float miterlimit = s->miterlimit;
  469. float linewidth = s->linewidth;
  470. fz_linejoin linejoin = s->linejoin;
  471. float dx0, dy0;
  472. float dx1, dy1;
  473. float dlx0, dly0;
  474. float dlx1, dly1;
  475. float dmx, dmy;
  476. float dmr2;
  477. float scale;
  478. float cross;
  479. int rev = 0;
  480. dx0 = bx - ax;
  481. dy0 = by - ay;
  482. dx1 = cx - bx;
  483. dy1 = cy - by;
  484. cross = dx1 * dy0 - dx0 * dy1;
  485. /* Ensure that cross >= 0 */
  486. if (cross < 0)
  487. {
  488. float tmp;
  489. tmp = dx1; dx1 = -dx0; dx0 = -tmp;
  490. tmp = dy1; dy1 = -dy0; dy0 = -tmp;
  491. cross = -cross;
  492. rev = !rev;
  493. }
  494. if (find_normal_vectors(dx0, dy0, linewidth, &dlx0, &dly0))
  495. linejoin = FZ_LINEJOIN_BEVEL;
  496. if (find_normal_vectors(dx1, dy1, linewidth, &dlx1, &dly1))
  497. linejoin = FZ_LINEJOIN_BEVEL;
  498. dmx = (dlx0 + dlx1) * 0.5f;
  499. dmy = (dly0 + dly1) * 0.5f;
  500. dmr2 = dmx * dmx + dmy * dmy;
  501. if (cross * cross < FLT_EPSILON && dx0 * dx1 + dy0 * dy1 >= 0)
  502. linejoin = FZ_LINEJOIN_BEVEL;
  503. /* XPS miter joins are clipped at miterlength, rather than simply
  504. * being converted to bevelled joins. */
  505. if (linejoin == FZ_LINEJOIN_MITER_XPS)
  506. {
  507. if (cross == 0)
  508. linejoin = FZ_LINEJOIN_BEVEL;
  509. else if (dmr2 * miterlimit * miterlimit >= linewidth * linewidth)
  510. linejoin = FZ_LINEJOIN_MITER;
  511. }
  512. else if (linejoin == FZ_LINEJOIN_MITER)
  513. if (dmr2 * miterlimit * miterlimit < linewidth * linewidth)
  514. linejoin = FZ_LINEJOIN_BEVEL;
  515. if (join_under)
  516. {
  517. fz_add_line(ctx, s, bx + dlx1, by + dly1, bx + dlx0, by + dly0, !rev);
  518. }
  519. else if (rev)
  520. {
  521. fz_add_line(ctx, s, bx + dlx1, by + dly1, bx, by, 0);
  522. fz_add_line(ctx, s, bx, by, bx + dlx0, by + dly0, 0);
  523. }
  524. else
  525. {
  526. fz_add_line(ctx, s, bx, by, bx + dlx0, by + dly0, 1);
  527. fz_add_line(ctx, s, bx + dlx1, by + dly1, bx, by, 1);
  528. }
  529. switch (linejoin)
  530. {
  531. case FZ_LINEJOIN_MITER_XPS:
  532. {
  533. float k, t0x, t0y, t1x, t1y;
  534. scale = linewidth * linewidth / dmr2;
  535. dmx *= scale;
  536. dmy *= scale;
  537. k = (scale - linewidth * miterlimit / sqrtf(dmr2)) / (scale - 1);
  538. t0x = bx - dmx + k * (dmx - dlx0);
  539. t0y = by - dmy + k * (dmy - dly0);
  540. t1x = bx - dmx + k * (dmx - dlx1);
  541. t1y = by - dmy + k * (dmy - dly1);
  542. if (rev)
  543. {
  544. fz_add_line(ctx, s, t1x, t1y, bx - dlx1, by - dly1, 1);
  545. fz_add_line(ctx, s, t0x, t0y, t1x, t1y, 1);
  546. fz_add_line(ctx, s, bx - dlx0, by - dly0, t0x, t0y, 1);
  547. }
  548. else
  549. {
  550. fz_add_line(ctx, s, bx - dlx0, by - dly0, t0x, t0y, 0);
  551. fz_add_line(ctx, s, t0x, t0y, t1x, t1y, 0);
  552. fz_add_line(ctx, s, t1x, t1y, bx - dlx1, by - dly1, 0);
  553. }
  554. break;
  555. }
  556. case FZ_LINEJOIN_MITER:
  557. scale = linewidth * linewidth / dmr2;
  558. dmx *= scale;
  559. dmy *= scale;
  560. if (rev)
  561. {
  562. fz_add_line(ctx, s, bx - dmx, by - dmy, bx - dlx1, by - dly1, 1);
  563. fz_add_line(ctx, s, bx - dlx0, by - dly0, bx - dmx, by - dmy, 1);
  564. }
  565. else
  566. {
  567. fz_add_line(ctx, s, bx - dlx0, by - dly0, bx - dmx, by - dmy, 0);
  568. fz_add_line(ctx, s, bx - dmx, by - dmy, bx - dlx1, by - dly1, 0);
  569. }
  570. break;
  571. case FZ_LINEJOIN_BEVEL:
  572. fz_add_line(ctx, s, bx - dlx0, by - dly0, bx - dlx1, by - dly1, rev);
  573. break;
  574. case FZ_LINEJOIN_ROUND:
  575. fz_add_arc(ctx, s, bx, by, -dlx0, -dly0, -dlx1, -dly1, rev);
  576. break;
  577. default:
  578. assert("Invalid line join" == NULL);
  579. }
  580. }
  581. static void
  582. do_linecap(fz_context *ctx, sctx *s, float bx, float by, fz_linecap linecap, int rev, float dlx, float dly)
  583. {
  584. float flatness = s->flatness;
  585. float linewidth = s->linewidth;
  586. switch (linecap)
  587. {
  588. case FZ_LINECAP_BUTT:
  589. fz_add_line(ctx, s, bx - dlx, by - dly, bx + dlx, by + dly, rev);
  590. break;
  591. case FZ_LINECAP_ROUND:
  592. {
  593. int i;
  594. int n = ceilf(FZ_PI / (2.0f * FZ_SQRT2 * sqrtf(flatness / linewidth)));
  595. float ox = bx - dlx;
  596. float oy = by - dly;
  597. for (i = 1; i < n; i++)
  598. {
  599. float theta = FZ_PI * i / n;
  600. float cth = cosf(theta);
  601. float sth = sinf(theta);
  602. float nx = bx - dlx * cth - dly * sth;
  603. float ny = by - dly * cth + dlx * sth;
  604. fz_add_line(ctx, s, ox, oy, nx, ny, rev);
  605. ox = nx;
  606. oy = ny;
  607. }
  608. fz_add_line(ctx, s, ox, oy, bx + dlx, by + dly, rev);
  609. break;
  610. }
  611. case FZ_LINECAP_SQUARE:
  612. fz_add_line(ctx, s, bx - dlx, by - dly,
  613. bx - dlx - dly, by - dly + dlx, rev);
  614. fz_add_line(ctx, s, bx - dlx - dly, by - dly + dlx,
  615. bx + dlx - dly, by + dly + dlx, rev);
  616. fz_add_line(ctx, s, bx + dlx - dly, by + dly + dlx,
  617. bx + dlx, by + dly, rev);
  618. break;
  619. case FZ_LINECAP_TRIANGLE:
  620. {
  621. float mx = -dly;
  622. float my = dlx;
  623. fz_add_line(ctx, s, bx - dlx, by - dly, bx + mx, by + my, rev);
  624. fz_add_line(ctx, s, bx + mx, by + my, bx + dlx, by + dly, rev);
  625. break;
  626. }
  627. default:
  628. assert("Invalid line cap" == NULL);
  629. }
  630. }
  631. static void
  632. fz_add_line_cap(fz_context *ctx, sctx *s, float ax, float ay, float bx, float by, fz_linecap linecap, int rev)
  633. {
  634. float linewidth = s->linewidth;
  635. float dx = bx - ax;
  636. float dy = by - ay;
  637. float scale = linewidth / sqrtf(dx * dx + dy * dy);
  638. float dlx = dy * scale;
  639. float dly = -dx * scale;
  640. do_linecap(ctx, s, bx, by, linecap, rev, dlx, dly);
  641. }
  642. static void
  643. fz_add_zero_len_cap(fz_context *ctx, sctx *s, float ax, float ay, fz_linecap linecap, int rev)
  644. {
  645. float linewidth = s->linewidth;
  646. float dx = rev ? -s->dirn_x : s->dirn_x;
  647. float dy = rev ? -s->dirn_y : s->dirn_y;
  648. float scale, dlx, dly;
  649. if (dx == 0 && dy == 0)
  650. return;
  651. scale = linewidth / sqrtf(dx * dx + dy * dy);
  652. dlx = dy * scale;
  653. dly = -dx * scale;
  654. do_linecap(ctx, s, ax, ay, linecap, rev, dlx, dly);
  655. }
  656. static void
  657. fz_add_line_dot(fz_context *ctx, sctx *s, float ax, float ay)
  658. {
  659. float flatness = s->flatness;
  660. float linewidth = s->linewidth;
  661. int n = ceilf(FZ_PI / (FZ_SQRT2 * sqrtf(flatness / linewidth)));
  662. float ox = ax - linewidth;
  663. float oy = ay;
  664. int i;
  665. if (n < 3)
  666. n = 3;
  667. for (i = 1; i < n; i++)
  668. {
  669. float theta = FZ_PI * 2 * i / n;
  670. float cth = cosf(theta);
  671. float sth = sinf(theta);
  672. float nx = ax - cth * linewidth;
  673. float ny = ay + sth * linewidth;
  674. fz_add_line(ctx, s, ox, oy, nx, ny, 0);
  675. ox = nx;
  676. oy = ny;
  677. }
  678. fz_add_line(ctx, s, ox, oy, ax - linewidth, ay, 0);
  679. }
  680. static void
  681. fz_stroke_flush(fz_context *ctx, sctx *s, fz_linecap start_cap, fz_linecap end_cap)
  682. {
  683. if (s->sn == 1)
  684. {
  685. fz_add_line_cap(ctx, s, s->beg[1].x, s->beg[1].y, s->beg[0].x, s->beg[0].y, start_cap, 2);
  686. fz_add_line_cap(ctx, s, s->seg[0].x, s->seg[0].y, s->seg[1].x, s->seg[1].y, end_cap, 0);
  687. }
  688. else if (s->not_just_moves)
  689. {
  690. if (s->cap == FZ_LINECAP_ROUND)
  691. {
  692. fz_add_line_dot(ctx, s, s->beg[0].x, s->beg[0].y);
  693. }
  694. else
  695. {
  696. fz_add_zero_len_cap(ctx, s, s->beg[0].x, s->beg[0].y, s->cap, 2);
  697. fz_add_zero_len_cap(ctx, s, s->beg[0].x, s->beg[0].y, s->cap, 0);
  698. }
  699. }
  700. fz_gap_rasterizer(ctx, s->rast);
  701. }
  702. static void
  703. fz_stroke_moveto(fz_context *ctx, void *s_, float x, float y)
  704. {
  705. struct sctx *s = (struct sctx *)s_;
  706. s->seg[0].x = s->beg[0].x = x;
  707. s->seg[0].y = s->beg[0].y = y;
  708. s->sn = 0;
  709. s->not_just_moves = 0;
  710. s->from_bezier = 0;
  711. s->dirn_x = 0;
  712. s->dirn_y = 0;
  713. }
  714. static void
  715. fz_stroke_lineto_aux(fz_context *ctx, sctx *s, float x, float y, int from_bezier, float dirn_x, float dirn_y)
  716. {
  717. float ox = s->seg[s->sn].x;
  718. float oy = s->seg[s->sn].y;
  719. float dx = x - ox;
  720. float dy = y - oy;
  721. float dlx, dly;
  722. s->not_just_moves = 1;
  723. /* We store the direction (as used for the alignment of caps etc) based on the
  724. * direction we are passed in. */
  725. s->dirn_x = dirn_x;
  726. s->dirn_y = dirn_y;
  727. /* We calculate the normal vectors from the delta that we have just moved. */
  728. if (find_normal_vectors(dx, dy, s->linewidth, &dlx, &dly))
  729. {
  730. return;
  731. }
  732. if (s->sn == 1)
  733. fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, ox, oy, x, y, s->from_bezier & from_bezier);
  734. #if 1
  735. if (0 && dx == 0)
  736. {
  737. fz_add_vert_rect(ctx, s, ox - dlx, oy, x + dlx, y);
  738. }
  739. else if (dy == 0)
  740. {
  741. fz_add_horiz_rect(ctx, s, ox, oy - dly, x, y + dly);
  742. }
  743. else
  744. #endif
  745. {
  746. fz_add_line(ctx, s, ox - dlx, oy - dly, x - dlx, y - dly, 0);
  747. fz_add_line(ctx, s, x + dlx, y + dly, ox + dlx, oy + dly, 1);
  748. }
  749. if (s->sn)
  750. {
  751. s->seg[0] = s->seg[1];
  752. s->seg[1].x = x;
  753. s->seg[1].y = y;
  754. }
  755. else
  756. {
  757. s->seg[1].x = s->beg[1].x = x;
  758. s->seg[1].y = s->beg[1].y = y;
  759. s->sn = 1;
  760. }
  761. s->from_bezier = from_bezier;
  762. }
  763. static void
  764. fz_stroke_lineto(fz_context *ctx, sctx *s, float x, float y, int from_bezier)
  765. {
  766. float ox = s->seg[s->sn].x;
  767. float oy = s->seg[s->sn].y;
  768. float dx = x - ox;
  769. float dy = y - oy;
  770. fz_stroke_lineto_aux(ctx, s, x, y, from_bezier, dx, dy);
  771. }
  772. static void
  773. fz_stroke_closepath(fz_context *ctx, sctx *s)
  774. {
  775. if (s->sn == 1)
  776. {
  777. fz_stroke_lineto(ctx, s, s->beg[0].x, s->beg[0].y, 0);
  778. /* fz_stroke_lineto will *normally* end up with s->seg[1] being the x,y coords passed in.
  779. * As such, the following line should draw a linejoin between the closing segment of this
  780. * subpath (seg[0]->seg[1]) == (seg[0]->beg[0]) and the first segment of this subpath
  781. * (beg[0]->beg[1]).
  782. * In cases where the line was already at an x,y infinitesimally close to s->beg[0],
  783. * fz_stroke_lineto may exit without doing any processing. This leaves seg[0]->seg[1]
  784. * pointing at the penultimate line segment. Thus this draws a linejoin between that
  785. * penultimate segment and the end segment. This is what we want. */
  786. fz_add_line_join(ctx, s, s->seg[0].x, s->seg[0].y, s->beg[0].x, s->beg[0].y, s->beg[1].x, s->beg[1].y, 0);
  787. }
  788. else if (s->not_just_moves && s->cap == FZ_LINECAP_ROUND)
  789. fz_add_line_dot(ctx, s, s->beg[0].x, s->beg[0].y);
  790. s->seg[0] = s->beg[0];
  791. s->sn = 0;
  792. s->not_just_moves = 0;
  793. s->from_bezier = 0;
  794. s->dirn_x = 0;
  795. s->dirn_y = 0;
  796. fz_gap_rasterizer(ctx, s->rast);
  797. }
  798. static void
  799. fz_stroke_bezier(fz_context *ctx, struct sctx *s,
  800. float xa, float ya,
  801. float xb, float yb,
  802. float xc, float yc,
  803. float xd, float yd, int depth)
  804. {
  805. float dmax;
  806. float xab, yab;
  807. float xbc, ybc;
  808. float xcd, ycd;
  809. float xabc, yabc;
  810. float xbcd, ybcd;
  811. float xabcd, yabcd;
  812. /* termination check */
  813. dmax = fz_abs(xa - xb);
  814. dmax = fz_max(dmax, fz_abs(ya - yb));
  815. dmax = fz_max(dmax, fz_abs(xd - xc));
  816. dmax = fz_max(dmax, fz_abs(yd - yc));
  817. if (dmax < s->flatness || depth >= MAX_DEPTH)
  818. {
  819. fz_stroke_lineto(ctx, s, xd, yd, 1);
  820. return;
  821. }
  822. xab = xa + xb;
  823. yab = ya + yb;
  824. xbc = xb + xc;
  825. ybc = yb + yc;
  826. xcd = xc + xd;
  827. ycd = yc + yd;
  828. xabc = xab + xbc;
  829. yabc = yab + ybc;
  830. xbcd = xbc + xcd;
  831. ybcd = ybc + ycd;
  832. xabcd = xabc + xbcd;
  833. yabcd = yabc + ybcd;
  834. xab *= 0.5f; yab *= 0.5f;
  835. /* xbc *= 0.5f; ybc *= 0.5f; */
  836. xcd *= 0.5f; ycd *= 0.5f;
  837. xabc *= 0.25f; yabc *= 0.25f;
  838. xbcd *= 0.25f; ybcd *= 0.25f;
  839. xabcd *= 0.125f; yabcd *= 0.125f;
  840. fz_stroke_bezier(ctx, s, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1);
  841. fz_stroke_bezier(ctx, s, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1);
  842. }
  843. static void
  844. fz_stroke_quad(fz_context *ctx, struct sctx *s,
  845. float xa, float ya,
  846. float xb, float yb,
  847. float xc, float yc, int depth)
  848. {
  849. float dmax;
  850. float xab, yab;
  851. float xbc, ybc;
  852. float xabc, yabc;
  853. /* termination check */
  854. dmax = fz_abs(xa - xb);
  855. dmax = fz_max(dmax, fz_abs(ya - yb));
  856. dmax = fz_max(dmax, fz_abs(xc - xb));
  857. dmax = fz_max(dmax, fz_abs(yc - yb));
  858. if (dmax < s->flatness || depth >= MAX_DEPTH)
  859. {
  860. fz_stroke_lineto(ctx, s, xc, yc, 1);
  861. return;
  862. }
  863. xab = xa + xb;
  864. yab = ya + yb;
  865. xbc = xb + xc;
  866. ybc = yb + yc;
  867. xabc = xab + xbc;
  868. yabc = yab + ybc;
  869. xab *= 0.5f; yab *= 0.5f;
  870. xbc *= 0.5f; ybc *= 0.5f;
  871. xabc *= 0.25f; yabc *= 0.25f;
  872. fz_stroke_quad(ctx, s, xa, ya, xab, yab, xabc, yabc, depth + 1);
  873. fz_stroke_quad(ctx, s, xabc, yabc, xbc, ybc, xc, yc, depth + 1);
  874. }
  875. static void
  876. stroke_moveto(fz_context *ctx, void *s_, float x, float y)
  877. {
  878. sctx *s = (sctx *)s_;
  879. fz_stroke_flush(ctx, s, s->stroke->start_cap, s->stroke->end_cap);
  880. fz_stroke_moveto(ctx, s, x, y);
  881. s->cur.x = x;
  882. s->cur.y = y;
  883. }
  884. static void
  885. stroke_lineto(fz_context *ctx, void *s_, float x, float y)
  886. {
  887. sctx *s = (sctx *)s_;
  888. fz_stroke_lineto(ctx, s, x, y, 0);
  889. s->cur.x = x;
  890. s->cur.y = y;
  891. }
  892. static void
  893. stroke_curveto(fz_context *ctx, void *s_, float x1, float y1, float x2, float y2, float x3, float y3)
  894. {
  895. sctx *s = (sctx *)s_;
  896. fz_stroke_bezier(ctx, s, s->cur.x, s->cur.y, x1, y1, x2, y2, x3, y3, 0);
  897. s->cur.x = x3;
  898. s->cur.y = y3;
  899. }
  900. static void
  901. stroke_quadto(fz_context *ctx, void *s_, float x1, float y1, float x2, float y2)
  902. {
  903. sctx *s = (sctx *)s_;
  904. fz_stroke_quad(ctx, s, s->cur.x, s->cur.y, x1, y1, x2, y2, 0);
  905. s->cur.x = x2;
  906. s->cur.y = y2;
  907. }
  908. static void
  909. stroke_close(fz_context *ctx, void *s_)
  910. {
  911. sctx *s = (sctx *)s_;
  912. fz_stroke_closepath(ctx, s);
  913. }
  914. static const fz_path_walker stroke_proc =
  915. {
  916. stroke_moveto,
  917. stroke_lineto,
  918. stroke_curveto,
  919. stroke_close,
  920. stroke_quadto
  921. };
  922. static void
  923. fz_dash_moveto(fz_context *ctx, struct sctx *s, float x, float y)
  924. {
  925. s->toggle = 1;
  926. s->offset = 0;
  927. s->phase = s->dash_phase;
  928. while (s->phase > 0 && s->phase >= s->dash_list[s->offset])
  929. {
  930. s->toggle = !s->toggle;
  931. s->phase -= s->dash_list[s->offset];
  932. s->offset ++;
  933. if (s->offset == s->dash_len)
  934. s->offset = 0;
  935. }
  936. s->dash_cur.x = x;
  937. s->dash_cur.y = y;
  938. if (s->toggle)
  939. {
  940. fz_stroke_flush(ctx, s, s->cap, s->stroke->end_cap);
  941. s->cap = s->stroke->start_cap;
  942. fz_stroke_moveto(ctx, s, x, y);
  943. }
  944. }
  945. /*
  946. Performs: a += (b-a) * i/n
  947. allowing for FP inaccuracies that can cause a to "overrun" b.
  948. */
  949. static float advance(float a, float b, float i, float n)
  950. {
  951. float d = b - a;
  952. float target = a + d * i/n;
  953. if (d < 0 && target < b)
  954. target = b;
  955. else if (d > 0 && target > b)
  956. target = b;
  957. return target;
  958. }
  959. static void
  960. fz_dash_lineto(fz_context *ctx, struct sctx *s, float bx, float by, int from_bezier)
  961. {
  962. float dx, dy, d;
  963. float total, used, ratio, tail;
  964. float ax, ay;
  965. float mx, my;
  966. float old_bx = 0, old_by = 0;
  967. int n;
  968. int dash_cap = s->stroke->dash_cap;
  969. ax = s->dash_cur.x;
  970. ay = s->dash_cur.y;
  971. dx = bx - ax;
  972. dy = by - ay;
  973. used = 0;
  974. tail = 0;
  975. total = sqrtf(dx * dx + dy * dy);
  976. /* If a is off screen, bring it onto the screen. First
  977. * horizontally... */
  978. if ((d = s->rect.x0 - ax) > 0)
  979. {
  980. if (bx < s->rect.x0)
  981. {
  982. /* Entirely off screen */
  983. tail = total;
  984. old_bx = bx;
  985. old_by = by;
  986. goto adjust_for_tail;
  987. }
  988. ax = s->rect.x0; /* d > 0, dx > 0 */
  989. goto a_moved_horizontally;
  990. }
  991. else if (d < 0 && (d = (s->rect.x1 - ax)) < 0)
  992. {
  993. if (bx > s->rect.x1)
  994. {
  995. /* Entirely off screen */
  996. tail = total;
  997. old_bx = bx;
  998. old_by = by;
  999. goto adjust_for_tail;
  1000. }
  1001. ax = s->rect.x1; /* d < 0, dx < 0 */
  1002. a_moved_horizontally: /* d and dx have the same sign */
  1003. assert((d > 0 && dx > 0) || (d < 0 && dx < 0));
  1004. assert(dx != 0);
  1005. ay = advance(ay, by, d, dx);
  1006. used = total * d/dx;
  1007. total -= used;
  1008. dx = bx - ax;
  1009. dy = by - ay;
  1010. }
  1011. /* Then vertically... */
  1012. if ((d = s->rect.y0 - ay) > 0)
  1013. {
  1014. if (by < s->rect.y0)
  1015. {
  1016. /* Entirely off screen */
  1017. tail = total;
  1018. old_bx = bx;
  1019. old_by = by;
  1020. goto adjust_for_tail;
  1021. }
  1022. ay = s->rect.y0; /* d > 0, dy > 0 */
  1023. goto a_moved_vertically;
  1024. }
  1025. else if (d < 0 && (d = (s->rect.y1 - ay)) < 0)
  1026. {
  1027. if (by > s->rect.y1)
  1028. {
  1029. /* Entirely off screen */
  1030. tail = total;
  1031. old_bx = bx;
  1032. old_by = by;
  1033. goto adjust_for_tail;
  1034. }
  1035. ay = s->rect.y1; /* d < 0, dy < 0 */
  1036. a_moved_vertically: /* d and dy have the same sign */
  1037. assert((d > 0 && dy > 0) || (d < 0 && dy < 0));
  1038. assert(dy != 0);
  1039. ax = advance(ax, bx, d, dy);
  1040. d = total * d/dy;
  1041. total -= d;
  1042. used += d;
  1043. dx = bx - ax;
  1044. dy = by - ay;
  1045. }
  1046. if (used != 0.0f)
  1047. {
  1048. /* Update the position in the dash array */
  1049. if (s->toggle)
  1050. {
  1051. fz_stroke_lineto(ctx, s, ax, ay, from_bezier);
  1052. }
  1053. else
  1054. {
  1055. fz_stroke_flush(ctx, s, s->cap, s->stroke->dash_cap);
  1056. s->cap = s->stroke->dash_cap;
  1057. fz_stroke_moveto(ctx, s, ax, ay);
  1058. }
  1059. used += s->phase;
  1060. n = used/s->dash_total;
  1061. used -= n*s->dash_total;
  1062. if (n & s->dash_len & 1)
  1063. s->toggle = !s->toggle;
  1064. while (used >= s->dash_list[s->offset])
  1065. {
  1066. used -= s->dash_list[s->offset];
  1067. s->offset++;
  1068. if (s->offset == s->dash_len)
  1069. s->offset = 0;
  1070. s->toggle = !s->toggle;
  1071. }
  1072. if (s->toggle)
  1073. {
  1074. fz_stroke_lineto(ctx, s, ax, ay, from_bezier);
  1075. }
  1076. else
  1077. {
  1078. fz_stroke_flush(ctx, s, s->cap, s->stroke->dash_cap);
  1079. s->cap = s->stroke->dash_cap;
  1080. fz_stroke_moveto(ctx, s, ax, ay);
  1081. }
  1082. s->phase = used;
  1083. used = 0;
  1084. }
  1085. /* Now if bx is off screen, bring it back */
  1086. if (dx == 0)
  1087. {
  1088. /* Earlier stages can have moved a to be b, while leaving it completely off screen. */
  1089. }
  1090. else if ((d = bx - s->rect.x0) < 0)
  1091. {
  1092. old_bx = bx;
  1093. old_by = by;
  1094. bx = s->rect.x0; /* d < 0, dx < 0 */
  1095. goto b_moved_horizontally;
  1096. }
  1097. else if (d > 0 && (d = (bx - s->rect.x1)) > 0)
  1098. {
  1099. old_bx = bx;
  1100. old_by = by;
  1101. bx = s->rect.x1; /* d > 0, dx > 0 */
  1102. b_moved_horizontally: /* d and dx have the same sign */
  1103. assert((d > 0 && dx > 0) || (d < 0 && dx < 0));
  1104. assert(dx != 0);
  1105. by = advance(by, ay, d, dx);
  1106. tail = total * d/dx;
  1107. total -= tail;
  1108. dx = bx - ax;
  1109. dy = by - ay;
  1110. }
  1111. /* Then vertically... */
  1112. if (dy == 0)
  1113. {
  1114. /* Earlier stages can have moved a to be b, while leaving it completely off screen. */
  1115. }
  1116. else if ((d = by - s->rect.y0) < 0)
  1117. {
  1118. old_bx = bx;
  1119. old_by = by;
  1120. by = s->rect.y0; /* d < 0, dy < 0 */
  1121. goto b_moved_vertically;
  1122. }
  1123. else if (d > 0 && (d = (by - s->rect.y1)) > 0)
  1124. {
  1125. float t;
  1126. old_bx = bx;
  1127. old_by = by;
  1128. by = s->rect.y1; /* d > 0, dy > 0 */
  1129. b_moved_vertically: /* d and dy have the same sign */
  1130. assert((d > 0 && dy > 0) || (d < 0 && dy < 0));
  1131. assert(dy != 0);
  1132. bx = advance(bx, ax, d, dy);
  1133. t = total * d/dy;
  1134. tail += t;
  1135. total -= t;
  1136. dx = bx - ax;
  1137. dy = by - ay;
  1138. }
  1139. while (total - used > s->dash_list[s->offset] - s->phase)
  1140. {
  1141. used += s->dash_list[s->offset] - s->phase;
  1142. ratio = used / total;
  1143. mx = ax + ratio * dx;
  1144. my = ay + ratio * dy;
  1145. if (s->toggle)
  1146. {
  1147. fz_stroke_lineto_aux(ctx, s, mx, my, from_bezier, dx, dy);
  1148. }
  1149. else
  1150. {
  1151. fz_stroke_flush(ctx, s, s->cap, dash_cap);
  1152. s->cap = dash_cap;
  1153. fz_stroke_moveto(ctx, s, mx, my);
  1154. }
  1155. s->toggle = !s->toggle;
  1156. s->phase = 0;
  1157. s->offset ++;
  1158. if (s->offset == s->dash_len)
  1159. s->offset = 0;
  1160. }
  1161. s->phase += total - used;
  1162. if (tail == 0.0f)
  1163. {
  1164. s->dash_cur.x = bx;
  1165. s->dash_cur.y = by;
  1166. if (s->toggle)
  1167. {
  1168. fz_stroke_lineto_aux(ctx, s, bx, by, from_bezier, dx, dy);
  1169. }
  1170. }
  1171. else
  1172. {
  1173. adjust_for_tail:
  1174. s->dash_cur.x = old_bx;
  1175. s->dash_cur.y = old_by;
  1176. /* Update the position in the dash array */
  1177. if (s->toggle)
  1178. {
  1179. fz_stroke_lineto_aux(ctx, s, old_bx, old_by, from_bezier, dx, dy);
  1180. }
  1181. else
  1182. {
  1183. fz_stroke_flush(ctx, s, s->cap, dash_cap);
  1184. s->cap = dash_cap;
  1185. fz_stroke_moveto(ctx, s, old_bx, old_by);
  1186. }
  1187. tail += s->phase;
  1188. n = tail/s->dash_total;
  1189. tail -= n*s->dash_total;
  1190. if (n & s->dash_len & 1)
  1191. s->toggle = !s->toggle;
  1192. while (tail > s->dash_list[s->offset])
  1193. {
  1194. tail -= s->dash_list[s->offset];
  1195. s->offset++;
  1196. if (s->offset == s->dash_len)
  1197. s->offset = 0;
  1198. s->toggle = !s->toggle;
  1199. }
  1200. if (s->toggle)
  1201. {
  1202. fz_stroke_lineto_aux(ctx, s, old_bx, old_by, from_bezier, dx, dy);
  1203. }
  1204. else
  1205. {
  1206. fz_stroke_flush(ctx, s, s->cap, dash_cap);
  1207. s->cap = dash_cap;
  1208. fz_stroke_moveto(ctx, s, old_bx, old_by);
  1209. }
  1210. s->phase = tail;
  1211. }
  1212. }
  1213. static void
  1214. fz_dash_bezier(fz_context *ctx, struct sctx *s,
  1215. float xa, float ya,
  1216. float xb, float yb,
  1217. float xc, float yc,
  1218. float xd, float yd, int depth)
  1219. {
  1220. float dmax;
  1221. float xab, yab;
  1222. float xbc, ybc;
  1223. float xcd, ycd;
  1224. float xabc, yabc;
  1225. float xbcd, ybcd;
  1226. float xabcd, yabcd;
  1227. /* termination check */
  1228. dmax = fz_abs(xa - xb);
  1229. dmax = fz_max(dmax, fz_abs(ya - yb));
  1230. dmax = fz_max(dmax, fz_abs(xd - xc));
  1231. dmax = fz_max(dmax, fz_abs(yd - yc));
  1232. if (dmax < s->flatness || depth >= MAX_DEPTH)
  1233. {
  1234. fz_dash_lineto(ctx, s, xd, yd, 1);
  1235. return;
  1236. }
  1237. xab = xa + xb;
  1238. yab = ya + yb;
  1239. xbc = xb + xc;
  1240. ybc = yb + yc;
  1241. xcd = xc + xd;
  1242. ycd = yc + yd;
  1243. xabc = xab + xbc;
  1244. yabc = yab + ybc;
  1245. xbcd = xbc + xcd;
  1246. ybcd = ybc + ycd;
  1247. xabcd = xabc + xbcd;
  1248. yabcd = yabc + ybcd;
  1249. xab *= 0.5f; yab *= 0.5f;
  1250. /* xbc *= 0.5f; ybc *= 0.5f; */
  1251. xcd *= 0.5f; ycd *= 0.5f;
  1252. xabc *= 0.25f; yabc *= 0.25f;
  1253. xbcd *= 0.25f; ybcd *= 0.25f;
  1254. xabcd *= 0.125f; yabcd *= 0.125f;
  1255. fz_dash_bezier(ctx, s, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1);
  1256. fz_dash_bezier(ctx, s, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1);
  1257. }
  1258. static void
  1259. fz_dash_quad(fz_context *ctx, struct sctx *s,
  1260. float xa, float ya,
  1261. float xb, float yb,
  1262. float xc, float yc, int depth)
  1263. {
  1264. float dmax;
  1265. float xab, yab;
  1266. float xbc, ybc;
  1267. float xabc, yabc;
  1268. /* termination check */
  1269. dmax = fz_abs(xa - xb);
  1270. dmax = fz_max(dmax, fz_abs(ya - yb));
  1271. dmax = fz_max(dmax, fz_abs(xc - xb));
  1272. dmax = fz_max(dmax, fz_abs(yc - yb));
  1273. if (dmax < s->flatness || depth >= MAX_DEPTH)
  1274. {
  1275. fz_dash_lineto(ctx, s, xc, yc, 1);
  1276. return;
  1277. }
  1278. xab = xa + xb;
  1279. yab = ya + yb;
  1280. xbc = xb + xc;
  1281. ybc = yb + yc;
  1282. xabc = xab + xbc;
  1283. yabc = yab + ybc;
  1284. xab *= 0.5f; yab *= 0.5f;
  1285. xbc *= 0.5f; ybc *= 0.5f;
  1286. xabc *= 0.25f; yabc *= 0.25f;
  1287. fz_dash_quad(ctx, s, xa, ya, xab, yab, xabc, yabc, depth + 1);
  1288. fz_dash_quad(ctx, s, xabc, yabc, xbc, ybc, xc, yc, depth + 1);
  1289. }
  1290. static void
  1291. dash_moveto(fz_context *ctx, void *s_, float x, float y)
  1292. {
  1293. sctx *s = (sctx *)s_;
  1294. fz_dash_moveto(ctx, s, x, y);
  1295. s->dash_beg.x = s->cur.x = x;
  1296. s->dash_beg.y = s->cur.y = y;
  1297. }
  1298. static void
  1299. dash_lineto(fz_context *ctx, void *s_, float x, float y)
  1300. {
  1301. sctx *s = (sctx *)s_;
  1302. fz_dash_lineto(ctx, s, x, y, 0);
  1303. s->cur.x = x;
  1304. s->cur.y = y;
  1305. }
  1306. static void
  1307. dash_curveto(fz_context *ctx, void *s_, float x1, float y1, float x2, float y2, float x3, float y3)
  1308. {
  1309. sctx *s = (sctx *)s_;
  1310. fz_dash_bezier(ctx, s, s->cur.x, s->cur.y, x1, y1, x2, y2, x3, y3, 0);
  1311. s->cur.x = x3;
  1312. s->cur.y = y3;
  1313. }
  1314. static void
  1315. dash_quadto(fz_context *ctx, void *s_, float x1, float y1, float x2, float y2)
  1316. {
  1317. sctx *s = (sctx *)s_;
  1318. fz_dash_quad(ctx, s, s->cur.x, s->cur.y, x1, y1, x2, y2, 0);
  1319. s->cur.x = x2;
  1320. s->cur.y = y2;
  1321. }
  1322. static void
  1323. dash_close(fz_context *ctx, void *s_)
  1324. {
  1325. sctx *s = (sctx *)s_;
  1326. fz_dash_lineto(ctx, s, s->dash_beg.x, s->dash_beg.y, 0);
  1327. s->cur.x = s->dash_beg.x;
  1328. s->cur.y = s->dash_beg.y;
  1329. }
  1330. static const fz_path_walker dash_proc =
  1331. {
  1332. dash_moveto,
  1333. dash_lineto,
  1334. dash_curveto,
  1335. dash_close,
  1336. dash_quadto
  1337. };
  1338. static int
  1339. do_flatten_stroke(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth)
  1340. {
  1341. struct sctx s;
  1342. const fz_path_walker *proc = &stroke_proc;
  1343. s.stroke = stroke;
  1344. s.rast = rast;
  1345. s.ctm = ctm;
  1346. s.flatness = flatness;
  1347. s.linejoin = stroke->linejoin;
  1348. s.linewidth = linewidth * 0.5f; /* hairlines use a different value from the path value */
  1349. s.miterlimit = stroke->miterlimit;
  1350. s.sn = 0;
  1351. s.not_just_moves = 0;
  1352. s.toggle = 0;
  1353. s.offset = 0;
  1354. s.phase = 0;
  1355. s.dirn_x = 0;
  1356. s.dirn_y = 0;
  1357. s.cap = stroke->start_cap;
  1358. s.dash_list = NULL;
  1359. s.dash_len = stroke->dash_len;
  1360. if (s.dash_len > 0)
  1361. {
  1362. int i;
  1363. fz_matrix inv;
  1364. float max_expand;
  1365. const float *list = stroke->dash_list;
  1366. s.dash_total = 0;
  1367. for (i = 0; i < s.dash_len; i++)
  1368. s.dash_total += list[i];
  1369. if (s.dash_total == 0)
  1370. return 1;
  1371. s.rect = fz_scissor_rasterizer(ctx, rast);
  1372. if (fz_try_invert_matrix(&inv, ctm))
  1373. return 1;
  1374. s.rect = fz_transform_rect(s.rect, inv);
  1375. s.rect.x0 -= linewidth;
  1376. s.rect.x1 += linewidth;
  1377. s.rect.y0 -= linewidth;
  1378. s.rect.y1 += linewidth;
  1379. max_expand = fz_matrix_max_expansion(ctm);
  1380. if (s.dash_total >= 0.01f && s.dash_total * max_expand >= 0.5f)
  1381. {
  1382. proc = &dash_proc;
  1383. s.dash_phase = fmodf(stroke->dash_phase, s.dash_total);
  1384. s.dash_list = list;
  1385. }
  1386. }
  1387. s.cur.x = s.cur.y = 0;
  1388. fz_walk_path(ctx, path, proc, &s);
  1389. fz_stroke_flush(ctx, &s, s.cap, stroke->end_cap);
  1390. return fz_is_empty_irect(fz_bound_rasterizer(ctx, rast));
  1391. }
  1392. int
  1393. fz_flatten_stroke_path(fz_context *ctx, fz_rasterizer *rast, const fz_path *path, const fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth, fz_irect scissor, fz_irect *bbox)
  1394. {
  1395. int empty;
  1396. fz_irect local_bbox;
  1397. if (!bbox)
  1398. bbox = &local_bbox;
  1399. if (fz_reset_rasterizer(ctx, rast, scissor))
  1400. {
  1401. empty = do_flatten_stroke(ctx, rast, path, stroke, ctm, flatness, linewidth);
  1402. if (empty)
  1403. return *bbox = fz_empty_irect, 1;
  1404. fz_postindex_rasterizer(ctx, rast);
  1405. }
  1406. empty = do_flatten_stroke(ctx, rast, path, stroke, ctm, flatness, linewidth);
  1407. if (empty)
  1408. return *bbox = fz_empty_irect, 1;
  1409. *bbox = fz_intersect_irect(scissor, fz_bound_rasterizer(ctx, rast));
  1410. return fz_is_empty_irect(*bbox);
  1411. }