agg_scanline_u.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. //----------------------------------------------------------------------------
  2. // Anti-Grain Geometry - Version 2.4
  3. // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
  4. //
  5. // Permission to copy, use, modify, sell and distribute this software
  6. // is granted provided this copyright notice appears in all copies.
  7. // This software is provided "as is" without express or implied
  8. // warranty, and with no claim as to its suitability for any purpose.
  9. //
  10. //----------------------------------------------------------------------------
  11. // Contact: mcseem@antigrain.com
  12. // mcseemagg@yahoo.com
  13. // http://www.antigrain.com
  14. //----------------------------------------------------------------------------
  15. //
  16. // Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
  17. // Liberty Technology Systems, Inc., visit http://lib-sys.com
  18. //
  19. // Liberty Technology Systems, Inc. is the provider of
  20. // PostScript and PDF technology for software developers.
  21. //
  22. //----------------------------------------------------------------------------
  23. #ifndef AGG_SCANLINE_U_INCLUDED
  24. #define AGG_SCANLINE_U_INCLUDED
  25. #include "agg_array.h"
  26. namespace agg
  27. {
  28. //=============================================================scanline_u8
  29. //
  30. // Unpacked scanline container class
  31. //
  32. // This class is used to transfer data from a scanline rasterizer
  33. // to the rendering buffer. It's organized very simple. The class stores
  34. // information of horizontal spans to render it into a pixel-map buffer.
  35. // Each span has staring X, length, and an array of bytes that determine the
  36. // cover-values for each pixel.
  37. // Before using this class you should know the minimal and maximal pixel
  38. // coordinates of your scanline. The protocol of using is:
  39. // 1. reset(min_x, max_x)
  40. // 2. add_cell() / add_span() - accumulate scanline.
  41. // When forming one scanline the next X coordinate must be always greater
  42. // than the last stored one, i.e. it works only with ordered coordinates.
  43. // 3. Call finalize(y) and render the scanline.
  44. // 3. Call reset_spans() to prepare for the new scanline.
  45. //
  46. // 4. Rendering:
  47. //
  48. // Scanline provides an iterator class that allows you to extract
  49. // the spans and the cover values for each pixel. Be aware that clipping
  50. // has not been done yet, so you should perform it yourself.
  51. // Use scanline_u8::iterator to render spans:
  52. //-------------------------------------------------------------------------
  53. //
  54. // int y = sl.y(); // Y-coordinate of the scanline
  55. //
  56. // ************************************
  57. // ...Perform vertical clipping here...
  58. // ************************************
  59. //
  60. // scanline_u8::const_iterator span = sl.begin();
  61. //
  62. // unsigned char* row = m_rbuf->row(y); // The address of the beginning
  63. // // of the current row
  64. //
  65. // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
  66. // // num_spans is always greater than 0.
  67. //
  68. // do
  69. // {
  70. // const scanline_u8::cover_type* covers =
  71. // span->covers; // The array of the cover values
  72. //
  73. // int num_pix = span->len; // Number of pixels of the span.
  74. // // Always greater than 0, still it's
  75. // // better to use "int" instead of
  76. // // "unsigned" because it's more
  77. // // convenient for clipping
  78. // int x = span->x;
  79. //
  80. // **************************************
  81. // ...Perform horizontal clipping here...
  82. // ...you have x, covers, and pix_count..
  83. // **************************************
  84. //
  85. // unsigned char* dst = row + x; // Calculate the start address of the row.
  86. // // In this case we assume a simple
  87. // // grayscale image 1-byte per pixel.
  88. // do
  89. // {
  90. // *dst++ = *covers++; // Hypotetical rendering.
  91. // }
  92. // while(--num_pix);
  93. //
  94. // ++span;
  95. // }
  96. // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
  97. //------------------------------------------------------------------------
  98. //
  99. // The question is: why should we accumulate the whole scanline when we
  100. // could render just separate spans when they're ready?
  101. // That's because using the scanline is generally faster. When is consists
  102. // of more than one span the conditions for the processor cash system
  103. // are better, because switching between two different areas of memory
  104. // (that can be very large) occurs less frequently.
  105. //------------------------------------------------------------------------
  106. class scanline_u8
  107. {
  108. public:
  109. typedef scanline_u8 self_type;
  110. typedef int8u cover_type;
  111. typedef int16 coord_type;
  112. //--------------------------------------------------------------------
  113. struct span
  114. {
  115. coord_type x;
  116. coord_type len;
  117. cover_type* covers;
  118. };
  119. typedef span* iterator;
  120. typedef const span* const_iterator;
  121. //--------------------------------------------------------------------
  122. scanline_u8() :
  123. m_min_x(0),
  124. m_last_x(0x7FFFFFF0),
  125. m_cur_span(0)
  126. {}
  127. //--------------------------------------------------------------------
  128. void reset(int min_x, int max_x)
  129. {
  130. unsigned max_len = max_x - min_x + 2;
  131. if(max_len > m_spans.size())
  132. {
  133. m_spans.resize(max_len);
  134. m_covers.resize(max_len);
  135. }
  136. m_last_x = 0x7FFFFFF0;
  137. m_min_x = min_x;
  138. m_cur_span = &m_spans[0];
  139. }
  140. //--------------------------------------------------------------------
  141. void add_cell(int x, unsigned cover)
  142. {
  143. x -= m_min_x;
  144. m_covers[x] = (cover_type)cover;
  145. if(x == m_last_x+1)
  146. {
  147. m_cur_span->len++;
  148. }
  149. else
  150. {
  151. m_cur_span++;
  152. m_cur_span->x = (coord_type)(x + m_min_x);
  153. m_cur_span->len = 1;
  154. m_cur_span->covers = &m_covers[x];
  155. }
  156. m_last_x = x;
  157. }
  158. //--------------------------------------------------------------------
  159. void add_cells(int x, unsigned len, const cover_type* covers)
  160. {
  161. x -= m_min_x;
  162. memcpy(&m_covers[x], covers, len * sizeof(cover_type));
  163. if(x == m_last_x+1)
  164. {
  165. m_cur_span->len += (coord_type)len;
  166. }
  167. else
  168. {
  169. m_cur_span++;
  170. m_cur_span->x = (coord_type)(x + m_min_x);
  171. m_cur_span->len = (coord_type)len;
  172. m_cur_span->covers = &m_covers[x];
  173. }
  174. m_last_x = x + len - 1;
  175. }
  176. //--------------------------------------------------------------------
  177. void add_span(int x, unsigned len, unsigned cover)
  178. {
  179. x -= m_min_x;
  180. memset(&m_covers[x], cover, len);
  181. if(x == m_last_x+1)
  182. {
  183. m_cur_span->len += (coord_type)len;
  184. }
  185. else
  186. {
  187. m_cur_span++;
  188. m_cur_span->x = (coord_type)(x + m_min_x);
  189. m_cur_span->len = (coord_type)len;
  190. m_cur_span->covers = &m_covers[x];
  191. }
  192. m_last_x = x + len - 1;
  193. }
  194. //--------------------------------------------------------------------
  195. void finalize(int y)
  196. {
  197. m_y = y;
  198. }
  199. //--------------------------------------------------------------------
  200. void reset_spans()
  201. {
  202. m_last_x = 0x7FFFFFF0;
  203. m_cur_span = &m_spans[0];
  204. }
  205. //--------------------------------------------------------------------
  206. int y() const { return m_y; }
  207. unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
  208. const_iterator begin() const { return &m_spans[1]; }
  209. iterator begin() { return &m_spans[1]; }
  210. private:
  211. scanline_u8(const self_type&);
  212. const self_type& operator = (const self_type&);
  213. private:
  214. int m_min_x;
  215. int m_last_x;
  216. int m_y;
  217. pod_array<cover_type> m_covers;
  218. pod_array<span> m_spans;
  219. span* m_cur_span;
  220. };
  221. //==========================================================scanline_u8_am
  222. //
  223. // The scanline container with alpha-masking
  224. //
  225. //------------------------------------------------------------------------
  226. template<class AlphaMask>
  227. class scanline_u8_am : public scanline_u8
  228. {
  229. public:
  230. typedef scanline_u8 base_type;
  231. typedef AlphaMask alpha_mask_type;
  232. typedef base_type::cover_type cover_type;
  233. typedef base_type::coord_type coord_type;
  234. scanline_u8_am() : base_type(), m_alpha_mask(0) {}
  235. scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
  236. //--------------------------------------------------------------------
  237. void finalize(int span_y)
  238. {
  239. base_type::finalize(span_y);
  240. if(m_alpha_mask)
  241. {
  242. typename base_type::iterator span = base_type::begin();
  243. unsigned count = base_type::num_spans();
  244. do
  245. {
  246. m_alpha_mask->combine_hspan(span->x,
  247. base_type::y(),
  248. span->covers,
  249. span->len);
  250. ++span;
  251. }
  252. while(--count);
  253. }
  254. }
  255. private:
  256. AlphaMask* m_alpha_mask;
  257. };
  258. //===========================================================scanline32_u8
  259. class scanline32_u8
  260. {
  261. public:
  262. typedef scanline32_u8 self_type;
  263. typedef int8u cover_type;
  264. typedef int32 coord_type;
  265. //--------------------------------------------------------------------
  266. struct span
  267. {
  268. span() {}
  269. span(coord_type x_, coord_type len_, cover_type* covers_) :
  270. x(x_), len(len_), covers(covers_) {}
  271. coord_type x;
  272. coord_type len;
  273. cover_type* covers;
  274. };
  275. typedef pod_bvector<span, 4> span_array_type;
  276. //--------------------------------------------------------------------
  277. class const_iterator
  278. {
  279. public:
  280. const_iterator(const span_array_type& spans) :
  281. m_spans(spans),
  282. m_span_idx(0)
  283. {}
  284. const span& operator*() const { return m_spans[m_span_idx]; }
  285. const span* operator->() const { return &m_spans[m_span_idx]; }
  286. void operator ++ () { ++m_span_idx; }
  287. private:
  288. const span_array_type& m_spans;
  289. unsigned m_span_idx;
  290. };
  291. //--------------------------------------------------------------------
  292. class iterator
  293. {
  294. public:
  295. iterator(span_array_type& spans) :
  296. m_spans(spans),
  297. m_span_idx(0)
  298. {}
  299. span& operator*() { return m_spans[m_span_idx]; }
  300. span* operator->() { return &m_spans[m_span_idx]; }
  301. void operator ++ () { ++m_span_idx; }
  302. private:
  303. span_array_type& m_spans;
  304. unsigned m_span_idx;
  305. };
  306. //--------------------------------------------------------------------
  307. scanline32_u8() :
  308. m_min_x(0),
  309. m_last_x(0x7FFFFFF0),
  310. m_covers()
  311. {}
  312. //--------------------------------------------------------------------
  313. void reset(int min_x, int max_x)
  314. {
  315. unsigned max_len = max_x - min_x + 2;
  316. if(max_len > m_covers.size())
  317. {
  318. m_covers.resize(max_len);
  319. }
  320. m_last_x = 0x7FFFFFF0;
  321. m_min_x = min_x;
  322. m_spans.remove_all();
  323. }
  324. //--------------------------------------------------------------------
  325. void add_cell(int x, unsigned cover)
  326. {
  327. x -= m_min_x;
  328. m_covers[x] = cover_type(cover);
  329. if(x == m_last_x+1)
  330. {
  331. m_spans.last().len++;
  332. }
  333. else
  334. {
  335. m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
  336. }
  337. m_last_x = x;
  338. }
  339. //--------------------------------------------------------------------
  340. void add_cells(int x, unsigned len, const cover_type* covers)
  341. {
  342. x -= m_min_x;
  343. memcpy(&m_covers[x], covers, len * sizeof(cover_type));
  344. if(x == m_last_x+1)
  345. {
  346. m_spans.last().len += coord_type(len);
  347. }
  348. else
  349. {
  350. m_spans.add(span(coord_type(x + m_min_x),
  351. coord_type(len),
  352. &m_covers[x]));
  353. }
  354. m_last_x = x + len - 1;
  355. }
  356. //--------------------------------------------------------------------
  357. void add_span(int x, unsigned len, unsigned cover)
  358. {
  359. x -= m_min_x;
  360. memset(&m_covers[x], cover, len);
  361. if(x == m_last_x+1)
  362. {
  363. m_spans.last().len += coord_type(len);
  364. }
  365. else
  366. {
  367. m_spans.add(span(coord_type(x + m_min_x),
  368. coord_type(len),
  369. &m_covers[x]));
  370. }
  371. m_last_x = x + len - 1;
  372. }
  373. //--------------------------------------------------------------------
  374. void finalize(int y)
  375. {
  376. m_y = y;
  377. }
  378. //--------------------------------------------------------------------
  379. void reset_spans()
  380. {
  381. m_last_x = 0x7FFFFFF0;
  382. m_spans.remove_all();
  383. }
  384. //--------------------------------------------------------------------
  385. int y() const { return m_y; }
  386. unsigned num_spans() const { return m_spans.size(); }
  387. const_iterator begin() const { return const_iterator(m_spans); }
  388. iterator begin() { return iterator(m_spans); }
  389. private:
  390. scanline32_u8(const self_type&);
  391. const self_type& operator = (const self_type&);
  392. private:
  393. int m_min_x;
  394. int m_last_x;
  395. int m_y;
  396. pod_array<cover_type> m_covers;
  397. span_array_type m_spans;
  398. };
  399. //========================================================scanline32_u8_am
  400. //
  401. // The scanline container with alpha-masking
  402. //
  403. //------------------------------------------------------------------------
  404. template<class AlphaMask>
  405. class scanline32_u8_am : public scanline32_u8
  406. {
  407. public:
  408. typedef scanline32_u8 base_type;
  409. typedef AlphaMask alpha_mask_type;
  410. typedef base_type::cover_type cover_type;
  411. typedef base_type::coord_type coord_type;
  412. scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
  413. scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
  414. //--------------------------------------------------------------------
  415. void finalize(int span_y)
  416. {
  417. base_type::finalize(span_y);
  418. if(m_alpha_mask)
  419. {
  420. typename base_type::iterator span = base_type::begin();
  421. unsigned count = base_type::num_spans();
  422. do
  423. {
  424. m_alpha_mask->combine_hspan(span->x,
  425. base_type::y(),
  426. span->covers,
  427. span->len);
  428. ++span;
  429. }
  430. while(--count);
  431. }
  432. }
  433. private:
  434. AlphaMask* m_alpha_mask;
  435. };
  436. }
  437. #endif