/inkscape-0.48.2/src/livarot/int-line.cpp

# · C++ · 1070 lines · 842 code · 114 blank · 114 comment · 331 complexity · 3b64dfe820aa3be1b2c215657868aca2 MD5 · raw file

  1. /**
  2. * \file livarot/int-line.cpp
  3. *
  4. * Implementation of coverage with integer boundaries.
  5. *
  6. * \author Fred
  7. *
  8. * public domain
  9. *
  10. */
  11. #include <glib.h>
  12. #include <cmath>
  13. #include <cstring>
  14. #include <string>
  15. #include <cstdlib>
  16. #include <cstdio>
  17. #include "livarot/int-line.h"
  18. #include "livarot/float-line.h"
  19. #include "livarot/BitLigne.h"
  20. IntLigne::IntLigne()
  21. {
  22. nbBord = maxBord = 0;
  23. bords = NULL;
  24. nbRun = maxRun = 0;
  25. runs = NULL;
  26. firstAc = lastAc = -1;
  27. }
  28. IntLigne::~IntLigne()
  29. {
  30. if ( maxBord > 0 ) {
  31. g_free(bords);
  32. nbBord = maxBord = 0;
  33. bords = NULL;
  34. }
  35. if ( maxRun > 0 ) {
  36. g_free(runs);
  37. nbRun = maxRun = 0;
  38. runs = NULL;
  39. }
  40. }
  41. void IntLigne::Reset()
  42. {
  43. nbBord = 0;
  44. nbRun = 0;
  45. firstAc = lastAc = -1;
  46. }
  47. int IntLigne::AddBord(int spos, float sval, int epos, float eval)
  48. {
  49. if ( nbBord + 1 >= maxBord ) {
  50. maxBord = 2 * nbBord + 2;
  51. bords = (int_ligne_bord *) g_realloc(bords, maxBord * sizeof(int_ligne_bord));
  52. }
  53. int n = nbBord++;
  54. bords[n].pos = spos;
  55. bords[n].val = sval;
  56. bords[n].start = true;
  57. bords[n].other = n+1;
  58. bords[n].prev = bords[n].next = -1;
  59. n = nbBord++;
  60. bords[n].pos = epos;
  61. bords[n].val = eval;
  62. bords[n].start = false;
  63. bords[n].other = n-1;
  64. bords[n].prev = bords[n].next = -1;
  65. return n - 1;
  66. }
  67. float IntLigne::RemainingValAt(int at)
  68. {
  69. int no = firstAc;
  70. float sum = 0;
  71. while ( no >= 0 ) {
  72. int nn = bords[no].other;
  73. sum += ValAt(at, bords[nn].pos, bords[no].pos, bords[nn].val, bords[no].val);
  74. no = bords[no].next;
  75. }
  76. return sum;
  77. }
  78. void IntLigne::Flatten()
  79. {
  80. if ( nbBord <= 1 ) {
  81. Reset();
  82. return;
  83. }
  84. nbRun = 0;
  85. firstAc = lastAc = -1;
  86. for (int i = 0; i < nbBord; i++) {
  87. bords[i].prev = i;
  88. }
  89. qsort(bords, nbBord, sizeof(int_ligne_bord), IntLigne::CmpBord);
  90. for (int i = 0; i < nbBord; i++) {
  91. bords[bords[i].prev].next = i;
  92. }
  93. for (int i = 0; i < nbBord; i++) {
  94. bords[i].other = bords[bords[i].other].next;
  95. }
  96. int lastStart = 0;
  97. float lastVal = 0;
  98. bool startExists = false;
  99. for (int i = 0; i < nbBord; ) {
  100. int cur = bords[i].pos;
  101. float leftV = 0;
  102. float rightV = 0;
  103. float midV = 0;
  104. while ( i < nbBord && bords[i].pos == cur && bords[i].start == false ) {
  105. Dequeue(i);
  106. leftV += bords[i].val;
  107. i++;
  108. }
  109. midV = RemainingValAt(cur);
  110. while ( i < nbBord && bords[i].pos == cur && bords[i].start == true ) {
  111. rightV += bords[i].val;
  112. Enqueue(bords[i].other);
  113. i++;
  114. }
  115. if ( startExists ) {
  116. AddRun(lastStart, cur, lastVal, leftV + midV);
  117. }
  118. if ( firstAc >= 0 ) {
  119. startExists = true;
  120. lastVal = midV + rightV;
  121. lastStart = cur;
  122. } else {
  123. startExists = false;
  124. }
  125. }
  126. }
  127. void IntLigne::Affiche()
  128. {
  129. printf("%i : \n", nbRun);
  130. for (int i = 0; i < nbRun;i++) {
  131. printf("(%i %f -> %i %f) ", runs[i].st, runs[i].vst, runs[i].en, runs[i].ven); // localization ok
  132. }
  133. printf("\n");
  134. }
  135. int IntLigne::AddRun(int st, int en, float vst, float ven)
  136. {
  137. if ( st >= en ) {
  138. return -1;
  139. }
  140. if ( nbRun >= maxRun ) {
  141. maxRun = 2 * nbRun + 1;
  142. runs = (int_ligne_run *) g_realloc(runs, maxRun * sizeof(int_ligne_run));
  143. }
  144. int n = nbRun++;
  145. runs[n].st = st;
  146. runs[n].en = en;
  147. runs[n].vst = vst;
  148. runs[n].ven = ven;
  149. return n;
  150. }
  151. void IntLigne::Booleen(IntLigne *a, IntLigne *b, BooleanOp mod)
  152. {
  153. Reset();
  154. if ( a->nbRun <= 0 && b->nbRun <= 0 ) {
  155. return;
  156. }
  157. if ( a->nbRun <= 0 ) {
  158. if ( mod == bool_op_union || mod == bool_op_symdiff ) {
  159. Copy(b);
  160. }
  161. return;
  162. }
  163. if ( b->nbRun <= 0 ) {
  164. if ( mod == bool_op_union || mod == bool_op_diff || mod == bool_op_symdiff ) {
  165. Copy(a);
  166. }
  167. return;
  168. }
  169. int curA = 0;
  170. int curB = 0;
  171. int curPos = (a->runs[0].st < b->runs[0].st) ? a->runs[0].st : b->runs[0].st;
  172. int nextPos = curPos;
  173. float valA = 0;
  174. float valB = 0;
  175. if ( curPos == a->runs[0].st ) {
  176. valA = a->runs[0].vst;
  177. }
  178. if ( curPos == b->runs[0].st ) {
  179. valB = b->runs[0].vst;
  180. }
  181. while ( curA < a->nbRun && curB < b->nbRun ) {
  182. int_ligne_run runA = a->runs[curA];
  183. int_ligne_run runB = b->runs[curB];
  184. const bool inA = ( curPos >= runA.st && curPos < runA.en );
  185. const bool inB = ( curPos >= runB.st && curPos < runB.en );
  186. bool startA = false;
  187. bool startB = false;
  188. bool endA = false;
  189. bool endB = false;
  190. if ( curPos < runA.st ) {
  191. if ( curPos < runB.st ) {
  192. startA = runA.st <= runB.st;
  193. startB = runA.st >= runB.st;
  194. nextPos = startA ? runA.st : runB.st;
  195. } else if ( curPos >= runB.st ) {
  196. startA = runA.st <= runB.en;
  197. endB = runA.st >= runB.en;
  198. nextPos = startA ? runA.st : runB.en;
  199. }
  200. } else if ( curPos == runA.st ) {
  201. if ( curPos < runB.st ) {
  202. endA = runA.en <= runB.st;
  203. startB = runA.en >= runB.st;
  204. nextPos = startB ? runB.en : runA.st;
  205. } else if ( curPos == runB.st ) {
  206. endA = runA.en <= runB.en;
  207. endB = runA.en >= runB.en;
  208. nextPos = endA? runA.en : runB.en;
  209. } else {
  210. endA = runA.en <= runB.en;
  211. endB = runA.en >= runB.en;
  212. nextPos = endA ? runA.en : runB.en;
  213. }
  214. } else {
  215. if ( curPos < runB.st ) {
  216. endA = runA.en <= runB.st;
  217. startB = runA.en >= runB.st;
  218. nextPos = startB ? runB.st : runA.en;
  219. } else if ( curPos == runB.st ) {
  220. endA = runA.en <= runB.en;
  221. endB = runA.en >= runB.en;
  222. nextPos = endA ? runA.en : runB.en;
  223. } else {
  224. endA = runA.en <= runB.en;
  225. endB = runA.en >= runB.en;
  226. nextPos = endA ? runA.en : runB.en;
  227. }
  228. }
  229. float oValA = valA;
  230. float oValB = valB;
  231. valA = inA ? ValAt(nextPos, runA.st, runA.en, runA.vst, runA.ven) : 0;
  232. valB = inB ? ValAt(nextPos, runB.st, runB.en, runB.vst, runB.ven) : 0;
  233. if ( mod == bool_op_union ) {
  234. if ( inA || inB ) {
  235. AddRun(curPos, nextPos, oValA + oValB, valA + valB);
  236. }
  237. } else if ( mod == bool_op_inters ) {
  238. if ( inA && inB ) {
  239. AddRun(curPos, nextPos, oValA * oValB, valA * valB);
  240. }
  241. } else if ( mod == bool_op_diff ) {
  242. if ( inA ) {
  243. AddRun(curPos, nextPos, oValA - oValB, valA - valB);
  244. }
  245. } else if ( mod == bool_op_symdiff ) {
  246. if ( inA && !(inB) ) {
  247. AddRun(curPos, nextPos, oValA - oValB, valA - valB);
  248. }
  249. if ( !(inA) && inB ) {
  250. AddRun(curPos, nextPos, oValB - oValA, valB - valA);
  251. }
  252. }
  253. curPos = nextPos;
  254. if ( startA ) {
  255. // inA=true; these are never used
  256. valA = runA.vst;
  257. }
  258. if ( startB ) {
  259. //inB=true;
  260. valB = runB.vst;
  261. }
  262. if ( endA ) {
  263. //inA=false;
  264. valA = 0;
  265. curA++;
  266. if ( curA < a->nbRun && a->runs[curA].st == curPos ) {
  267. valA = a->runs[curA].vst;
  268. }
  269. }
  270. if ( endB ) {
  271. //inB=false;
  272. valB = 0;
  273. curB++;
  274. if ( curB < b->nbRun && b->runs[curB].st == curPos ) {
  275. valB = b->runs[curB].vst;
  276. }
  277. }
  278. }
  279. while ( curA < a->nbRun ) {
  280. int_ligne_run runA = a->runs[curA];
  281. const bool inA = ( curPos >= runA.st && curPos < runA.en );
  282. const bool inB = false;
  283. bool startA = false;
  284. bool endA = false;
  285. if ( curPos < runA.st ) {
  286. nextPos = runA.st;
  287. startA = true;
  288. } else if ( curPos >= runA.st ) {
  289. nextPos = runA.en;
  290. endA = true;
  291. }
  292. float oValA = valA;
  293. float oValB = valB;
  294. valA = inA ? ValAt(nextPos,runA.st, runA.en, runA.vst, runA.ven) : 0;
  295. valB = 0;
  296. if ( mod == bool_op_union ) {
  297. if ( inA || inB ) {
  298. AddRun(curPos, nextPos, oValA + oValB, valA + valB);
  299. }
  300. } else if ( mod == bool_op_inters ) {
  301. if ( inA && inB ) {
  302. AddRun(curPos, nextPos, oValA * oValB, valA * valB);
  303. }
  304. } else if ( mod == bool_op_diff ) {
  305. if ( inA ) {
  306. AddRun(curPos, nextPos, oValA - oValB, valA - valB);
  307. }
  308. } else if ( mod == bool_op_symdiff ) {
  309. if ( inA && !(inB) ) {
  310. AddRun(curPos, nextPos, oValA - oValB, valA - valB);
  311. }
  312. if ( !(inA) && inB ) {
  313. AddRun(curPos,nextPos,oValB-oValA,valB-valA);
  314. }
  315. }
  316. curPos = nextPos;
  317. if ( startA ) {
  318. //inA=true;
  319. valA = runA.vst;
  320. }
  321. if ( endA ) {
  322. //inA=false;
  323. valA = 0;
  324. curA++;
  325. if ( curA < a->nbRun && a->runs[curA].st == curPos ) {
  326. valA = a->runs[curA].vst;
  327. }
  328. }
  329. }
  330. while ( curB < b->nbRun ) {
  331. int_ligne_run runB = b->runs[curB];
  332. const bool inB = ( curPos >= runB.st && curPos < runB.en );
  333. const bool inA = false;
  334. bool startB = false;
  335. bool endB = false;
  336. if ( curPos < runB.st ) {
  337. nextPos = runB.st;
  338. startB = true;
  339. } else if ( curPos >= runB.st ) {
  340. nextPos = runB.en;
  341. endB = true;
  342. }
  343. float oValA = valA;
  344. float oValB = valB;
  345. valB = inB ? ValAt(nextPos, runB.st, runB.en, runB.vst, runB.ven) : 0;
  346. valA = 0;
  347. if ( mod == bool_op_union ) {
  348. if ( inA || inB ) {
  349. AddRun(curPos, nextPos, oValA + oValB,valA + valB);
  350. }
  351. } else if ( mod == bool_op_inters ) {
  352. if ( inA && inB ) {
  353. AddRun(curPos, nextPos, oValA * oValB, valA * valB);
  354. }
  355. } else if ( mod == bool_op_diff ) {
  356. if ( inA ) {
  357. AddRun(curPos, nextPos, oValA - oValB, valA - valB);
  358. }
  359. } else if ( mod == bool_op_symdiff ) {
  360. if ( inA && !(inB) ) {
  361. AddRun(curPos, nextPos, oValA - oValB,valA - valB);
  362. }
  363. if ( !(inA) && inB ) {
  364. AddRun(curPos, nextPos, oValB - oValA, valB - valA);
  365. }
  366. }
  367. curPos = nextPos;
  368. if ( startB ) {
  369. //inB=true;
  370. valB = runB.vst;
  371. }
  372. if ( endB ) {
  373. //inB=false;
  374. valB = 0;
  375. curB++;
  376. if ( curB < b->nbRun && b->runs[curB].st == curPos ) {
  377. valB = b->runs[curB].vst;
  378. }
  379. }
  380. }
  381. }
  382. /**
  383. * Transform a line of bits into pixel coverage values.
  384. *
  385. * This is where you go from supersampled data to alpha values.
  386. * \see IntLigne::Copy(int nbSub,BitLigne* *a).
  387. */
  388. void IntLigne::Copy(BitLigne* a)
  389. {
  390. if ( a->curMax <= a->curMin ) {
  391. Reset();
  392. return;
  393. }
  394. if ( a->curMin < a->st ) {
  395. a->curMin = a->st;
  396. }
  397. if ( a->curMax < a->st ) {
  398. Reset();
  399. return;
  400. }
  401. if ( a->curMin > a->en ) {
  402. Reset();
  403. return;
  404. }
  405. if ( a->curMax > a->en ) {
  406. a->curMax=a->en;
  407. }
  408. nbBord = 0;
  409. nbRun = 0;
  410. int lastVal = 0;
  411. int lastStart = 0;
  412. bool startExists = false;
  413. int masks[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
  414. uint32_t c_full = a->fullB[(a->curMin-a->st) >> 3];
  415. uint32_t c_part = a->partB[(a->curMin-a->st) >> 3];
  416. c_full <<= 4 * ((a->curMin - a->st) & 0x00000007);
  417. c_part <<= 4 * ((a->curMin - a->st) & 0x00000007);
  418. for (int i = a->curMin; i <= a->curMax; i++) {
  419. int nbBit = masks[c_full >> 28] + masks[c_part >> 28];
  420. if ( nbBit > 0 ) {
  421. if ( startExists ) {
  422. if ( lastVal == nbBit ) {
  423. // on continue le run
  424. } else {
  425. AddRun(lastStart, i, ((float) lastVal) / 4, ((float) lastVal) / 4);
  426. lastStart = i;
  427. lastVal = nbBit;
  428. }
  429. } else {
  430. lastStart = i;
  431. lastVal = nbBit;
  432. startExists = true;
  433. }
  434. } else {
  435. if ( startExists ) {
  436. AddRun(lastStart, i, ((float) lastVal) / 4, ((float) lastVal) / 4);
  437. }
  438. startExists = false;
  439. }
  440. int chg = (i + 1 - a->st) & 0x00000007;
  441. if ( chg == 0 ) {
  442. c_full = a->fullB[(i + 1 - a->st) >> 3];
  443. c_part = a->partB[(i + 1 - a->st) >> 3];
  444. } else {
  445. c_full <<= 4;
  446. c_part <<= 4;
  447. }
  448. }
  449. if ( startExists ) {
  450. AddRun(lastStart, a->curMax + 1, ((float) lastVal) / 4, ((float) lastVal) / 4);
  451. }
  452. }
  453. /**
  454. * Transform a line of bits into pixel coverage values.
  455. *
  456. * Alpha values are computed from supersampled data, so we have to scan the
  457. * BitLigne left to right, summing the bits in each pixel. The alpha value
  458. * is then "number of bits"/(nbSub*nbSub)". Full bits and partial bits are
  459. * treated as equals because the method produces ugly results otherwise.
  460. *
  461. * \param nbSub Number of BitLigne in the array "a".
  462. */
  463. void IntLigne::Copy(int nbSub, BitLigne **as)
  464. {
  465. if ( nbSub <= 0 ) {
  466. Reset();
  467. return;
  468. }
  469. if ( nbSub == 1 ) {
  470. Copy(as[0]);
  471. return;
  472. }
  473. // compute the min-max of the pixels to be rasterized from the min-max of the inpur bitlignes
  474. int curMin = as[0]->curMin;
  475. int curMax = as[0]->curMax;
  476. for (int i = 1; i < nbSub; i++) {
  477. if ( as[i]->curMin < curMin ) {
  478. curMin = as[i]->curMin;
  479. }
  480. if ( as[i]->curMax > curMax ) {
  481. curMax = as[i]->curMax;
  482. }
  483. }
  484. if ( curMin < as[0]->st ) {
  485. curMin = as[0]->st;
  486. }
  487. if ( curMax > as[0]->en ) {
  488. curMax = as[0]->en;
  489. }
  490. if ( curMax <= curMin ) {
  491. Reset();
  492. return;
  493. }
  494. nbBord = 0;
  495. nbRun = 0;
  496. int lastVal = 0;
  497. int lastStart = 0;
  498. bool startExists = false;
  499. float spA;
  500. int masks[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
  501. int theSt = as[0]->st;
  502. if ( nbSub == 4 ) {
  503. // special case for 4*4 supersampling, to avoid a few loops
  504. uint32_t c_full[4];
  505. c_full[0] = as[0]->fullB[(curMin - theSt) >> 3] | as[0]->partB[(curMin - theSt) >> 3];
  506. c_full[0] <<= 4 * ((curMin - theSt) & 7);
  507. c_full[1] = as[1]->fullB[(curMin - theSt) >> 3] | as[1]->partB[(curMin - theSt) >> 3];
  508. c_full[1] <<= 4 * ((curMin - theSt) & 7);
  509. c_full[2] = as[2]->fullB[(curMin - theSt) >> 3] | as[2]->partB[(curMin - theSt) >> 3];
  510. c_full[2] <<= 4* ((curMin - theSt) & 7);
  511. c_full[3] = as[3]->fullB[(curMin - theSt) >> 3] | as[3]->partB[(curMin - theSt) >> 3];
  512. c_full[3] <<= 4* ((curMin - theSt) & 7);
  513. spA = 1.0 / (4 * 4);
  514. for (int i = curMin; i <= curMax; i++) {
  515. int nbBit = 0;
  516. if ( c_full[0] == 0 && c_full[1] == 0 && c_full[2] == 0 && c_full[3] == 0 ) {
  517. if ( startExists ) {
  518. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  519. }
  520. startExists = false;
  521. i = theSt + (((i - theSt) & (~7) ) + 7);
  522. } else if ( c_full[0] == 0xFFFFFFFF && c_full[1] == 0xFFFFFFFF &&
  523. c_full[2] == 0xFFFFFFFF && c_full[3] == 0xFFFFFFFF ) {
  524. if ( startExists ) {
  525. if ( lastVal == 4*4) {
  526. } else {
  527. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  528. lastStart = i;
  529. }
  530. } else {
  531. lastStart = i;
  532. }
  533. lastVal = 4*4;
  534. startExists = true;
  535. i = theSt + (((i - theSt) & (~7) ) + 7);
  536. } else {
  537. nbBit += masks[c_full[0] >> 28];
  538. nbBit += masks[c_full[1] >> 28];
  539. nbBit += masks[c_full[2] >> 28];
  540. nbBit += masks[c_full[3] >> 28];
  541. if ( nbBit > 0 ) {
  542. if ( startExists ) {
  543. if ( lastVal == nbBit ) {
  544. // on continue le run
  545. } else {
  546. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  547. lastStart = i;
  548. lastVal = nbBit;
  549. }
  550. } else {
  551. lastStart = i;
  552. lastVal = nbBit;
  553. startExists = true;
  554. }
  555. } else {
  556. if ( startExists ) {
  557. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  558. }
  559. startExists = false;
  560. }
  561. }
  562. int chg = (i + 1 - theSt) & 7;
  563. if ( chg == 0 ) {
  564. if ( i < curMax ) {
  565. c_full[0] = as[0]->fullB[(i + 1 - theSt) >> 3] | as[0]->partB[(i + 1 - theSt) >> 3];
  566. c_full[1] = as[1]->fullB[(i + 1 - theSt) >> 3] | as[1]->partB[(i + 1 - theSt) >> 3];
  567. c_full[2] = as[2]->fullB[(i + 1 - theSt) >> 3] | as[2]->partB[(i + 1 - theSt) >> 3];
  568. c_full[3] = as[3]->fullB[(i + 1 - theSt) >> 3] | as[3]->partB[(i + 1 - theSt) >> 3];
  569. } else {
  570. // end of line. byebye
  571. }
  572. } else {
  573. c_full[0] <<= 4;
  574. c_full[1] <<= 4;
  575. c_full[2] <<= 4;
  576. c_full[3] <<= 4;
  577. }
  578. }
  579. } else {
  580. uint32_t c_full[16]; // we take nbSub < 16, since 16*16 supersampling makes a 1/256 precision in alpha values
  581. // and that's the max of what 32bit argb can represent
  582. // in fact, we'll treat it as 4*nbSub supersampling, so that's a half truth and a full lazyness from me
  583. // uint32_t c_part[16];
  584. // start by putting the bits of the nbSub BitLignes in as[] in their respective c_full
  585. for (int i = 0; i < nbSub; i++) {
  586. // fullB and partB treated equally
  587. c_full[i] = as[i]->fullB[(curMin - theSt) >> 3] | as[i]->partB[(curMin - theSt) >> 3];
  588. c_full[i] <<= 4 * ((curMin - theSt) & 7);
  589. /* c_part[i]=as[i]->partB[(curMin-theSt)>>3];
  590. c_part[i]<<=4*((curMin-theSt)&7);*/
  591. }
  592. spA = 1.0 / (4 * nbSub); // contribution to the alpha value of a single bit of the supersampled data
  593. for (int i = curMin; i <= curMax;i++) {
  594. int nbBit = 0;
  595. // int nbPartBit=0;
  596. // a little acceleration: if the lines only contain full or empty bits, we can flush
  597. // what's remaining in the c_full at best we flush an entire c_full, ie 32 bits, or 32/4=8 pixels
  598. bool allEmpty = true;
  599. bool allFull = true;
  600. for (int j = 0; j < nbSub; j++) {
  601. if ( c_full[j] != 0 /*|| c_part[j] != 0*/ ) {
  602. allEmpty=false;
  603. break;
  604. }
  605. }
  606. if ( allEmpty ) {
  607. // the remaining bits in c_full[] are empty: flush
  608. if ( startExists ) {
  609. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  610. }
  611. startExists = false;
  612. i = theSt + (((i - theSt) & (~7) ) + 7);
  613. } else {
  614. for (int j = 0; j < nbSub; j++) {
  615. if ( c_full[j] != 0xFFFFFFFF ) {
  616. allFull=false;
  617. break;
  618. }
  619. }
  620. if ( allFull ) {
  621. // the remaining bits in c_full[] are empty: flush
  622. if ( startExists ) {
  623. if ( lastVal == 4 * nbSub) {
  624. } else {
  625. AddRun(lastStart, i, ((float) lastVal) * spA,((float) lastVal) * spA);
  626. lastStart = i;
  627. }
  628. } else {
  629. lastStart = i;
  630. }
  631. lastVal = 4 * nbSub;
  632. startExists = true;
  633. i = theSt + (((i - theSt) & (~7) ) + 7);
  634. } else {
  635. // alpha values will be between 0 and 1, so we have more work to do
  636. // compute how many bit this pixel holds
  637. for (int j = 0; j < nbSub; j++) {
  638. nbBit += masks[c_full[j] >> 28];
  639. // nbPartBit+=masks[c_part[j]>>28];
  640. }
  641. // and add a single-pixel run if needed, or extend the current run if the alpha value hasn't changed
  642. if ( nbBit > 0 ) {
  643. if ( startExists ) {
  644. if ( lastVal == nbBit ) {
  645. // alpha value hasn't changed: we continue
  646. } else {
  647. // alpha value did change: put the run that was being done,...
  648. AddRun(lastStart, i, ((float) lastVal) * spA, ((float) lastVal) * spA);
  649. // ... and start a new one
  650. lastStart = i;
  651. lastVal = nbBit;
  652. }
  653. } else {
  654. // alpha value was 0, so we "create" a new run with alpha nbBit
  655. lastStart = i;
  656. lastVal = nbBit;
  657. startExists = true;
  658. }
  659. } else {
  660. if ( startExists ) {
  661. AddRun(lastStart, i, ((float) lastVal) * spA,((float) lastVal) * spA);
  662. }
  663. startExists = false;
  664. }
  665. }
  666. }
  667. // move to the right: shift bits in the c_full[], and if we shifted everything, load the next c_full[]
  668. int chg = (i + 1 - theSt) & 7;
  669. if ( chg == 0 ) {
  670. if ( i < curMax ) {
  671. for (int j = 0; j < nbSub; j++) {
  672. c_full[j] = as[j]->fullB[(i + 1 - theSt) >> 3] | as[j]->partB[(i + 1 - theSt) >> 3];
  673. // c_part[j]=as[j]->partB[(i+1-theSt)>>3];
  674. }
  675. } else {
  676. // end of line. byebye
  677. }
  678. } else {
  679. for (int j = 0; j < nbSub; j++) {
  680. c_full[j]<<=4;
  681. // c_part[j]<<=4;
  682. }
  683. }
  684. }
  685. }
  686. if ( startExists ) {
  687. AddRun(lastStart, curMax + 1, ((float) lastVal) * spA,((float) lastVal) * spA);
  688. }
  689. }
  690. /// Copy another IntLigne
  691. void IntLigne::Copy(IntLigne *a)
  692. {
  693. if ( a->nbRun <= 0 ) {
  694. Reset();
  695. return;
  696. }
  697. nbBord = 0;
  698. nbRun = a->nbRun;
  699. if ( nbRun > maxRun ) {
  700. maxRun = nbRun;
  701. runs = (int_ligne_run*) g_realloc(runs, maxRun * sizeof(int_ligne_run));
  702. }
  703. memcpy(runs, a->runs, nbRun * sizeof(int_ligne_run));
  704. }
  705. /**
  706. * Copy a FloatLigne's runs.
  707. *
  708. * Compute non-overlapping runs with integer boundaries from a set of runs
  709. * with floating-point boundaries. This involves replacing floating-point
  710. * boundaries that are not integer by single-pixel runs, so this function
  711. * contains plenty of rounding and float->integer conversion (read:
  712. * time-consuming).
  713. *
  714. * \todo
  715. * Optimization Questions: Why is this called so often compared with the
  716. * other Copy() routines? How does AddRun() look for optimization potential?
  717. */
  718. void IntLigne::Copy(FloatLigne* a)
  719. {
  720. if ( a->runs.empty() ) {
  721. Reset();
  722. return;
  723. }
  724. /* if ( showCopy ) {
  725. printf("\nfloatligne:\n");
  726. a->Affiche();
  727. }*/
  728. nbBord = 0;
  729. nbRun = 0;
  730. firstAc = lastAc = -1;
  731. bool pixExists = false;
  732. int curPos = (int) floor(a->runs[0].st) - 1;
  733. float lastSurf = 0;
  734. float tolerance = 0.00001;
  735. // we take each run of the FloatLigne in sequence and make single-pixel runs of its boundaries as needed
  736. // since the float_ligne_runs are non-overlapping, when a single-pixel run intersects with another runs,
  737. // it must intersect with the single-pixel run created for the end of that run. so instead of creating a new
  738. // int_ligne_run, we just add the coverage to that run.
  739. for (int i = 0; i < int(a->runs.size()); i++) {
  740. float_ligne_run runA = a->runs[i];
  741. float curStF = floor(runA.st);
  742. float curEnF = floor(runA.en);
  743. int curSt = (int) curStF;
  744. int curEn = (int) curEnF;
  745. // stEx: start boundary is not integer -> create single-pixel run for it
  746. // enEx: end boundary is not integer -> create single-pixel run for it
  747. // miEx: the runs minus the eventual single-pixel runs is not empty
  748. bool stEx = true;
  749. bool miEx = true;
  750. bool enEx = true;
  751. int miSt = curSt;
  752. float miStF = curStF;
  753. float msv;
  754. float mev;
  755. if ( runA.en - curEnF < tolerance ) {
  756. enEx = false;
  757. }
  758. // msv and mev are the start and end value of the middle section of the run, that is the run minus the
  759. // single-pixel runs creaed for its boundaries
  760. if ( runA.st-curStF < tolerance /*miSt == runA.st*/ ) {
  761. stEx = false;
  762. msv = runA.vst;
  763. } else {
  764. miSt += 1;
  765. miStF += 1.0;
  766. if ( enEx == false && miSt == curEn ) {
  767. msv = runA.ven;
  768. } else {
  769. // msv=a->ValAt(miSt,runA.st,runA.en,runA.vst,runA.ven);
  770. msv = runA.vst + (miStF-runA.st) * runA.pente;
  771. }
  772. }
  773. if ( miSt >= curEn ) {
  774. miEx = false;
  775. }
  776. if ( stEx == false && miEx == false /*curEn == runA.st*/ ) {
  777. mev = runA.vst;
  778. } else if ( enEx == false /*curEn == runA.en*/ ) {
  779. mev = runA.ven;
  780. } else {
  781. // mev=a->ValAt(curEn,runA.st,runA.en,runA.vst,runA.ven);
  782. mev = runA.vst + (curEnF-runA.st) * runA.pente;
  783. }
  784. // check the different cases
  785. if ( stEx && enEx ) {
  786. // stEx && enEx
  787. if ( curEn > curSt ) {
  788. if ( pixExists ) {
  789. if ( curPos < curSt ) {
  790. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  791. lastSurf=0.5*(msv+a->runs[i].vst)*(miStF-a->runs[i].st);
  792. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  793. } else {
  794. lastSurf+=0.5*(msv+a->runs[i].vst)*(miStF-a->runs[i].st);
  795. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  796. }
  797. pixExists=false;
  798. } else {
  799. lastSurf=0.5*(msv+a->runs[i].vst)*(miStF-a->runs[i].st);
  800. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  801. }
  802. } else if ( pixExists ) {
  803. if ( curPos < curSt ) {
  804. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  805. lastSurf=0.5*(a->runs[i].ven+a->runs[i].vst)*(a->runs[i].en-a->runs[i].st);
  806. curPos=curSt;
  807. } else {
  808. lastSurf += 0.5 * (a->runs[i].ven+a->runs[i].vst)*(a->runs[i].en-a->runs[i].st);
  809. }
  810. } else {
  811. lastSurf=0.5*(a->runs[i].ven+a->runs[i].vst)*(a->runs[i].en-a->runs[i].st);
  812. curPos=curSt;
  813. pixExists=true;
  814. }
  815. } else if ( pixExists ) {
  816. if ( curPos < curSt ) {
  817. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  818. lastSurf = 0.5 * (msv+a->runs[i].vst) * (miStF-a->runs[i].st);
  819. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  820. } else {
  821. lastSurf += 0.5 * (msv+a->runs[i].vst) * (miStF-a->runs[i].st);
  822. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  823. }
  824. pixExists=false;
  825. } else {
  826. lastSurf = 0.5 * (msv+a->runs[i].vst) * (miStF-a->runs[i].st);
  827. AddRun(curSt,curSt+1,lastSurf,lastSurf);
  828. }
  829. if ( miEx ) {
  830. if ( pixExists && curPos < miSt ) {
  831. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  832. }
  833. pixExists=false;
  834. AddRun(miSt,curEn,msv,mev);
  835. }
  836. if ( enEx ) {
  837. if ( curEn > curSt ) {
  838. lastSurf=0.5*(mev+a->runs[i].ven)*(a->runs[i].en-curEnF);
  839. pixExists=true;
  840. curPos=curEn;
  841. } else if ( ! stEx ) {
  842. if ( pixExists ) {
  843. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  844. }
  845. lastSurf=0.5*(mev+a->runs[i].ven)*(a->runs[i].en-curEnF);
  846. pixExists=true;
  847. curPos=curEn;
  848. }
  849. }
  850. }
  851. if ( pixExists ) {
  852. AddRun(curPos,curPos+1,lastSurf,lastSurf);
  853. }
  854. /* if ( showCopy ) {
  855. printf("-> intligne:\n");
  856. Affiche();
  857. }*/
  858. }
  859. void IntLigne::Enqueue(int no)
  860. {
  861. if ( firstAc < 0 ) {
  862. firstAc = lastAc = no;
  863. bords[no].prev = bords[no].next = -1;
  864. } else {
  865. bords[no].next = -1;
  866. bords[no].prev = lastAc;
  867. bords[lastAc].next = no;
  868. lastAc = no;
  869. }
  870. }
  871. void IntLigne::Dequeue(int no)
  872. {
  873. if ( no == firstAc ) {
  874. if ( no == lastAc ) {
  875. firstAc = lastAc = -1;
  876. } else {
  877. firstAc = bords[no].next;
  878. }
  879. } else if ( no == lastAc ) {
  880. lastAc = bords[no].prev;
  881. } else {
  882. }
  883. if ( bords[no].prev >= 0 ) {
  884. bords[bords[no].prev].next = bords[no].next;
  885. }
  886. if ( bords[no].next >= 0 ) {
  887. bords[bords[no].next].prev = bords[no].prev;
  888. }
  889. bords[no].prev = bords[no].next = -1;
  890. }
  891. /**
  892. * Rasterization.
  893. *
  894. * The parameters have the same meaning as in the AlphaLigne class.
  895. */
  896. void IntLigne::Raster(raster_info &dest, void *color, RasterInRunFunc worker)
  897. {
  898. if ( nbRun <= 0 ) {
  899. return;
  900. }
  901. int min = runs[0].st;
  902. int max = runs[nbRun-1].en;
  903. if ( dest.endPix <= min || dest.startPix >= max ) {
  904. return;
  905. }
  906. int curRun = -1;
  907. for (curRun = 0; curRun < nbRun; curRun++) {
  908. if ( runs[curRun].en > dest.startPix ) {
  909. break;
  910. }
  911. }
  912. if ( curRun >= nbRun ) {
  913. return;
  914. }
  915. if ( runs[curRun].st < dest.startPix ) {
  916. int nst = runs[curRun].st;
  917. int nen = runs[curRun].en;
  918. float vst = runs[curRun].vst;
  919. float ven = runs[curRun].ven;
  920. float nvst = (vst * (nen - dest.startPix) + ven * (dest.startPix - nst)) / ((float) (nen - nst));
  921. if ( runs[curRun].en <= dest.endPix ) {
  922. (worker)(dest, color, dest.startPix, nvst, runs[curRun].en, runs[curRun].ven);
  923. } else {
  924. float nven = (vst * (nen - dest.endPix) + ven * (dest.endPix - nst)) / ((float)(nen - nst));
  925. (worker)(dest, color, dest.startPix, nvst, dest.endPix, nven);
  926. return;
  927. }
  928. curRun++;
  929. }
  930. for (; (curRun < nbRun && runs[curRun].en <= dest.endPix); curRun++) {
  931. (worker)(dest, color, runs[curRun].st, runs[curRun].vst, runs[curRun].en, runs[curRun].ven);
  932. //Buffer::RasterRun(*dest,color,runs[curRun].st,runs[curRun].vst,runs[curRun].en,runs[curRun].ven);
  933. }
  934. if ( curRun >= nbRun ) {
  935. return;
  936. }
  937. if ( runs[curRun].st < dest.endPix && runs[curRun].en > dest.endPix ) {
  938. int const nst = runs[curRun].st;
  939. int const nen = runs[curRun].en;
  940. float const vst = runs[curRun].vst;
  941. float const ven = runs[curRun].ven;
  942. float const nven = (vst * (nen - dest.endPix) + ven * (dest.endPix - nst)) / ((float)(nen - nst));
  943. (worker)(dest,color,runs[curRun].st,runs[curRun].vst,dest.endPix,nven);
  944. curRun++;
  945. }
  946. }
  947. /*
  948. Local Variables:
  949. mode:c++
  950. c-file-style:"stroustrup"
  951. c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  952. indent-tabs-mode:nil
  953. fill-column:99
  954. End:
  955. */
  956. // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :