draw-edgebuffer.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  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 <assert.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <limits.h>
  28. #undef DEBUG_SCAN_CONVERTER
  29. /* Define ourselves a 'fixed' type for clarity */
  30. typedef int fixed;
  31. #define fixed_shift 8
  32. #define float2fixed(x) ((int)((x)*(1<<fixed_shift)))
  33. #define fixed2int(x) ((int)((x)>>fixed_shift))
  34. #define fixed_half (1<<(fixed_shift-1))
  35. #define fixed_1 (1<<fixed_shift)
  36. #define int2fixed(x) ((x)<<fixed_shift)
  37. enum
  38. {
  39. DIRN_UNSET = -1,
  40. DIRN_UP = 0,
  41. DIRN_DOWN = 1
  42. };
  43. typedef struct
  44. {
  45. fixed left;
  46. fixed right;
  47. fixed y;
  48. signed char d; /* 0 up (or horiz), 1 down, -1 uninited */
  49. /* unset == 1, iff the values in the above are unset */
  50. unsigned char unset;
  51. /* can_save == 1, iff we are eligible to 'save'. i.e. if we
  52. * have not yet output a cursor, and have not detected
  53. * any line segments completely out of range. */
  54. unsigned char can_save;
  55. unsigned char saved;
  56. fixed save_left;
  57. fixed save_right;
  58. int save_iy;
  59. int save_d;
  60. }
  61. cursor_t;
  62. typedef struct fz_edgebuffer_s
  63. {
  64. fz_rasterizer super;
  65. int app;
  66. int sorted;
  67. int n;
  68. int index_cap;
  69. int *index;
  70. int table_cap;
  71. int *table;
  72. /* cursor section, for use with any part of pixel mode */
  73. cursor_t cursor[3];
  74. } fz_edgebuffer;
  75. static fz_rasterizer_insert_fn fz_insert_edgebuffer_app;
  76. static fz_rasterizer_insert_fn fz_insert_edgebuffer;
  77. #ifdef DEBUG_SCAN_CONVERTER
  78. int debugging_scan_converter = 1;
  79. static void
  80. fz_edgebuffer_print(fz_context *ctx, fz_output *out, fz_edgebuffer * edgebuffer)
  81. {
  82. int i;
  83. int height = edgebuffer->super.clip.y1 - edgebuffer->super.clip.y0;
  84. fz_write_printf(ctx, out, "Edgebuffer %x\n", edgebuffer);
  85. fz_write_printf(ctx, out, "xmin=%x xmax=%x base=%x height=%x\n",
  86. edgebuffer->super.clip.x0, edgebuffer->super.clip.x1, edgebuffer->super.clip.y0, height);
  87. for (i=0; i < height; i++) {
  88. int offset = edgebuffer->index[i];
  89. int *row = &edgebuffer->table[offset];
  90. int count = *row++;
  91. assert ((count & 1) == 0);
  92. fz_write_printf(ctx, out, "%x @ %x: %d =", i, offset, count);
  93. while (count-- > 0) {
  94. int v = *row++;
  95. fz_write_printf(ctx, out, " %x:%d", v&~1, v&1);
  96. }
  97. fz_write_printf(ctx, out, "\n");
  98. }
  99. }
  100. static void
  101. fz_edgebuffer_print_app(fz_context *ctx, fz_output *out, fz_edgebuffer * edgebuffer)
  102. {
  103. int i;
  104. int height = edgebuffer->super.clip.y1 - edgebuffer->super.clip.y0;
  105. fz_write_printf(ctx, out, "Edgebuffer %x\n", edgebuffer);
  106. fz_write_printf(ctx, out, "xmin=%x xmax=%x base=%x height=%x\n",
  107. edgebuffer->super.clip.x0, edgebuffer->super.clip.x1, edgebuffer->super.clip.y0, height);
  108. if (edgebuffer->table == NULL)
  109. return;
  110. for (i=0; i < height; i++) {
  111. int offset = edgebuffer->index[i];
  112. int *row = &edgebuffer->table[offset];
  113. int count = *row++;
  114. int count0 = count;
  115. fz_write_printf(ctx, out, "%x @ %x: %d =", i, offset, count);
  116. while (count-- > 0) {
  117. int l = *row++;
  118. int r = *row++;
  119. fz_write_printf(ctx, out, " %x:%x", l, r);
  120. }
  121. assert((count0 & 1) == 0); (void)count0;
  122. fz_write_printf(ctx, out, "\n");
  123. }
  124. }
  125. #endif
  126. static void fz_drop_edgebuffer(fz_context *ctx, fz_rasterizer *r)
  127. {
  128. fz_edgebuffer *eb = (fz_edgebuffer *)r;
  129. if (eb)
  130. {
  131. fz_free(ctx, eb->index);
  132. fz_free(ctx, eb->table);
  133. }
  134. fz_free(ctx, eb);
  135. }
  136. static void index_edgebuffer_insert(fz_context *ctx, fz_rasterizer *ras, float fsx, float fsy, float fex, float fey, int rev)
  137. {
  138. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  139. int iminy, imaxy;
  140. int height = eb->super.clip.y1 - eb->super.clip.y0;
  141. if (fsy == fey)
  142. return;
  143. if (fsx < fex)
  144. {
  145. if (fsx < eb->super.bbox.x0) eb->super.bbox.x0 = fsx;
  146. if (fex > eb->super.bbox.x1) eb->super.bbox.x1 = fex;
  147. }
  148. else
  149. {
  150. if (fsx > eb->super.bbox.x1) eb->super.bbox.x1 = fsx;
  151. if (fex < eb->super.bbox.x0) eb->super.bbox.x0 = fex;
  152. }
  153. if (fsy < fey)
  154. {
  155. if (fsy < eb->super.bbox.y0) eb->super.bbox.y0 = fsy;
  156. if (fey > eb->super.bbox.y1) eb->super.bbox.y1 = fey;
  157. }
  158. else
  159. {
  160. if (fey < eb->super.bbox.y0) eb->super.bbox.y0 = fey;
  161. if (fsy > eb->super.bbox.y1) eb->super.bbox.y1 = fsy;
  162. }
  163. /* To strictly match, this should be:
  164. * iminy = int2fixed(float2fixed(fsy))
  165. * imaxy = int2fixed(float2fixed(fsx))
  166. * but this is faster. It can round differently,
  167. * (on some machines at least) hence the iminy--; below.
  168. */
  169. iminy = (int)fsy;
  170. imaxy = (int)fey;
  171. if (iminy > imaxy)
  172. {
  173. int t;
  174. t = iminy; iminy = imaxy; imaxy = t;
  175. }
  176. imaxy++;
  177. iminy--;
  178. imaxy -= eb->super.clip.y0;
  179. if (imaxy < 0)
  180. return;
  181. iminy -= eb->super.clip.y0;
  182. if (iminy < 0)
  183. iminy = 0;
  184. else if (iminy > height)
  185. return;
  186. if (imaxy > height-1)
  187. imaxy = height-1;
  188. #ifdef DEBUG_SCAN_CONVERTER
  189. if (debugging_scan_converter)
  190. fprintf(stderr, "%x->%x:%d\n", iminy, imaxy, eb->n);
  191. #endif
  192. eb->index[iminy] += eb->n;
  193. eb->index[imaxy+1] -= eb->n;
  194. }
  195. static void fz_postindex_edgebuffer(fz_context *ctx, fz_rasterizer *r)
  196. {
  197. fz_edgebuffer *eb = (fz_edgebuffer *)r;
  198. int height = eb->super.clip.y1 - eb->super.clip.y0 + 1;
  199. int n = eb->n;
  200. int total = 0;
  201. int delta = 0;
  202. int i;
  203. eb->super.fns.insert = (eb->app ? fz_insert_edgebuffer_app : fz_insert_edgebuffer);
  204. for (i = 0; i < height; i++)
  205. {
  206. delta += eb->index[i];
  207. eb->index[i] = total;
  208. total += 1 + delta*n;
  209. }
  210. assert(delta == 0);
  211. if (eb->table_cap < total)
  212. {
  213. eb->table = fz_realloc_array(ctx, eb->table, total, int);
  214. eb->table_cap = total;
  215. }
  216. for (i = 0; i < height; i++)
  217. {
  218. eb->table[eb->index[i]] = 0;
  219. }
  220. }
  221. static int fz_reset_edgebuffer(fz_context *ctx, fz_rasterizer *r)
  222. {
  223. fz_edgebuffer *eb = (fz_edgebuffer *)r;
  224. int height = eb->super.clip.y1 - eb->super.clip.y0 + 1;
  225. int n;
  226. eb->sorted = 0;
  227. if (eb->index_cap < height)
  228. {
  229. eb->index = fz_realloc_array(ctx, eb->index, height, int);
  230. eb->index_cap = height;
  231. }
  232. memset(eb->index, 0, sizeof(int) * height);
  233. n = 1;
  234. if (eb->app)
  235. {
  236. n = 2;
  237. eb->cursor[0].saved = 0;
  238. eb->cursor[0].unset = 1;
  239. eb->cursor[0].can_save = 1;
  240. eb->cursor[0].d = DIRN_UNSET;
  241. eb->cursor[1].saved = 0;
  242. eb->cursor[1].unset = 1;
  243. eb->cursor[1].can_save = 1;
  244. eb->cursor[1].d = DIRN_UNSET;
  245. eb->cursor[2].saved = 0;
  246. eb->cursor[2].unset = 1;
  247. eb->cursor[2].can_save = 1;
  248. eb->cursor[2].d = DIRN_UNSET;
  249. }
  250. eb->n = n;
  251. eb->super.fns.insert = index_edgebuffer_insert;
  252. return 1;
  253. }
  254. static void mark_line(fz_context *ctx, fz_edgebuffer *eb, fixed sx, fixed sy, fixed ex, fixed ey)
  255. {
  256. int base_y = eb->super.clip.y0;
  257. int height = eb->super.clip.y1 - eb->super.clip.y0;
  258. int *table = eb->table;
  259. int *index = eb->index;
  260. int delta;
  261. int iy, ih;
  262. fixed clip_sy, clip_ey;
  263. int dirn = DIRN_UP;
  264. int *row;
  265. if (fixed2int(sy + fixed_half-1) == fixed2int(ey + fixed_half-1))
  266. return;
  267. if (sy > ey) {
  268. int t;
  269. t = sy; sy = ey; ey = t;
  270. t = sx; sx = ex; ex = t;
  271. dirn = DIRN_DOWN;
  272. }
  273. if (fixed2int(sx) < eb->super.bbox.x0)
  274. eb->super.bbox.x0 = fixed2int(sx);
  275. if (fixed2int(sx + fixed_1 - 1) > eb->super.bbox.x1)
  276. eb->super.bbox.x1 = fixed2int(sx + fixed_1 - 1);
  277. if (fixed2int(ex) < eb->super.bbox.x0)
  278. eb->super.bbox.x0 = fixed2int(ex);
  279. if (fixed2int(ex + fixed_1 - 1) > eb->super.bbox.x1)
  280. eb->super.bbox.x1 = fixed2int(ex + fixed_1 - 1);
  281. if (fixed2int(sy) < eb->super.bbox.y0)
  282. eb->super.bbox.y0 = fixed2int(sy);
  283. if (fixed2int(ey + fixed_1 - 1) > eb->super.bbox.y1)
  284. eb->super.bbox.y1 = fixed2int(ey + fixed_1 - 1);
  285. /* Lines go from sy to ey, closed at the start, open at the end. */
  286. /* We clip them to a region to make them closed at both ends. */
  287. /* Thus the unset scanline marked (>= sy) is: */
  288. clip_sy = ((sy + fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
  289. /* The last scanline marked (< ey) is: */
  290. clip_ey = ((ey - fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
  291. /* Now allow for banding */
  292. if (clip_sy < int2fixed(base_y) + fixed_half)
  293. clip_sy = int2fixed(base_y) + fixed_half;
  294. if (ey <= clip_sy)
  295. return;
  296. if (clip_ey > int2fixed(base_y + height - 1) + fixed_half)
  297. clip_ey = int2fixed(base_y + height - 1) + fixed_half;
  298. if (sy > clip_ey)
  299. return;
  300. delta = clip_sy - sy;
  301. if (delta > 0)
  302. {
  303. int dx = ex - sx;
  304. int dy = ey - sy;
  305. int advance = (int)(((int64_t)dx * delta + (dy>>1)) / dy);
  306. sx += advance;
  307. sy += delta;
  308. }
  309. ex -= sx;
  310. ey -= sy;
  311. clip_ey -= clip_sy;
  312. delta = ey - clip_ey;
  313. if (delta > 0)
  314. {
  315. int advance = (int)(((int64_t)ex * delta + (ey>>1)) / ey);
  316. ex -= advance;
  317. ey -= delta;
  318. }
  319. ih = fixed2int(ey);
  320. assert(ih >= 0);
  321. iy = fixed2int(sy) - base_y;
  322. #ifdef DEBUG_SCAN_CONVERTER
  323. if (debugging_scan_converter)
  324. fz_write_printf(ctx, fz_stderr(ctx), " iy=%x ih=%x\n", iy, ih);
  325. #endif
  326. assert(iy >= 0 && iy < height);
  327. /* We always cross at least one scanline */
  328. row = &table[index[iy]];
  329. *row = (*row)+1; /* Increment the count */
  330. row[*row] = (sx&~1) | dirn;
  331. if (ih == 0)
  332. return;
  333. if (ex >= 0) {
  334. int x_inc, n_inc, f;
  335. /* We want to change sx by ex in ih steps. So each step, we add
  336. * ex/ih to sx. That's x_inc + n_inc/ih.
  337. */
  338. x_inc = ex/ih;
  339. n_inc = ex-(x_inc*ih);
  340. f = ih>>1;
  341. delta = ih;
  342. do {
  343. int count;
  344. iy++;
  345. sx += x_inc;
  346. f -= n_inc;
  347. if (f < 0) {
  348. f += ih;
  349. sx++;
  350. }
  351. assert(iy >= 0 && iy < height);
  352. row = &table[index[iy]];
  353. count = *row = (*row)+1; /* Increment the count */
  354. row[count] = (sx&~1) | dirn;
  355. } while (--delta);
  356. } else {
  357. int x_dec, n_dec, f;
  358. ex = -ex;
  359. /* We want to change sx by ex in ih steps. So each step, we subtract
  360. * ex/ih from sx. That's x_dec + n_dec/ih.
  361. */
  362. x_dec = ex/ih;
  363. n_dec = ex-(x_dec*ih);
  364. f = ih>>1;
  365. delta = ih;
  366. do {
  367. int count;
  368. iy++;
  369. sx -= x_dec;
  370. f -= n_dec;
  371. if (f < 0) {
  372. f += ih;
  373. sx--;
  374. }
  375. assert(iy >= 0 && iy < height);
  376. row = &table[index[iy]];
  377. count = *row = (*row)+1; /* Increment the count */
  378. row[count] = (sx&~1) | dirn;
  379. } while (--delta);
  380. }
  381. }
  382. /* Allow for floats that are too large to safely convert to fixeds (ints),
  383. * by just clipping them at the end. */
  384. static fixed
  385. safe_float2fixed(float f)
  386. {
  387. if (f < (float)-0x00800000)
  388. return INT_MIN;
  389. else if (f >= (float)0x00800000)
  390. return INT_MAX;
  391. else
  392. return float2fixed(f);
  393. }
  394. static void fz_insert_edgebuffer(fz_context *ctx, fz_rasterizer *ras, float fsx, float fsy, float fex, float fey, int rev)
  395. {
  396. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  397. fixed sx = safe_float2fixed(fsx);
  398. fixed sy = safe_float2fixed(fsy);
  399. fixed ex = safe_float2fixed(fex);
  400. fixed ey = safe_float2fixed(fey);
  401. mark_line(ctx, eb, sx, sy, ex, ey);
  402. }
  403. static inline void
  404. cursor_output(fz_edgebuffer * FZ_RESTRICT eb, int rev, int iy)
  405. {
  406. int *row;
  407. int count;
  408. int height = eb->super.clip.y1 - eb->super.clip.y0;
  409. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  410. rev &= 1; /* Edge label 0 is forwards, 1 and 2 are reverse */
  411. if (iy >= 0 && iy < height) {
  412. if (cr->can_save) {
  413. /* Save it for later in case we join up */
  414. cr->save_left = cr->left;
  415. cr->save_right = cr->right;
  416. cr->save_iy = iy;
  417. cr->save_d = cr->d;
  418. cr->saved = 1;
  419. } else {
  420. /* Enter it into the table */
  421. row = &eb->table[eb->index[iy]];
  422. if (cr->d == DIRN_UNSET)
  423. {
  424. /* Move 0 0; line 10 0; line 0 0; */
  425. /* FIXME */
  426. }
  427. else
  428. {
  429. *row = count = (*row)+1; /* Increment the count */
  430. #ifdef DEBUG_SCAN_CONVERTER
  431. if (debugging_scan_converter)
  432. fprintf(stderr, "row: %x: %x->%x %c\n", iy, cr->left, cr->right, (cr->d^rev) == DIRN_UP ? '^' : (cr->d^rev) == DIRN_DOWN ? 'v' : '-');
  433. #endif
  434. assert(count <= (eb->index[iy+1] - eb->index[iy] - 1)/2);
  435. row[2 * count - 1] = (cr->left&~1) | (cr->d ^ rev);
  436. row[2 * count] = cr->right;
  437. }
  438. }
  439. }
  440. cr->can_save = 0;
  441. }
  442. static inline void
  443. cursor_output_inrange(fz_edgebuffer * FZ_RESTRICT eb, int rev, int iy)
  444. {
  445. int *row;
  446. int count;
  447. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  448. rev &= 1; /* Edge label 0 is forwards, 1 and 2 are reverse */
  449. assert(iy >= 0 && iy < eb->super.clip.y1 - eb->super.clip.y0);
  450. if (cr->can_save) {
  451. /* Save it for later in case we join up */
  452. cr->save_left = cr->left;
  453. cr->save_right = cr->right;
  454. cr->save_iy = iy;
  455. cr->save_d = cr->d;
  456. cr->saved = 1;
  457. } else {
  458. /* Enter it into the table */
  459. assert(cr->d != DIRN_UNSET);
  460. row = &eb->table[eb->index[iy]];
  461. *row = count = (*row)+1; /* Increment the count */
  462. #ifdef DEBUG_SCAN_CONVERTER
  463. if (debugging_scan_converter)
  464. printf("row= %x: %x->%x %c\n", iy, cr->left, cr->right, (cr->d^rev) == DIRN_UP ? '^' : (cr->d^rev) == DIRN_DOWN ? 'v' : '-');
  465. #endif
  466. row[2 * count - 1] = (cr->left&~1) | (cr->d ^ rev);
  467. row[2 * count] = cr->right;
  468. }
  469. cr->can_save = 0;
  470. }
  471. /* Step the cursor in y, allowing for maybe crossing a scanline */
  472. static inline void
  473. cursor_step(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  474. {
  475. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  476. int new_iy;
  477. int base = eb->super.clip.y0;
  478. int iy = fixed2int(cr->y) - base;
  479. cr->y += dy;
  480. new_iy = fixed2int(cr->y) - base;
  481. if (new_iy != iy) {
  482. cursor_output(eb, rev, iy);
  483. cr->left = x;
  484. cr->right = x;
  485. } else {
  486. if (x < cr->left)
  487. cr->left = x;
  488. if (x > cr->right)
  489. cr->right = x;
  490. }
  491. }
  492. /* Step the cursor in y, never by enough to cross a scanline. */
  493. static inline void
  494. cursor_never_step_vertical(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  495. {
  496. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  497. assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
  498. cr->y += dy;
  499. }
  500. /* Step the cursor in y, never by enough to cross a scanline,
  501. * knowing that we are moving left, and that the right edge
  502. * has already been accounted for. */
  503. static inline void
  504. cursor_never_step_left(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  505. {
  506. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  507. assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
  508. if (x < cr->left)
  509. cr->left = x;
  510. cr->y += dy;
  511. }
  512. /* Step the cursor in y, never by enough to cross a scanline,
  513. * knowing that we are moving right, and that the left edge
  514. * has already been accounted for. */
  515. static inline void
  516. cursor_never_step_right(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  517. {
  518. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  519. assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
  520. if (x > cr->right)
  521. cr->right = x;
  522. cr->y += dy;
  523. }
  524. /* Step the cursor in y, always by enough to cross a scanline. */
  525. static inline void
  526. cursor_always_step(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  527. {
  528. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  529. int base = eb->super.clip.y0;
  530. int iy = fixed2int(cr->y) - base;
  531. cursor_output(eb, rev, iy);
  532. cr->y += dy;
  533. cr->left = x;
  534. cr->right = x;
  535. }
  536. /* Step the cursor in y, always by enough to cross a scanline, as
  537. * part of a vertical line, knowing that we are moving from a
  538. * position guaranteed to be in the valid y range. */
  539. static inline void
  540. cursor_always_step_inrange_vertical(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  541. {
  542. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  543. int base = eb->super.clip.y0;
  544. int iy = fixed2int(cr->y) - base;
  545. cursor_output(eb, rev, iy);
  546. cr->y += dy;
  547. }
  548. /* Step the cursor in y, always by enough to cross a scanline, as
  549. * part of a left moving line, knowing that we are moving from a
  550. * position guaranteed to be in the valid y range. */
  551. static inline void
  552. cursor_always_inrange_step_left(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  553. {
  554. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  555. int base = eb->super.clip.y0;
  556. int iy = fixed2int(cr->y) - base;
  557. cr->y += dy;
  558. cursor_output_inrange(eb, rev, iy);
  559. cr->right = x;
  560. }
  561. /* Step the cursor in y, always by enough to cross a scanline, as
  562. * part of a right moving line, knowing that we are moving from a
  563. * position guaranteed to be in the valid y range. */
  564. static inline void
  565. cursor_always_inrange_step_right(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed dy, fixed x)
  566. {
  567. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  568. int base = eb->super.clip.y0;
  569. int iy = fixed2int(cr->y) - base;
  570. cr->y += dy;
  571. cursor_output_inrange(eb, rev, iy);
  572. cr->left = x;
  573. }
  574. static inline void cursor_init(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed y, fixed x)
  575. {
  576. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  577. assert(y >= int2fixed(eb->super.clip.y0) && y <= int2fixed(eb->super.clip.y1));
  578. cr->y = y;
  579. cr->left = x;
  580. cr->right = x;
  581. cr->d = DIRN_UNSET;
  582. }
  583. static inline void cursor_left_merge(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  584. {
  585. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  586. if (x < cr->left)
  587. cr->left = x;
  588. }
  589. static inline void cursor_left(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  590. {
  591. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  592. cr->left = x;
  593. }
  594. static inline void cursor_right_merge(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  595. {
  596. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  597. if (x > cr->right)
  598. cr->right = x;
  599. }
  600. static inline void cursor_right(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  601. {
  602. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  603. cr->right = x;
  604. }
  605. static inline void cursor_down(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  606. {
  607. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  608. int base = eb->super.clip.y0;
  609. if (cr->d == DIRN_UP)
  610. {
  611. cursor_output(eb, rev, fixed2int(cr->y) - base);
  612. cr->left = x;
  613. cr->right = x;
  614. }
  615. cr->d = DIRN_DOWN;
  616. }
  617. static inline void cursor_up(fz_edgebuffer * FZ_RESTRICT eb, int rev, fixed x)
  618. {
  619. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  620. int base = eb->super.clip.y0;
  621. if (cr->d == DIRN_DOWN)
  622. {
  623. cursor_output(eb, rev, fixed2int(cr->y) - base);
  624. cr->left = x;
  625. cr->right = x;
  626. }
  627. cr->d = DIRN_UP;
  628. }
  629. static inline int dirns_match(int d0, int d1)
  630. {
  631. return d0 == d1 || d0 == DIRN_UNSET || d1 == DIRN_UNSET;
  632. }
  633. static inline int dirn_flip(int d)
  634. {
  635. return d < 0 ? d : d^1;
  636. }
  637. static inline int dirns_merge(int d0, int d1)
  638. {
  639. if (d0 == DIRN_UNSET)
  640. return d1;
  641. assert(dirns_match(d0, d1));
  642. return d0;
  643. }
  644. static void
  645. cursor_flush(fz_edgebuffer * FZ_RESTRICT eb)
  646. {
  647. int base = eb->super.clip.y0;
  648. int iy0, iy1, iy2;
  649. cursor_t * FZ_RESTRICT cr0 = &eb->cursor[0];
  650. cursor_t * FZ_RESTRICT cr1 = &eb->cursor[1];
  651. cursor_t * FZ_RESTRICT cr2 = &eb->cursor[2];
  652. if (cr0->unset)
  653. {
  654. assert(cr1->unset && cr2->unset);
  655. return;
  656. }
  657. iy0 = fixed2int(cr0->y) - base;
  658. iy1 = fixed2int(cr1->y) - base;
  659. if (!cr2->unset)
  660. {
  661. assert(!cr1->unset);
  662. iy2 = fixed2int(cr2->y) - base;
  663. /* Try to merge the end of cursor 0 with the end of cursor 1 */
  664. if (iy0 == iy1 && dirns_match(cr0->d, dirn_flip(cr1->d)))
  665. {
  666. /* Succeeded! Just one to output. */
  667. cr0->d = dirns_merge(cr0->d, dirn_flip(cr1->d));
  668. if (cr0->left > cr1->left)
  669. cr0->left = cr1->left;
  670. if (cr0->right < cr1->right)
  671. cr0->right = cr1->right;
  672. cr1->unset = 1; /* Stop us outputting cursor 1 later */
  673. }
  674. /* Try to merge the end of cursor 2 with the start of cursor 0 */
  675. if (cr0->saved)
  676. {
  677. if (cr0->save_iy == iy2 && dirns_match(cr0->save_d, cr2->d))
  678. {
  679. cr0->save_d = dirns_merge(cr0->save_d, cr2->d);
  680. if (cr0->save_left > cr2->left)
  681. cr0->save_left = cr2->left;
  682. if (cr0->save_right > cr2->right)
  683. cr0->save_right = cr2->right;
  684. cr2->unset = 1; /* Stop us outputting cursor 2 later */
  685. }
  686. }
  687. else
  688. {
  689. /* Maybe cursor 0 never moved from the original pixel */
  690. if (iy0 == iy2 && dirns_match(cr0->d, cr2->d))
  691. {
  692. cr0->d = dirns_merge(cr0->d, cr2->d);
  693. if (cr0->left > cr2->left)
  694. cr0->left = cr2->left;
  695. if (cr0->right > cr2->right)
  696. cr0->right = cr2->right;
  697. cr2->unset = 1; /* Stop us outputting cursor 2 later */
  698. }
  699. }
  700. /* Try to merge the start of cursor 2 with the start of cursor 1 */
  701. if (cr1->saved)
  702. {
  703. if (cr2->saved)
  704. {
  705. if (cr2->save_iy == cr1->save_iy && dirns_match(cr2->save_d, dirn_flip(cr1->save_d)))
  706. {
  707. cr2->save_d = dirns_merge(cr2->save_d, dirn_flip(cr1->save_d));
  708. if (cr2->save_left > cr1->save_left)
  709. cr2->save_left = cr1->save_left;
  710. if (cr2->save_right > cr1->save_right)
  711. cr2->save_right = cr1->save_right;
  712. cr1->saved = 0; /* Don't output cr1->saved again later */
  713. }
  714. }
  715. else if (!cr2->unset)
  716. {
  717. /* Maybe cursor 2 never moved from the original pixel */
  718. if (iy2 == cr1->save_iy && dirns_match(cr2->d, dirn_flip(cr1->save_d)))
  719. {
  720. cr2->d = dirns_merge(cr2->d, dirn_flip(cr1->save_d));
  721. if (cr2->left > cr1->save_left)
  722. cr2->left = cr1->save_left;
  723. if (cr2->right > cr1->save_right)
  724. cr2->right = cr1->save_right;
  725. cr1->saved = 0; /* Don't output cr1->saved again later */
  726. }
  727. }
  728. }
  729. else if (!cr1->unset)
  730. {
  731. /* Cursor 1 might not have moved from the original pixel, hence nothing saved */
  732. if (cr2->saved)
  733. {
  734. if (cr2->save_iy == iy1 && dirns_match(cr2->save_d, dirn_flip(cr1->d)))
  735. {
  736. cr2->save_d = dirns_merge(cr2->save_d, dirn_flip(cr1->d));
  737. if (cr2->save_left > cr1->left)
  738. cr2->save_left = cr1->left;
  739. if (cr2->save_right > cr1->right)
  740. cr2->save_right = cr1->right;
  741. cr1->unset = 1; /* Stop us outputting cursor 1 later */
  742. }
  743. }
  744. else if (!cr2->unset)
  745. {
  746. /* Maybe cursor 2 never moved from the original pixel */
  747. if (iy2 == iy1 && dirns_match(cr2->d, dirn_flip(cr1->d)))
  748. {
  749. cr2->d = dirns_merge(cr2->d, dirn_flip(cr1->d));
  750. if (cr2->left > cr1->left)
  751. cr2->left = cr1->left;
  752. if (cr2->right > cr1->right)
  753. cr2->right = cr1->right;
  754. cr1->unset = 1; /* Stop us outputting cursor 1 later */
  755. }
  756. }
  757. }
  758. else
  759. {
  760. /* Cursor 1 might not have moved from the original pixel, hence nothing saved,
  761. * AND we might have merged it with cursor 0 already! */
  762. if (cr2->saved)
  763. {
  764. if (iy0 == cr2->save_iy && dirns_match(cr0->d, cr2->save_d))
  765. {
  766. cr0->d = dirns_merge(cr0->d, cr2->save_d);
  767. if (cr0->left > cr2->save_left)
  768. cr0->left = cr2->save_left;
  769. if (cr0->right > cr2->save_right)
  770. cr0->right = cr2->save_right;
  771. cr2->saved = 0; /* Stop us outputting saved cursor 2 later */
  772. }
  773. }
  774. else if (!cr2->unset)
  775. {
  776. /* Maybe cursor 2 never moved from the original pixel */
  777. if (iy0 == iy2 && dirns_match(cr0->d, cr2->d))
  778. {
  779. cr0->d = dirns_merge(cr0->d, cr2->d);
  780. if (cr0->left > cr2->left)
  781. cr0->left = cr2->left;
  782. if (cr0->right > cr2->right)
  783. cr0->right = cr2->right;
  784. cr2->unset = 1; /* Stop us outputting cursor 2 later */
  785. }
  786. }
  787. }
  788. }
  789. else
  790. {
  791. iy2 = 0;
  792. /* Try to merge the end of cursor 0 with the start of cursor 0 */
  793. if (cr0->saved)
  794. {
  795. if (iy0 == cr0->save_iy && dirns_match(cr0->d, cr0->save_d))
  796. {
  797. cr0->d = dirns_merge(cr0->d, cr0->save_d);
  798. if (cr0->left > cr0->save_left)
  799. cr0->left = cr0->save_left;
  800. if (cr0->right > cr0->save_right)
  801. cr0->right = cr0->save_right;
  802. cr0->saved = 0; /* Stop us outputting saved cursor 0 later */
  803. }
  804. }
  805. if (!cr1->unset)
  806. {
  807. /* Try to merge the end of cursor 1 with the start of cursor 1 */
  808. if (cr1->saved)
  809. {
  810. if (iy1 == cr1->save_iy && dirns_match(cr1->d, cr1->save_d))
  811. {
  812. cr1->d = dirns_merge(cr1->d, cr1->save_d);
  813. if (cr1->left > cr1->save_left)
  814. cr1->left = cr1->save_left;
  815. if (cr1->right > cr1->save_right)
  816. cr1->right = cr1->save_right;
  817. cr1->saved = 0; /* Stop us outputting saved cursor 1 later */
  818. }
  819. }
  820. }
  821. }
  822. if (!cr0->unset)
  823. cursor_output(eb, 0, iy0);
  824. if (cr0->saved)
  825. {
  826. cr0->left = cr0->save_left;
  827. cr0->right = cr0->save_right;
  828. cr0->d = cr0->save_d;
  829. cursor_output(eb, 0, cr0->save_iy);
  830. }
  831. if (!cr1->unset)
  832. cursor_output(eb, 1, iy1);
  833. if (cr1->saved)
  834. {
  835. cr1->left = cr1->save_left;
  836. cr1->right = cr1->save_right;
  837. cr1->d = cr1->save_d;
  838. cursor_output(eb, 1, cr1->save_iy);
  839. }
  840. if (!cr2->unset)
  841. cursor_output(eb, 2, iy2);
  842. if (cr2->saved)
  843. {
  844. cr2->left = cr2->save_left;
  845. cr2->right = cr2->save_right;
  846. cr2->d = cr2->save_d;
  847. cursor_output(eb, 2, cr2->save_iy);
  848. }
  849. }
  850. static void do_mark_line_app(fz_context *ctx, fz_edgebuffer *eb, fixed sx, fixed sy, fixed ex, fixed ey, int rev)
  851. {
  852. int base_y = eb->super.clip.y0;
  853. int height = eb->super.clip.y1 - eb->super.clip.y0;
  854. int isy, iey;
  855. fixed y_steps;
  856. fixed save_sy = sy;
  857. fixed save_ex = ex;
  858. fixed save_ey = ey;
  859. int truncated;
  860. cursor_t * FZ_RESTRICT cr = &eb->cursor[rev];
  861. if (cr->unset)
  862. cr->y = sy, cr->left = sx, cr->right = sx, cr->unset = 0;
  863. /* Floating point inaccuracies can cause these not *quite* to be true. */
  864. assert(cr->y == sy && cr->left <= sx && cr->right >= sx && cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN);
  865. sy = cr->y;
  866. if (cr->left > sx)
  867. sx = cr->left;
  868. else if (cr->right < sx)
  869. sx = cr->right;
  870. if (sx == ex && sy == ey)
  871. return;
  872. isy = fixed2int(sy) - base_y;
  873. iey = fixed2int(ey) - base_y;
  874. #ifdef DEBUG_SCAN_CONVERTER
  875. if (debugging_scan_converter)
  876. fz_write_printf(ctx, fz_stderr(ctx), "Marking line (app) from %x,%x to %x,%x (%x,%x) %d\n", sx, sy, ex, ey, isy, iey, rev);
  877. #endif
  878. if (isy < iey) {
  879. /* Rising line */
  880. if (iey < 0 || isy >= height) {
  881. /* All line is outside. */
  882. cr->y = ey;
  883. cr->left = ex;
  884. cr->right = ex;
  885. cr->can_save = 0;
  886. return;
  887. }
  888. if (isy < 0) {
  889. /* Move sy up */
  890. int y = ey - sy;
  891. int new_sy = int2fixed(base_y);
  892. int dy = new_sy - sy;
  893. sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y);
  894. sy = new_sy;
  895. cursor_init(eb, rev, sy, sx);
  896. isy = 0;
  897. }
  898. truncated = iey > height;
  899. if (truncated) {
  900. /* Move ey down */
  901. int y = ey - sy;
  902. int new_ey = int2fixed(base_y + height);
  903. int dy = ey - new_ey;
  904. save_ex = ex;
  905. save_ey = ey;
  906. ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y);
  907. ey = new_ey;
  908. iey = height;
  909. }
  910. } else {
  911. /* Falling line */
  912. if (isy < 0 || iey >= height) {
  913. /* All line is outside. */
  914. cr->y = ey;
  915. cr->left = ex;
  916. cr->right = ex;
  917. cr->can_save = 0;
  918. return;
  919. }
  920. truncated = iey < 0;
  921. if (truncated) {
  922. /* Move ey up */
  923. int y = ey - sy;
  924. int new_ey = int2fixed(base_y);
  925. int dy = ey - new_ey;
  926. ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y);
  927. ey = new_ey;
  928. iey = 0;
  929. }
  930. if (isy >= height) {
  931. /* Move sy down */
  932. int y = ey - sy;
  933. if (y) {
  934. int new_sy = int2fixed(base_y + height);
  935. int dy = new_sy - sy;
  936. sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y);
  937. sy = new_sy;
  938. cursor_init(eb, rev, sy, sx);
  939. isy = height;
  940. }
  941. }
  942. }
  943. assert(cr->left <= sx);
  944. assert(cr->right >= sx);
  945. assert(cr->y == sy);
  946. /* A note: The code below used to be of the form:
  947. * if (isy == iey) ... deal with horizontal lines
  948. * else if (ey > sy) {
  949. * fixed y_steps = ey - sy;
  950. * ... deal with rising lines ...
  951. * } else {
  952. * fixed y_steps = ey - sy;
  953. * ... deal with falling lines
  954. * }
  955. * but that lead to problems, for instance, an example seen
  956. * has sx=2aa8e, sy=8aee7, ex=7ffc1686, ey=8003e97a.
  957. * Thus isy=84f, iey=ff80038a. We can see that ey < sy, but
  958. * sy - ey < 0!
  959. * We therefore rejig our code so that the choice between
  960. * cases is done based on the sign of y_steps rather than
  961. * the relative size of ey and sy.
  962. */
  963. /* First, deal with lines that don't change scanline.
  964. * This accommodates horizontal lines. */
  965. if (isy == iey) {
  966. if (save_sy == save_ey) {
  967. /* Horizontal line. Don't change cr->d, don't flush. */
  968. } else if (save_sy > save_ey) {
  969. /* Falling line, flush if previous was rising */
  970. cursor_down(eb, rev, sx);
  971. } else {
  972. /* Rising line, flush if previous was falling */
  973. cursor_up(eb, rev, sx);
  974. }
  975. if (sx <= ex) {
  976. cursor_left_merge(eb, rev, sx);
  977. cursor_right_merge(eb, rev, ex);
  978. } else {
  979. cursor_left_merge(eb, rev, ex);
  980. cursor_right_merge(eb, rev, sx);
  981. }
  982. cr->y = ey;
  983. if (sy > save_ey)
  984. goto endFalling;
  985. } else if ((y_steps = ey - sy) > 0) {
  986. /* We want to change from sy to ey, which are guaranteed to be on
  987. * different scanlines. We do this in 3 phases.
  988. * Phase 1 gets us from sy to the next scanline boundary.
  989. * Phase 2 gets us all the way to the last scanline boundary.
  990. * Phase 3 gets us from the last scanline boundary to ey.
  991. */
  992. /* We want to change from sy to ey, which are guaranteed to be on
  993. * different scanlines. We do this in 3 phases.
  994. * Phase 1 gets us from sy to the next scanline boundary. (We may exit after phase 1).
  995. * Phase 2 gets us all the way to the last scanline boundary. (This may be a null operation)
  996. * Phase 3 gets us from the last scanline boundary to ey. (We are guaranteed to have output the cursor at least once before phase 3).
  997. */
  998. int phase1_y_steps = (-sy) & (fixed_1 - 1);
  999. int phase3_y_steps = ey & (fixed_1 - 1);
  1000. cursor_up(eb, rev, sx);
  1001. if (sx == ex) {
  1002. /* Vertical line. (Rising) */
  1003. /* Phase 1: */
  1004. cursor_left_merge(eb, rev, sx);
  1005. cursor_right_merge(eb, rev, sx);
  1006. if (phase1_y_steps) {
  1007. /* If phase 1 will move us into a new scanline, then we must
  1008. * flush it before we move. */
  1009. cursor_step(eb, rev, phase1_y_steps, sx);
  1010. sy += phase1_y_steps;
  1011. y_steps -= phase1_y_steps;
  1012. if (y_steps == 0)
  1013. goto end;
  1014. }
  1015. /* Phase 3: precalculation */
  1016. y_steps -= phase3_y_steps;
  1017. /* Phase 2: */
  1018. y_steps = fixed2int(y_steps);
  1019. assert(y_steps >= 0);
  1020. if (y_steps > 0) {
  1021. cursor_always_step(eb, rev, fixed_1, sx);
  1022. y_steps--;
  1023. while (y_steps) {
  1024. cursor_always_step_inrange_vertical(eb, rev, fixed_1, sx);
  1025. y_steps--;
  1026. }
  1027. }
  1028. /* Phase 3 */
  1029. assert(cr->left == sx && cr->right == sx);
  1030. cr->y += phase3_y_steps;
  1031. } else if (sx < ex) {
  1032. /* Lines increasing in x. (Rightwards, rising) */
  1033. int phase1_x_steps, phase3_x_steps;
  1034. fixed x_steps = ex - sx;
  1035. /* Phase 1: */
  1036. cursor_left_merge(eb, rev, sx);
  1037. if (phase1_y_steps) {
  1038. phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
  1039. sx += phase1_x_steps;
  1040. cursor_right_merge(eb, rev, sx);
  1041. x_steps -= phase1_x_steps;
  1042. cursor_step(eb, rev, phase1_y_steps, sx);
  1043. sy += phase1_y_steps;
  1044. y_steps -= phase1_y_steps;
  1045. if (y_steps == 0)
  1046. goto end;
  1047. }
  1048. /* Phase 3: precalculation */
  1049. phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
  1050. x_steps -= phase3_x_steps;
  1051. y_steps -= phase3_y_steps;
  1052. assert((y_steps & (fixed_1 - 1)) == 0);
  1053. /* Phase 2: */
  1054. y_steps = fixed2int(y_steps);
  1055. assert(y_steps >= 0);
  1056. if (y_steps) {
  1057. /* We want to change sx by x_steps in y_steps steps.
  1058. * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/y_steps. */
  1059. int x_inc = x_steps/y_steps;
  1060. int n_inc = x_steps - (x_inc * y_steps);
  1061. int f = y_steps/2;
  1062. int d = y_steps;
  1063. /* Special casing the unset iteration, allows us to simplify
  1064. * the following loop. */
  1065. sx += x_inc;
  1066. f -= n_inc;
  1067. if (f < 0)
  1068. f += d, sx++;
  1069. cursor_right_merge(eb, rev, sx);
  1070. cursor_always_step(eb, rev, fixed_1, sx);
  1071. y_steps--;
  1072. while (y_steps) {
  1073. sx += x_inc;
  1074. f -= n_inc;
  1075. if (f < 0)
  1076. f += d, sx++;
  1077. cursor_right(eb, rev, sx);
  1078. cursor_always_inrange_step_right(eb, rev, fixed_1, sx);
  1079. y_steps--;
  1080. };
  1081. }
  1082. /* Phase 3 */
  1083. assert(cr->left <= ex && cr->right >= sx);
  1084. cursor_right(eb, rev, ex);
  1085. cr->y += phase3_y_steps;
  1086. } else {
  1087. /* Lines decreasing in x. (Leftwards, rising) */
  1088. int phase1_x_steps, phase3_x_steps;
  1089. fixed x_steps = sx - ex;
  1090. /* Phase 1: */
  1091. cursor_right_merge(eb, rev, sx);
  1092. if (phase1_y_steps) {
  1093. phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
  1094. x_steps -= phase1_x_steps;
  1095. sx -= phase1_x_steps;
  1096. cursor_left_merge(eb, rev, sx);
  1097. cursor_step(eb, rev, phase1_y_steps, sx);
  1098. sy += phase1_y_steps;
  1099. y_steps -= phase1_y_steps;
  1100. if (y_steps == 0)
  1101. goto end;
  1102. }
  1103. /* Phase 3: precalculation */
  1104. phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
  1105. x_steps -= phase3_x_steps;
  1106. y_steps -= phase3_y_steps;
  1107. assert((y_steps & (fixed_1 - 1)) == 0);
  1108. /* Phase 2: */
  1109. y_steps = fixed2int(y_steps);
  1110. assert(y_steps >= 0);
  1111. if (y_steps) {
  1112. /* We want to change sx by x_steps in y_steps steps.
  1113. * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
  1114. int x_inc = x_steps/y_steps;
  1115. int n_inc = x_steps - (x_inc * y_steps);
  1116. int f = y_steps/2;
  1117. int d = y_steps;
  1118. /* Special casing the unset iteration, allows us to simplify
  1119. * the following loop. */
  1120. sx -= x_inc;
  1121. f -= n_inc;
  1122. if (f < 0)
  1123. f += d, sx--;
  1124. cursor_left_merge(eb, rev, sx);
  1125. cursor_always_step(eb, rev, fixed_1, sx);
  1126. y_steps--;
  1127. while (y_steps) {
  1128. sx -= x_inc;
  1129. f -= n_inc;
  1130. if (f < 0)
  1131. f += d, sx--;
  1132. cursor_left(eb, rev, sx);
  1133. cursor_always_inrange_step_left(eb, rev, fixed_1, sx);
  1134. y_steps--;
  1135. }
  1136. }
  1137. /* Phase 3 */
  1138. assert(cr->right >= ex && cr->left <= sx);
  1139. cursor_left(eb, rev, ex);
  1140. cr->y += phase3_y_steps;
  1141. }
  1142. } else {
  1143. /* So lines decreasing in y. */
  1144. /* We want to change from sy to ey, which are guaranteed to be on
  1145. * different scanlines. We do this in 3 phases.
  1146. * Phase 1 gets us from sy to the next scanline boundary. This never causes an output.
  1147. * Phase 2 gets us all the way to the last scanline boundary. This is guaranteed to cause an output.
  1148. * Phase 3 gets us from the last scanline boundary to ey. We are guaranteed to have outputted by now.
  1149. */
  1150. int phase1_y_steps = sy & (fixed_1 - 1);
  1151. int phase3_y_steps = (-ey) & (fixed_1 - 1);
  1152. y_steps = -y_steps;
  1153. /* Cope with the awkward 0x80000000 case. */
  1154. if (y_steps < 0)
  1155. {
  1156. int mx, my;
  1157. mx = sx + ((ex-sx)>>1);
  1158. my = sy + ((ey-sy)>>1);
  1159. do_mark_line_app(ctx, eb, sx, sy, mx, my, rev);
  1160. do_mark_line_app(ctx, eb, mx, my, ex, ey, rev);
  1161. return;
  1162. }
  1163. cursor_down(eb, rev, sx);
  1164. if (sx == ex) {
  1165. /* Vertical line. (Falling) */
  1166. /* Phase 1: */
  1167. cursor_left_merge(eb, rev, sx);
  1168. cursor_right_merge(eb, rev, sx);
  1169. if (phase1_y_steps) {
  1170. /* Phase 1 in a falling line never moves us into a new scanline. */
  1171. cursor_never_step_vertical(eb, rev, -phase1_y_steps, sx);
  1172. sy -= phase1_y_steps;
  1173. y_steps -= phase1_y_steps;
  1174. if (y_steps == 0)
  1175. goto endFalling;
  1176. }
  1177. /* Phase 3: precalculation */
  1178. y_steps -= phase3_y_steps;
  1179. assert((y_steps & (fixed_1 - 1)) == 0);
  1180. /* Phase 2: */
  1181. y_steps = fixed2int(y_steps);
  1182. assert(y_steps >= 0);
  1183. if (y_steps) {
  1184. cursor_always_step(eb, rev, -fixed_1, sx);
  1185. y_steps--;
  1186. while (y_steps) {
  1187. cursor_always_step_inrange_vertical(eb, rev, -fixed_1, sx);
  1188. y_steps--;
  1189. }
  1190. }
  1191. /* Phase 3 */
  1192. if (phase3_y_steps > 0) {
  1193. cursor_step(eb, rev, -phase3_y_steps, sx);
  1194. assert(cr->left == sx && cr->right == sx);
  1195. }
  1196. } else if (sx < ex) {
  1197. /* Lines increasing in x. (Rightwards, falling) */
  1198. int phase1_x_steps, phase3_x_steps;
  1199. fixed x_steps = ex - sx;
  1200. /* Phase 1: */
  1201. cursor_left_merge(eb, rev, sx);
  1202. if (phase1_y_steps) {
  1203. phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
  1204. x_steps -= phase1_x_steps;
  1205. sx += phase1_x_steps;
  1206. /* Phase 1 in a falling line never moves us into a new scanline. */
  1207. cursor_never_step_right(eb, rev, -phase1_y_steps, sx);
  1208. sy -= phase1_y_steps;
  1209. y_steps -= phase1_y_steps;
  1210. if (y_steps == 0)
  1211. goto endFalling;
  1212. } else
  1213. cursor_right_merge(eb, rev, sx);
  1214. /* Phase 3: precalculation */
  1215. phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
  1216. x_steps -= phase3_x_steps;
  1217. y_steps -= phase3_y_steps;
  1218. assert((y_steps & (fixed_1 - 1)) == 0);
  1219. /* Phase 2: */
  1220. y_steps = fixed2int(y_steps);
  1221. assert(y_steps >= 0);
  1222. if (y_steps) {
  1223. /* We want to change sx by x_steps in y_steps steps.
  1224. * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/ey. */
  1225. int x_inc = x_steps/y_steps;
  1226. int n_inc = x_steps - (x_inc * y_steps);
  1227. int f = y_steps/2;
  1228. int d = y_steps;
  1229. cursor_always_step(eb, rev, -fixed_1, sx);
  1230. sx += x_inc;
  1231. f -= n_inc;
  1232. if (f < 0)
  1233. f += d, sx++;
  1234. cursor_right(eb, rev, sx);
  1235. y_steps--;
  1236. while (y_steps) {
  1237. cursor_always_inrange_step_right(eb, rev, -fixed_1, sx);
  1238. sx += x_inc;
  1239. f -= n_inc;
  1240. if (f < 0)
  1241. f += d, sx++;
  1242. cursor_right(eb, rev, sx);
  1243. y_steps--;
  1244. }
  1245. }
  1246. /* Phase 3 */
  1247. if (phase3_y_steps > 0) {
  1248. cursor_step(eb, rev, -phase3_y_steps, sx);
  1249. cursor_right(eb, rev, ex);
  1250. assert(cr->left == sx && cr->right == ex);
  1251. }
  1252. } else {
  1253. /* Lines decreasing in x. (Falling) */
  1254. int phase1_x_steps, phase3_x_steps;
  1255. fixed x_steps = sx - ex;
  1256. /* Phase 1: */
  1257. cursor_right_merge(eb, rev, sx);
  1258. if (phase1_y_steps) {
  1259. phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
  1260. x_steps -= phase1_x_steps;
  1261. sx -= phase1_x_steps;
  1262. /* Phase 1 in a falling line never moves us into a new scanline. */
  1263. cursor_never_step_left(eb, rev, -phase1_y_steps, sx);
  1264. sy -= phase1_y_steps;
  1265. y_steps -= phase1_y_steps;
  1266. if (y_steps == 0)
  1267. goto endFalling;
  1268. } else
  1269. cursor_left_merge(eb, rev, sx);
  1270. /* Phase 3: precalculation */
  1271. phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
  1272. x_steps -= phase3_x_steps;
  1273. y_steps -= phase3_y_steps;
  1274. assert((y_steps & (fixed_1 - 1)) == 0);
  1275. /* Phase 2: */
  1276. y_steps = fixed2int(y_steps);
  1277. assert(y_steps >= 0);
  1278. if (y_steps) {
  1279. /* We want to change sx by x_steps in y_steps steps.
  1280. * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
  1281. int x_inc = x_steps/y_steps;
  1282. int n_inc = x_steps - (x_inc * y_steps);
  1283. int f = y_steps/2;
  1284. int d = y_steps;
  1285. cursor_always_step(eb, rev, -fixed_1, sx);
  1286. sx -= x_inc;
  1287. f -= n_inc;
  1288. if (f < 0)
  1289. f += d, sx--;
  1290. cursor_left(eb, rev, sx);
  1291. y_steps--;
  1292. while (y_steps) {
  1293. cursor_always_inrange_step_left(eb, rev, -fixed_1, sx);
  1294. sx -= x_inc;
  1295. f -= n_inc;
  1296. if (f < 0)
  1297. f += d, sx--;
  1298. cursor_left(eb, rev, sx);
  1299. y_steps--;
  1300. }
  1301. }
  1302. /* Phase 3 */
  1303. if (phase3_y_steps > 0) {
  1304. cursor_step(eb, rev, -phase3_y_steps, sx);
  1305. cursor_left(eb, rev, ex);
  1306. assert(cr->left == ex && cr->right == sx);
  1307. }
  1308. }
  1309. endFalling:
  1310. if (truncated)
  1311. cursor_output(eb, rev, fixed2int(cr->y) - base_y);
  1312. }
  1313. end:
  1314. if (truncated) {
  1315. cr->left = save_ex;
  1316. cr->right = save_ex;
  1317. cr->y = save_ey;
  1318. }
  1319. }
  1320. static void mark_line_app(fz_context *ctx, fz_edgebuffer *eb, fixed sx, fixed sy, fixed ex, fixed ey, int rev)
  1321. {
  1322. if (rev == 1)
  1323. {
  1324. fixed t;
  1325. t = sx, sx = ex, ex = t;
  1326. t = sy, sy = ey, ey = t;
  1327. }
  1328. do_mark_line_app(ctx, eb, sx, sy, ex, ey, rev);
  1329. }
  1330. static void fz_insert_edgebuffer_app(fz_context *ctx, fz_rasterizer *ras, float fsx, float fsy, float fex, float fey, int rev)
  1331. {
  1332. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  1333. fixed sx = safe_float2fixed(fsx);
  1334. fixed sy = safe_float2fixed(fsy);
  1335. fixed ex = safe_float2fixed(fex);
  1336. fixed ey = safe_float2fixed(fey);
  1337. if (fsx < fex)
  1338. {
  1339. if (fsx < eb->super.bbox.x0) eb->super.bbox.x0 = fsx;
  1340. if (fex > eb->super.bbox.x1) eb->super.bbox.x1 = fex;
  1341. }
  1342. else
  1343. {
  1344. if (fsx > eb->super.bbox.x1) eb->super.bbox.x1 = fsx;
  1345. if (fex < eb->super.bbox.x0) eb->super.bbox.x0 = fex;
  1346. }
  1347. if (fsy < fey)
  1348. {
  1349. if (fsy < eb->super.bbox.y0) eb->super.bbox.y0 = fsy;
  1350. if (fey > eb->super.bbox.y1) eb->super.bbox.y1 = fey;
  1351. }
  1352. else
  1353. {
  1354. if (fey < eb->super.bbox.y0) eb->super.bbox.y0 = fey;
  1355. if (fsy > eb->super.bbox.y1) eb->super.bbox.y1 = fsy;
  1356. }
  1357. mark_line_app(ctx, eb, sx, sy, ex, ey, rev);
  1358. }
  1359. static int intcmp(const void *a, const void *b)
  1360. {
  1361. return *((int*)a) - *((int *)b);
  1362. }
  1363. static void fz_convert_edgebuffer(fz_context *ctx, fz_rasterizer *ras, int eofill, const fz_irect *clip, fz_pixmap *pix, unsigned char *color, fz_overprint *eop)
  1364. {
  1365. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  1366. int scanlines = ras->clip.y1 - ras->clip.y0;
  1367. int i, n, a, pl, pr;
  1368. int *table = eb->table;
  1369. int *index = eb->index;
  1370. uint8_t *out;
  1371. fz_solid_color_painter_t *fn;
  1372. fn = fz_get_solid_color_painter(pix->n, color, pix->alpha, eop);
  1373. assert(fn);
  1374. if (fn == NULL)
  1375. return;
  1376. #ifdef DEBUG_SCAN_CONVERTER
  1377. if (debugging_scan_converter)
  1378. {
  1379. fz_output *err = fz_stderr(ctx);
  1380. fz_write_printf(ctx, err, "Before sort:\n");
  1381. fz_edgebuffer_print(ctx, err, eb);
  1382. }
  1383. #endif
  1384. if (!eb->sorted)
  1385. {
  1386. eb->sorted = 1;
  1387. for (i = 0; i < scanlines; i++)
  1388. {
  1389. int *row = &table[index[i]];
  1390. int rowlen = *row++;
  1391. /* Bubblesort short runs, qsort longer ones. */
  1392. /* FIXME: Check "6" below */
  1393. if (rowlen <= 6) {
  1394. int j, k;
  1395. for (j = 0; j < rowlen-1; j++)
  1396. {
  1397. int t = row[j];
  1398. for (k = j+1; k < rowlen; k++)
  1399. {
  1400. int s = row[k];
  1401. if (t > s)
  1402. row[k] = t, t = row[j] = s;
  1403. }
  1404. }
  1405. } else
  1406. qsort(row, rowlen, sizeof(int), intcmp);
  1407. }
  1408. #ifdef DEBUG_SCAN_CONVERTER
  1409. if (debugging_scan_converter)
  1410. {
  1411. fz_output *err = fz_stderr(ctx);
  1412. fz_write_printf(ctx, err, "Before filter: %s\n", eofill ? "EO" : "NZ");
  1413. fz_edgebuffer_print(ctx, err, eb);
  1414. }
  1415. #endif
  1416. for (i=0; i < scanlines; i++) {
  1417. int *row = &table[index[i]];
  1418. int *rowstart = row;
  1419. int rowlen = *row++;
  1420. int *rowout = row;
  1421. while (rowlen > 0)
  1422. {
  1423. int left, right;
  1424. if (eofill) {
  1425. /* Even Odd */
  1426. left = (*row++)&~1;
  1427. right = (*row++)&~1;
  1428. rowlen -= 2;
  1429. } else {
  1430. /* Non-Zero */
  1431. int w;
  1432. left = *row++;
  1433. w = ((left&1)-1) | (left&1);
  1434. rowlen--;
  1435. do {
  1436. right = *row++;
  1437. rowlen--;
  1438. w += ((right&1)-1) | (right&1);
  1439. } while (w != 0);
  1440. left &= ~1;
  1441. right &= ~1;
  1442. }
  1443. if (right > left) {
  1444. *rowout++ = left;
  1445. *rowout++ = right;
  1446. }
  1447. }
  1448. *rowstart = (rowout-rowstart)-1;
  1449. }
  1450. }
  1451. #ifdef DEBUG_SCAN_CONVERTER
  1452. if (debugging_scan_converter)
  1453. {
  1454. fz_output *err = fz_stderr(ctx);
  1455. fz_write_printf(ctx, err, "Before render:\n");
  1456. fz_edgebuffer_print(ctx, err, eb);
  1457. }
  1458. #endif
  1459. n = pix->n;
  1460. a = pix->alpha;
  1461. pl = fz_maxi(ras->clip.x0, pix->x);
  1462. pr = fz_mini(ras->clip.x1, pix->x + pix->w);
  1463. pr -= pl;
  1464. out = pix->samples + pix->stride * fz_maxi(ras->clip.y0 - pix->y, 0) + fz_maxi(ras->clip.x0 - pix->x, 0) * n;
  1465. if (scanlines > pix->y + pix->h - ras->clip.y0)
  1466. scanlines = pix->y + pix->h - ras->clip.y0;
  1467. for (i = fz_maxi(pix->y - ras->clip.y0, 0); i < scanlines; i++) {
  1468. int *row = &table[index[i]];
  1469. int rowlen = *row++;
  1470. while (rowlen > 0) {
  1471. int left, right;
  1472. left = *row++;
  1473. right = *row++;
  1474. rowlen -= 2;
  1475. left = fixed2int(left + fixed_half) - pl;
  1476. right = fixed2int(right + fixed_half) - pl;
  1477. if (right <= 0)
  1478. continue;
  1479. if (left >= pr)
  1480. continue;
  1481. if (right > pr)
  1482. right = pr;
  1483. if (left < 0)
  1484. left = 0;
  1485. right -= left;
  1486. if (right > 0) {
  1487. (*fn)(out + left*n, n, right, color, a, eop);
  1488. }
  1489. }
  1490. out += pix->stride;
  1491. }
  1492. }
  1493. static int edgecmp(const void *a, const void *b)
  1494. {
  1495. int left = ((int*)a)[0];
  1496. int right = ((int*)b)[0];
  1497. left -= right;
  1498. if (left)
  1499. return left;
  1500. return ((int*)a)[1] - ((int*)b)[1];
  1501. }
  1502. static void fz_convert_edgebuffer_app(fz_context *ctx, fz_rasterizer *ras, int eofill, const fz_irect *clip, fz_pixmap *pix, unsigned char *color, fz_overprint *eop)
  1503. {
  1504. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  1505. int scanlines = ras->clip.y1 - ras->clip.y0;
  1506. int i, n, a, pl, pr;
  1507. int *table = eb->table;
  1508. int *index = eb->index;
  1509. uint8_t *out;
  1510. fz_solid_color_painter_t *fn;
  1511. fn = fz_get_solid_color_painter(pix->n, color, pix->alpha, eop);
  1512. assert(fn);
  1513. if (fn == NULL)
  1514. return;
  1515. #ifdef DEBUG_SCAN_CONVERTER
  1516. if (debugging_scan_converter)
  1517. {
  1518. fz_output *err = fz_stderr(ctx);
  1519. fz_write_printf(ctx, err, "Before sort:\n");
  1520. fz_edgebuffer_print_app(ctx, err, eb);
  1521. }
  1522. #endif
  1523. if (!eb->sorted)
  1524. {
  1525. eb->sorted = 1;
  1526. for (i = 0; i < scanlines; i++)
  1527. {
  1528. int *row = &table[index[i]];
  1529. int rowlen = *row++;
  1530. /* Bubblesort short runs, qsort longer ones. */
  1531. /* FIXME: Check "6" below */
  1532. if (rowlen <= 6) {
  1533. int j, k;
  1534. for (j = 0; j < rowlen-1; j++) {
  1535. int * FZ_RESTRICT t = &row[j<<1];
  1536. for (k = j+1; k < rowlen; k++) {
  1537. int * FZ_RESTRICT s = &row[k<<1];
  1538. int tmp;
  1539. if (t[0] < s[0])
  1540. continue;
  1541. if (t[0] > s[0])
  1542. tmp = t[0], t[0] = s[0], s[0] = tmp;
  1543. else if (t[0] <= s[1])
  1544. continue;
  1545. tmp = t[1]; t[1] = s[1]; s[1] = tmp;
  1546. }
  1547. }
  1548. } else
  1549. qsort(row, rowlen, 2*sizeof(int), edgecmp);
  1550. }
  1551. #ifdef DEBUG_SCAN_CONVERTER
  1552. if (debugging_scan_converter)
  1553. {
  1554. fz_output *err = fz_stderr(ctx);
  1555. fz_write_printf(ctx, err, "Before filter: %s\n", eofill ? "EO" : "NZ");
  1556. fz_edgebuffer_print_app(ctx, err, eb);
  1557. }
  1558. #endif
  1559. for (i=0; i < scanlines; i++) {
  1560. int *row = &table[index[i]];
  1561. int rowlen = *row++;
  1562. int *rowstart = row;
  1563. int *rowout = row;
  1564. int ll, lr, rl, rr, wind, marked_to;
  1565. /* Avoid double setting pixels, by keeping where we have marked to. */
  1566. marked_to = int2fixed(clip->x0);
  1567. while (rowlen > 0) {
  1568. if (eofill) {
  1569. /* Even Odd */
  1570. ll = (*row++)&~1;
  1571. lr = *row;
  1572. row += 2;
  1573. rowlen-=2;
  1574. /* We will fill solidly from ll to at least lr, possibly further */
  1575. assert(rowlen >= 0);
  1576. rr = (*row++);
  1577. if (rr > lr)
  1578. lr = rr;
  1579. } else {
  1580. /* Non-Zero */
  1581. int w;
  1582. ll = *row++;
  1583. lr = *row++;
  1584. wind = -(ll&1) | 1;
  1585. ll &= ~1;
  1586. rowlen--;
  1587. assert(rowlen > 0);
  1588. do {
  1589. rl = *row++;
  1590. rr = *row++;
  1591. w = -(rl&1) | 1;
  1592. /* rl &= ~1; */
  1593. rowlen--;
  1594. if (rr > lr)
  1595. lr = rr;
  1596. wind += w;
  1597. if (wind == 0)
  1598. break;
  1599. } while (rowlen > 0);
  1600. }
  1601. if (marked_to >= lr)
  1602. continue;
  1603. if (marked_to >= ll) {
  1604. if (rowout == rowstart)
  1605. ll = marked_to;
  1606. else {
  1607. rowout -= 2;
  1608. ll = *rowout;
  1609. }
  1610. }
  1611. if (lr > ll) {
  1612. *rowout++ = ll;
  1613. *rowout++ = lr;
  1614. marked_to = lr;
  1615. }
  1616. }
  1617. rowstart[-1] = rowout-rowstart;
  1618. }
  1619. }
  1620. #ifdef DEBUG_SCAN_CONVERTER
  1621. if (debugging_scan_converter)
  1622. {
  1623. fz_output *err = fz_stderr(ctx);
  1624. fz_write_printf(ctx, err, "Before render:\n");
  1625. fz_edgebuffer_print_app(ctx, err, eb);
  1626. }
  1627. #endif
  1628. n = pix->n;
  1629. a = pix->alpha;
  1630. pl = clip->x0;
  1631. pr = clip->x1 - pl;
  1632. out = pix->samples + pix->stride * (clip->y0 - pix->y) + (clip->x0 - pix->x) * n;
  1633. if (scanlines > clip->y1 - ras->clip.y0)
  1634. scanlines = clip->y1 - ras->clip.y0;
  1635. i = (clip->y0 - ras->clip.y0);
  1636. if (i < 0)
  1637. return;
  1638. for (; i < scanlines; i++) {
  1639. int *row = &table[index[i]];
  1640. int rowlen = *row++;
  1641. while (rowlen > 0) {
  1642. int left, right;
  1643. left = *row++;
  1644. right = *row++;
  1645. rowlen -= 2;
  1646. left = fixed2int(left + fixed_half) - pl;
  1647. right = fixed2int(right + fixed_half) - pl;
  1648. if (right <= 0)
  1649. continue;
  1650. if (left >= pr)
  1651. break;
  1652. if (right > pr)
  1653. right = pr;
  1654. if (left < 0)
  1655. left = 0;
  1656. right -= left;
  1657. if (right > 0) {
  1658. (*fn)(out + left*n, n, right, color, a, eop);
  1659. }
  1660. }
  1661. out += pix->stride;
  1662. }
  1663. }
  1664. static void fz_gap_edgebuffer(fz_context *ctx, fz_rasterizer *ras)
  1665. {
  1666. fz_edgebuffer *eb = (fz_edgebuffer *)ras;
  1667. if (eb->app)
  1668. {
  1669. #ifdef DEBUG_SCAN_CONVERTER
  1670. if (0 && debugging_scan_converter)
  1671. {
  1672. fz_output *err = fz_stderr(ctx);
  1673. fz_write_printf(ctx, fz_stderr(ctx), "Pen up move.\n");
  1674. fz_write_printf(ctx, err, "Before flush:\n");
  1675. fz_edgebuffer_print_app(ctx, err, eb);
  1676. }
  1677. #endif
  1678. cursor_flush(eb);
  1679. eb->cursor[0].saved = 0;
  1680. eb->cursor[0].unset = 1;
  1681. eb->cursor[0].can_save = 1;
  1682. eb->cursor[0].d = DIRN_UNSET;
  1683. eb->cursor[1].saved = 0;
  1684. eb->cursor[1].unset = 1;
  1685. eb->cursor[1].can_save = 1;
  1686. eb->cursor[1].d = DIRN_UNSET;
  1687. eb->cursor[2].saved = 0;
  1688. eb->cursor[2].unset = 1;
  1689. eb->cursor[2].can_save = 1;
  1690. eb->cursor[2].d = DIRN_UNSET;
  1691. }
  1692. }
  1693. static int fz_is_rect_edgebuffer(fz_context *ctx, fz_rasterizer *r)
  1694. {
  1695. return 0;
  1696. }
  1697. static const fz_rasterizer_fns edgebuffer_app =
  1698. {
  1699. fz_drop_edgebuffer,
  1700. fz_reset_edgebuffer,
  1701. fz_postindex_edgebuffer,
  1702. fz_insert_edgebuffer_app,
  1703. NULL,
  1704. fz_gap_edgebuffer,
  1705. fz_convert_edgebuffer_app,
  1706. fz_is_rect_edgebuffer,
  1707. 1 /* Reusable */
  1708. };
  1709. static const fz_rasterizer_fns edgebuffer_cop =
  1710. {
  1711. fz_drop_edgebuffer,
  1712. fz_reset_edgebuffer,
  1713. fz_postindex_edgebuffer,
  1714. fz_insert_edgebuffer,
  1715. NULL,
  1716. NULL, /* gap */
  1717. fz_convert_edgebuffer,
  1718. fz_is_rect_edgebuffer,
  1719. 1 /* Reusable */
  1720. };
  1721. fz_rasterizer *
  1722. fz_new_edgebuffer(fz_context *ctx, fz_edgebuffer_rule rule)
  1723. {
  1724. fz_edgebuffer *eb;
  1725. eb = fz_new_derived_rasterizer(ctx, fz_edgebuffer, rule == FZ_EDGEBUFFER_ANY_PART_OF_PIXEL ? &edgebuffer_app : &edgebuffer_cop);
  1726. eb->app = rule == FZ_EDGEBUFFER_ANY_PART_OF_PIXEL;
  1727. return &eb->super;
  1728. }