agg_pixfmt_rgb.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  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 high precision colors 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_PIXFMT_RGB_INCLUDED
  24. #define AGG_PIXFMT_RGB_INCLUDED
  25. #include <string.h>
  26. #include "agg_pixfmt_base.h"
  27. #include "agg_rendering_buffer.h"
  28. namespace agg
  29. {
  30. //=====================================================apply_gamma_dir_rgb
  31. template<class ColorT, class Order, class GammaLut> class apply_gamma_dir_rgb
  32. {
  33. public:
  34. typedef typename ColorT::value_type value_type;
  35. apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
  36. AGG_INLINE void operator () (value_type* p)
  37. {
  38. p[Order::R] = m_gamma.dir(p[Order::R]);
  39. p[Order::G] = m_gamma.dir(p[Order::G]);
  40. p[Order::B] = m_gamma.dir(p[Order::B]);
  41. }
  42. private:
  43. const GammaLut& m_gamma;
  44. };
  45. //=====================================================apply_gamma_inv_rgb
  46. template<class ColorT, class Order, class GammaLut> class apply_gamma_inv_rgb
  47. {
  48. public:
  49. typedef typename ColorT::value_type value_type;
  50. apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {}
  51. AGG_INLINE void operator () (value_type* p)
  52. {
  53. p[Order::R] = m_gamma.inv(p[Order::R]);
  54. p[Order::G] = m_gamma.inv(p[Order::G]);
  55. p[Order::B] = m_gamma.inv(p[Order::B]);
  56. }
  57. private:
  58. const GammaLut& m_gamma;
  59. };
  60. //=========================================================blender_rgb
  61. template<class ColorT, class Order>
  62. struct blender_rgb
  63. {
  64. typedef ColorT color_type;
  65. typedef Order order_type;
  66. typedef typename color_type::value_type value_type;
  67. typedef typename color_type::calc_type calc_type;
  68. typedef typename color_type::long_type long_type;
  69. // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's
  70. // compositing function. Since the render buffer is opaque we skip the
  71. // initial premultiply and final demultiply.
  72. //--------------------------------------------------------------------
  73. static AGG_INLINE void blend_pix(value_type* p,
  74. value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
  75. {
  76. blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
  77. }
  78. //--------------------------------------------------------------------
  79. static AGG_INLINE void blend_pix(value_type* p,
  80. value_type cr, value_type cg, value_type cb, value_type alpha)
  81. {
  82. p[Order::R] = color_type::lerp(p[Order::R], cr, alpha);
  83. p[Order::G] = color_type::lerp(p[Order::G], cg, alpha);
  84. p[Order::B] = color_type::lerp(p[Order::B], cb, alpha);
  85. }
  86. };
  87. //======================================================blender_rgb_pre
  88. template<class ColorT, class Order>
  89. struct blender_rgb_pre
  90. {
  91. typedef ColorT color_type;
  92. typedef Order order_type;
  93. typedef typename color_type::value_type value_type;
  94. typedef typename color_type::calc_type calc_type;
  95. typedef typename color_type::long_type long_type;
  96. // Blend pixels using the premultiplied form of Alvy-Ray Smith's
  97. // compositing function.
  98. //--------------------------------------------------------------------
  99. static AGG_INLINE void blend_pix(value_type* p,
  100. value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
  101. {
  102. blend_pix(p,
  103. color_type::mult_cover(cr, cover),
  104. color_type::mult_cover(cg, cover),
  105. color_type::mult_cover(cb, cover),
  106. color_type::mult_cover(alpha, cover));
  107. }
  108. //--------------------------------------------------------------------
  109. static AGG_INLINE void blend_pix(value_type* p,
  110. value_type cr, value_type cg, value_type cb, value_type alpha)
  111. {
  112. p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha);
  113. p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha);
  114. p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha);
  115. }
  116. };
  117. //===================================================blender_rgb_gamma
  118. template<class ColorT, class Order, class Gamma>
  119. class blender_rgb_gamma : public blender_base<ColorT, Order>
  120. {
  121. public:
  122. typedef ColorT color_type;
  123. typedef Order order_type;
  124. typedef Gamma gamma_type;
  125. typedef typename color_type::value_type value_type;
  126. typedef typename color_type::calc_type calc_type;
  127. typedef typename color_type::long_type long_type;
  128. //--------------------------------------------------------------------
  129. blender_rgb_gamma() : m_gamma(0) {}
  130. void gamma(const gamma_type& g) { m_gamma = &g; }
  131. //--------------------------------------------------------------------
  132. AGG_INLINE void blend_pix(value_type* p,
  133. value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover)
  134. {
  135. blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover));
  136. }
  137. //--------------------------------------------------------------------
  138. AGG_INLINE void blend_pix(value_type* p,
  139. value_type cr, value_type cg, value_type cb, value_type alpha)
  140. {
  141. calc_type r = m_gamma->dir(p[Order::R]);
  142. calc_type g = m_gamma->dir(p[Order::G]);
  143. calc_type b = m_gamma->dir(p[Order::B]);
  144. p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r);
  145. p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g);
  146. p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b);
  147. }
  148. private:
  149. const gamma_type* m_gamma;
  150. };
  151. //==================================================pixfmt_alpha_blend_rgb
  152. template<class Blender, class RenBuf, unsigned Step, unsigned Offset = 0>
  153. class pixfmt_alpha_blend_rgb
  154. {
  155. public:
  156. typedef pixfmt_rgb_tag pixfmt_category;
  157. typedef RenBuf rbuf_type;
  158. typedef Blender blender_type;
  159. typedef typename rbuf_type::row_data row_data;
  160. typedef typename blender_type::color_type color_type;
  161. typedef typename blender_type::order_type order_type;
  162. typedef typename color_type::value_type value_type;
  163. typedef typename color_type::calc_type calc_type;
  164. enum
  165. {
  166. pix_step = Step,
  167. pix_offset = Offset,
  168. pix_width = sizeof(value_type) * pix_step
  169. };
  170. struct pixel_type
  171. {
  172. value_type c[pix_step];
  173. void set(value_type r, value_type g, value_type b)
  174. {
  175. c[order_type::R] = r;
  176. c[order_type::G] = g;
  177. c[order_type::B] = b;
  178. }
  179. void set(const color_type& color)
  180. {
  181. set(color.r, color.g, color.b);
  182. }
  183. void get(value_type& r, value_type& g, value_type& b) const
  184. {
  185. r = c[order_type::R];
  186. g = c[order_type::G];
  187. b = c[order_type::B];
  188. }
  189. color_type get() const
  190. {
  191. return color_type(
  192. c[order_type::R],
  193. c[order_type::G],
  194. c[order_type::B]);
  195. }
  196. pixel_type* next()
  197. {
  198. return this + 1;
  199. }
  200. const pixel_type* next() const
  201. {
  202. return this + 1;
  203. }
  204. pixel_type* advance(int n)
  205. {
  206. return this + n;
  207. }
  208. const pixel_type* advance(int n) const
  209. {
  210. return this + n;
  211. }
  212. };
  213. private:
  214. //--------------------------------------------------------------------
  215. AGG_INLINE void blend_pix(pixel_type* p,
  216. value_type r, value_type g, value_type b, value_type a,
  217. unsigned cover)
  218. {
  219. m_blender.blend_pix(p->c, r, g, b, a, cover);
  220. }
  221. //--------------------------------------------------------------------
  222. AGG_INLINE void blend_pix(pixel_type* p,
  223. value_type r, value_type g, value_type b, value_type a)
  224. {
  225. m_blender.blend_pix(p->c, r, g, b, a);
  226. }
  227. //--------------------------------------------------------------------
  228. AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover)
  229. {
  230. m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover);
  231. }
  232. //--------------------------------------------------------------------
  233. AGG_INLINE void blend_pix(pixel_type* p, const color_type& c)
  234. {
  235. m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a);
  236. }
  237. //--------------------------------------------------------------------
  238. AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover)
  239. {
  240. if (!c.is_transparent())
  241. {
  242. if (c.is_opaque() && cover == cover_mask)
  243. {
  244. p->set(c);
  245. }
  246. else
  247. {
  248. blend_pix(p, c, cover);
  249. }
  250. }
  251. }
  252. //--------------------------------------------------------------------
  253. AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c)
  254. {
  255. if (!c.is_transparent())
  256. {
  257. if (c.is_opaque())
  258. {
  259. p->set(c);
  260. }
  261. else
  262. {
  263. blend_pix(p, c);
  264. }
  265. }
  266. }
  267. public:
  268. //--------------------------------------------------------------------
  269. explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) :
  270. m_rbuf(&rb)
  271. {}
  272. void attach(rbuf_type& rb) { m_rbuf = &rb; }
  273. //--------------------------------------------------------------------
  274. template<class PixFmt>
  275. bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
  276. {
  277. rect_i r(x1, y1, x2, y2);
  278. if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
  279. {
  280. int stride = pixf.stride();
  281. m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
  282. (r.x2 - r.x1) + 1,
  283. (r.y2 - r.y1) + 1,
  284. stride);
  285. return true;
  286. }
  287. return false;
  288. }
  289. //--------------------------------------------------------------------
  290. Blender& blender() { return m_blender; }
  291. //--------------------------------------------------------------------
  292. AGG_INLINE unsigned width() const { return m_rbuf->width(); }
  293. AGG_INLINE unsigned height() const { return m_rbuf->height(); }
  294. AGG_INLINE int stride() const { return m_rbuf->stride(); }
  295. //--------------------------------------------------------------------
  296. AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
  297. AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
  298. AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); }
  299. //--------------------------------------------------------------------
  300. AGG_INLINE int8u* pix_ptr(int x, int y)
  301. {
  302. return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
  303. }
  304. AGG_INLINE const int8u* pix_ptr(int x, int y) const
  305. {
  306. return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset);
  307. }
  308. // Return pointer to pixel value, forcing row to be allocated.
  309. AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len)
  310. {
  311. return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset));
  312. }
  313. // Return pointer to pixel value, or null if row not allocated.
  314. AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const
  315. {
  316. int8u* p = m_rbuf->row_ptr(y);
  317. return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0;
  318. }
  319. // Get pixel pointer from raw buffer pointer.
  320. AGG_INLINE static pixel_type* pix_value_ptr(void* p)
  321. {
  322. return (pixel_type*)((value_type*)p + pix_offset);
  323. }
  324. // Get pixel pointer from raw buffer pointer.
  325. AGG_INLINE static const pixel_type* pix_value_ptr(const void* p)
  326. {
  327. return (const pixel_type*)((const value_type*)p + pix_offset);
  328. }
  329. //--------------------------------------------------------------------
  330. AGG_INLINE static void write_plain_color(void* p, color_type c)
  331. {
  332. // RGB formats are implicitly premultiplied.
  333. c.premultiply();
  334. pix_value_ptr(p)->set(c);
  335. }
  336. //--------------------------------------------------------------------
  337. AGG_INLINE static color_type read_plain_color(const void* p)
  338. {
  339. return pix_value_ptr(p)->get();
  340. }
  341. //--------------------------------------------------------------------
  342. AGG_INLINE static void make_pix(int8u* p, const color_type& c)
  343. {
  344. ((pixel_type*)p)->set(c);
  345. }
  346. //--------------------------------------------------------------------
  347. AGG_INLINE color_type pixel(int x, int y) const
  348. {
  349. if (const pixel_type* p = pix_value_ptr(x, y))
  350. {
  351. return p->get();
  352. }
  353. return color_type::no_color();
  354. }
  355. //--------------------------------------------------------------------
  356. AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
  357. {
  358. pix_value_ptr(x, y, 1)->set(c);
  359. }
  360. //--------------------------------------------------------------------
  361. AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover)
  362. {
  363. copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover);
  364. }
  365. //--------------------------------------------------------------------
  366. AGG_INLINE void copy_hline(int x, int y,
  367. unsigned len,
  368. const color_type& c)
  369. {
  370. pixel_type* p = pix_value_ptr(x, y, len);
  371. do
  372. {
  373. p->set(c);
  374. p = p->next();
  375. }
  376. while(--len);
  377. }
  378. //--------------------------------------------------------------------
  379. AGG_INLINE void copy_vline(int x, int y,
  380. unsigned len,
  381. const color_type& c)
  382. {
  383. do
  384. {
  385. pix_value_ptr(x, y++, 1)->set(c);
  386. }
  387. while (--len);
  388. }
  389. //--------------------------------------------------------------------
  390. void blend_hline(int x, int y,
  391. unsigned len,
  392. const color_type& c,
  393. int8u cover)
  394. {
  395. if (!c.is_transparent())
  396. {
  397. pixel_type* p = pix_value_ptr(x, y, len);
  398. if (c.is_opaque() && cover == cover_mask)
  399. {
  400. do
  401. {
  402. p->set(c);
  403. p = p->next();
  404. }
  405. while (--len);
  406. }
  407. else
  408. {
  409. do
  410. {
  411. blend_pix(p, c, cover);
  412. p = p->next();
  413. }
  414. while (--len);
  415. }
  416. }
  417. }
  418. //--------------------------------------------------------------------
  419. void blend_vline(int x, int y,
  420. unsigned len,
  421. const color_type& c,
  422. int8u cover)
  423. {
  424. if (!c.is_transparent())
  425. {
  426. if (c.is_opaque() && cover == cover_mask)
  427. {
  428. do
  429. {
  430. pix_value_ptr(x, y++, 1)->set(c);
  431. }
  432. while (--len);
  433. }
  434. else
  435. {
  436. do
  437. {
  438. blend_pix(pix_value_ptr(x, y++, 1), c, cover);
  439. }
  440. while (--len);
  441. }
  442. }
  443. }
  444. //--------------------------------------------------------------------
  445. void blend_solid_hspan(int x, int y,
  446. unsigned len,
  447. const color_type& c,
  448. const int8u* covers)
  449. {
  450. if (!c.is_transparent())
  451. {
  452. pixel_type* p = pix_value_ptr(x, y, len);
  453. do
  454. {
  455. if (c.is_opaque() && *covers == cover_mask)
  456. {
  457. p->set(c);
  458. }
  459. else
  460. {
  461. blend_pix(p, c, *covers);
  462. }
  463. p = p->next();
  464. ++covers;
  465. }
  466. while (--len);
  467. }
  468. }
  469. //--------------------------------------------------------------------
  470. void blend_solid_vspan(int x, int y,
  471. unsigned len,
  472. const color_type& c,
  473. const int8u* covers)
  474. {
  475. if (!c.is_transparent())
  476. {
  477. do
  478. {
  479. pixel_type* p = pix_value_ptr(x, y++, 1);
  480. if (c.is_opaque() && *covers == cover_mask)
  481. {
  482. p->set(c);
  483. }
  484. else
  485. {
  486. blend_pix(p, c, *covers);
  487. }
  488. ++covers;
  489. }
  490. while (--len);
  491. }
  492. }
  493. //--------------------------------------------------------------------
  494. void copy_color_hspan(int x, int y,
  495. unsigned len,
  496. const color_type* colors)
  497. {
  498. pixel_type* p = pix_value_ptr(x, y, len);
  499. do
  500. {
  501. p->set(*colors++);
  502. p = p->next();
  503. }
  504. while (--len);
  505. }
  506. //--------------------------------------------------------------------
  507. void copy_color_vspan(int x, int y,
  508. unsigned len,
  509. const color_type* colors)
  510. {
  511. do
  512. {
  513. pix_value_ptr(x, y++, 1)->set(*colors++);
  514. }
  515. while (--len);
  516. }
  517. //--------------------------------------------------------------------
  518. void blend_color_hspan(int x, int y,
  519. unsigned len,
  520. const color_type* colors,
  521. const int8u* covers,
  522. int8u cover)
  523. {
  524. pixel_type* p = pix_value_ptr(x, y, len);
  525. if (covers)
  526. {
  527. do
  528. {
  529. copy_or_blend_pix(p, *colors++, *covers++);
  530. p = p->next();
  531. }
  532. while (--len);
  533. }
  534. else
  535. {
  536. if (cover == cover_mask)
  537. {
  538. do
  539. {
  540. copy_or_blend_pix(p, *colors++);
  541. p = p->next();
  542. }
  543. while (--len);
  544. }
  545. else
  546. {
  547. do
  548. {
  549. copy_or_blend_pix(p, *colors++, cover);
  550. p = p->next();
  551. }
  552. while (--len);
  553. }
  554. }
  555. }
  556. //--------------------------------------------------------------------
  557. void blend_color_vspan(int x, int y,
  558. unsigned len,
  559. const color_type* colors,
  560. const int8u* covers,
  561. int8u cover)
  562. {
  563. if (covers)
  564. {
  565. do
  566. {
  567. copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++);
  568. }
  569. while (--len);
  570. }
  571. else
  572. {
  573. if (cover == cover_mask)
  574. {
  575. do
  576. {
  577. copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++);
  578. }
  579. while (--len);
  580. }
  581. else
  582. {
  583. do
  584. {
  585. copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover);
  586. }
  587. while (--len);
  588. }
  589. }
  590. }
  591. //--------------------------------------------------------------------
  592. template<class Function> void for_each_pixel(Function f)
  593. {
  594. for (unsigned y = 0; y < height(); ++y)
  595. {
  596. row_data r = m_rbuf->row(y);
  597. if (r.ptr)
  598. {
  599. unsigned len = r.x2 - r.x1 + 1;
  600. pixel_type* p = pix_value_ptr(r.x1, y, len);
  601. do
  602. {
  603. f(p->c);
  604. p = p->next();
  605. }
  606. while (--len);
  607. }
  608. }
  609. }
  610. //--------------------------------------------------------------------
  611. template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
  612. {
  613. for_each_pixel(apply_gamma_dir_rgb<color_type, order_type, GammaLut>(g));
  614. }
  615. //--------------------------------------------------------------------
  616. template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
  617. {
  618. for_each_pixel(apply_gamma_inv_rgb<color_type, order_type, GammaLut>(g));
  619. }
  620. //--------------------------------------------------------------------
  621. template<class RenBuf2>
  622. void copy_from(const RenBuf2& from,
  623. int xdst, int ydst,
  624. int xsrc, int ysrc,
  625. unsigned len)
  626. {
  627. if (const int8u* p = from.row_ptr(ysrc))
  628. {
  629. memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
  630. p + xsrc * pix_width,
  631. len * pix_width);
  632. }
  633. }
  634. //--------------------------------------------------------------------
  635. // Blend from an RGBA surface.
  636. template<class SrcPixelFormatRenderer>
  637. void blend_from(const SrcPixelFormatRenderer& from,
  638. int xdst, int ydst,
  639. int xsrc, int ysrc,
  640. unsigned len,
  641. int8u cover)
  642. {
  643. typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
  644. typedef typename SrcPixelFormatRenderer::order_type src_order;
  645. if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
  646. {
  647. pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
  648. if (cover == cover_mask)
  649. {
  650. do
  651. {
  652. value_type alpha = psrc->c[src_order::A];
  653. if (alpha <= color_type::empty_value())
  654. {
  655. if (alpha >= color_type::full_value())
  656. {
  657. pdst->c[order_type::R] = psrc->c[src_order::R];
  658. pdst->c[order_type::G] = psrc->c[src_order::G];
  659. pdst->c[order_type::B] = psrc->c[src_order::B];
  660. }
  661. else
  662. {
  663. blend_pix(pdst,
  664. psrc->c[src_order::R],
  665. psrc->c[src_order::G],
  666. psrc->c[src_order::B],
  667. alpha);
  668. }
  669. }
  670. psrc = psrc->next();
  671. pdst = pdst->next();
  672. }
  673. while(--len);
  674. }
  675. else
  676. {
  677. do
  678. {
  679. copy_or_blend_pix(pdst, psrc->get(), cover);
  680. psrc = psrc->next();
  681. pdst = pdst->next();
  682. }
  683. while (--len);
  684. }
  685. }
  686. }
  687. //--------------------------------------------------------------------
  688. // Blend from single color, using grayscale surface as alpha channel.
  689. template<class SrcPixelFormatRenderer>
  690. void blend_from_color(const SrcPixelFormatRenderer& from,
  691. const color_type& color,
  692. int xdst, int ydst,
  693. int xsrc, int ysrc,
  694. unsigned len,
  695. int8u cover)
  696. {
  697. typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
  698. typedef typename SrcPixelFormatRenderer::color_type src_color_type;
  699. if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
  700. {
  701. pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
  702. do
  703. {
  704. copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0]));
  705. psrc = psrc->next();
  706. pdst = pdst->next();
  707. }
  708. while (--len);
  709. }
  710. }
  711. //--------------------------------------------------------------------
  712. // Blend from color table, using grayscale surface as indexes into table.
  713. // Obviously, this only works for integer value types.
  714. template<class SrcPixelFormatRenderer>
  715. void blend_from_lut(const SrcPixelFormatRenderer& from,
  716. const color_type* color_lut,
  717. int xdst, int ydst,
  718. int xsrc, int ysrc,
  719. unsigned len,
  720. int8u cover)
  721. {
  722. typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type;
  723. if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc))
  724. {
  725. pixel_type* pdst = pix_value_ptr(xdst, ydst, len);
  726. if (cover == cover_mask)
  727. {
  728. do
  729. {
  730. const color_type& color = color_lut[psrc->c[0]];
  731. blend_pix(pdst, color);
  732. psrc = psrc->next();
  733. pdst = pdst->next();
  734. }
  735. while(--len);
  736. }
  737. else
  738. {
  739. do
  740. {
  741. copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover);
  742. psrc = psrc->next();
  743. pdst = pdst->next();
  744. }
  745. while(--len);
  746. }
  747. }
  748. }
  749. private:
  750. rbuf_type* m_rbuf;
  751. Blender m_blender;
  752. };
  753. //-----------------------------------------------------------------------
  754. typedef blender_rgb<rgba8, order_rgb> blender_rgb24;
  755. typedef blender_rgb<rgba8, order_bgr> blender_bgr24;
  756. typedef blender_rgb<srgba8, order_rgb> blender_srgb24;
  757. typedef blender_rgb<srgba8, order_bgr> blender_sbgr24;
  758. typedef blender_rgb<rgba16, order_rgb> blender_rgb48;
  759. typedef blender_rgb<rgba16, order_bgr> blender_bgr48;
  760. typedef blender_rgb<rgba32, order_rgb> blender_rgb96;
  761. typedef blender_rgb<rgba32, order_bgr> blender_bgr96;
  762. typedef blender_rgb_pre<rgba8, order_rgb> blender_rgb24_pre;
  763. typedef blender_rgb_pre<rgba8, order_bgr> blender_bgr24_pre;
  764. typedef blender_rgb_pre<srgba8, order_rgb> blender_srgb24_pre;
  765. typedef blender_rgb_pre<srgba8, order_bgr> blender_sbgr24_pre;
  766. typedef blender_rgb_pre<rgba16, order_rgb> blender_rgb48_pre;
  767. typedef blender_rgb_pre<rgba16, order_bgr> blender_bgr48_pre;
  768. typedef blender_rgb_pre<rgba32, order_rgb> blender_rgb96_pre;
  769. typedef blender_rgb_pre<rgba32, order_bgr> blender_bgr96_pre;
  770. typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 3> pixfmt_rgb24;
  771. typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 3> pixfmt_bgr24;
  772. typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 3> pixfmt_srgb24;
  773. typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 3> pixfmt_sbgr24;
  774. typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 3> pixfmt_rgb48;
  775. typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 3> pixfmt_bgr48;
  776. typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 3> pixfmt_rgb96;
  777. typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 3> pixfmt_bgr96;
  778. typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 3> pixfmt_rgb24_pre;
  779. typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 3> pixfmt_bgr24_pre;
  780. typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 3> pixfmt_srgb24_pre;
  781. typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 3> pixfmt_sbgr24_pre;
  782. typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 3> pixfmt_rgb48_pre;
  783. typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 3> pixfmt_bgr48_pre;
  784. typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 3> pixfmt_rgb96_pre;
  785. typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 3> pixfmt_bgr96_pre;
  786. typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 0> pixfmt_rgbx32;
  787. typedef pixfmt_alpha_blend_rgb<blender_rgb24, rendering_buffer, 4, 1> pixfmt_xrgb32;
  788. typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 1> pixfmt_xbgr32;
  789. typedef pixfmt_alpha_blend_rgb<blender_bgr24, rendering_buffer, 4, 0> pixfmt_bgrx32;
  790. typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 0> pixfmt_srgbx32;
  791. typedef pixfmt_alpha_blend_rgb<blender_srgb24, rendering_buffer, 4, 1> pixfmt_sxrgb32;
  792. typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 1> pixfmt_sxbgr32;
  793. typedef pixfmt_alpha_blend_rgb<blender_sbgr24, rendering_buffer, 4, 0> pixfmt_sbgrx32;
  794. typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 0> pixfmt_rgbx64;
  795. typedef pixfmt_alpha_blend_rgb<blender_rgb48, rendering_buffer, 4, 1> pixfmt_xrgb64;
  796. typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 1> pixfmt_xbgr64;
  797. typedef pixfmt_alpha_blend_rgb<blender_bgr48, rendering_buffer, 4, 0> pixfmt_bgrx64;
  798. typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 0> pixfmt_rgbx128;
  799. typedef pixfmt_alpha_blend_rgb<blender_rgb96, rendering_buffer, 4, 1> pixfmt_xrgb128;
  800. typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 1> pixfmt_xbgr128;
  801. typedef pixfmt_alpha_blend_rgb<blender_bgr96, rendering_buffer, 4, 0> pixfmt_bgrx128;
  802. typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 0> pixfmt_rgbx32_pre;
  803. typedef pixfmt_alpha_blend_rgb<blender_rgb24_pre, rendering_buffer, 4, 1> pixfmt_xrgb32_pre;
  804. typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 1> pixfmt_xbgr32_pre;
  805. typedef pixfmt_alpha_blend_rgb<blender_bgr24_pre, rendering_buffer, 4, 0> pixfmt_bgrx32_pre;
  806. typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 0> pixfmt_srgbx32_pre;
  807. typedef pixfmt_alpha_blend_rgb<blender_srgb24_pre, rendering_buffer, 4, 1> pixfmt_sxrgb32_pre;
  808. typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 1> pixfmt_sxbgr32_pre;
  809. typedef pixfmt_alpha_blend_rgb<blender_sbgr24_pre, rendering_buffer, 4, 0> pixfmt_sbgrx32_pre;
  810. typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 0> pixfmt_rgbx64_pre;
  811. typedef pixfmt_alpha_blend_rgb<blender_rgb48_pre, rendering_buffer, 4, 1> pixfmt_xrgb64_pre;
  812. typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 1> pixfmt_xbgr64_pre;
  813. typedef pixfmt_alpha_blend_rgb<blender_bgr48_pre, rendering_buffer, 4, 0> pixfmt_bgrx64_pre;
  814. typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 0> pixfmt_rgbx128_pre;
  815. typedef pixfmt_alpha_blend_rgb<blender_rgb96_pre, rendering_buffer, 4, 1> pixfmt_xrgb128_pre;
  816. typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 1> pixfmt_xbgr128_pre;
  817. typedef pixfmt_alpha_blend_rgb<blender_bgr96_pre, rendering_buffer, 4, 0> pixfmt_bgrx128_pre;
  818. //-----------------------------------------------------pixfmt_rgb24_gamma
  819. template<class Gamma> class pixfmt_rgb24_gamma :
  820. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>
  821. {
  822. public:
  823. pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) :
  824. pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
  825. {
  826. this->blender().gamma(g);
  827. }
  828. };
  829. //-----------------------------------------------------pixfmt_srgb24_gamma
  830. template<class Gamma> class pixfmt_srgb24_gamma :
  831. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>
  832. {
  833. public:
  834. pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) :
  835. pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_rgb, Gamma>, rendering_buffer, 3>(rb)
  836. {
  837. this->blender().gamma(g);
  838. }
  839. };
  840. //-----------------------------------------------------pixfmt_bgr24_gamma
  841. template<class Gamma> class pixfmt_bgr24_gamma :
  842. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>
  843. {
  844. public:
  845. pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) :
  846. pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
  847. {
  848. this->blender().gamma(g);
  849. }
  850. };
  851. //-----------------------------------------------------pixfmt_sbgr24_gamma
  852. template<class Gamma> class pixfmt_sbgr24_gamma :
  853. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>
  854. {
  855. public:
  856. pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) :
  857. pixfmt_alpha_blend_rgb<blender_rgb_gamma<srgba8, order_bgr, Gamma>, rendering_buffer, 3>(rb)
  858. {
  859. this->blender().gamma(g);
  860. }
  861. };
  862. //-----------------------------------------------------pixfmt_rgb48_gamma
  863. template<class Gamma> class pixfmt_rgb48_gamma :
  864. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>
  865. {
  866. public:
  867. pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) :
  868. pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_rgb, Gamma>, rendering_buffer, 3>(rb)
  869. {
  870. this->blender().gamma(g);
  871. }
  872. };
  873. //-----------------------------------------------------pixfmt_bgr48_gamma
  874. template<class Gamma> class pixfmt_bgr48_gamma :
  875. public pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>
  876. {
  877. public:
  878. pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) :
  879. pixfmt_alpha_blend_rgb<blender_rgb_gamma<rgba16, order_bgr, Gamma>, rendering_buffer, 3>(rb)
  880. {
  881. this->blender().gamma(g);
  882. }
  883. };
  884. }
  885. #endif