Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2.  
  3. typedef unsigned char byte;
  4.  
  5. static inline float roundup(float x)
  6. {
  7.         return (x < 0) ? floorf(x) : ceilf(x);
  8. }
  9.  
  10. static inline int lerp(int a, int b, int t)
  11. {
  12.         return a + (((b - a) * t) >> 16);
  13. }
  14.  
  15. static inline int bilerp(int a, int b, int c, int d, int u, int v)
  16. {
  17.         return lerp(lerp(a, b, u), lerp(c, d, u), v);
  18. }
  19.  
  20. static inline byte *sample_nearest(byte *s, int w, int h, int n, int u, int v)
  21. {
  22.         if (u < 0) u = 0;
  23.         if (v < 0) v = 0;
  24.         if (u >= w) u = w - 1;
  25.         if (v >= h) v = h - 1;
  26.         return s + (v * w + u) * n;
  27. }
  28.  
  29. /* Blend premultiplied source image in constant alpha over destination */
  30.  
  31. static inline void
  32. fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
  33. {
  34.         int k;
  35.         int n1 = n-1;
  36.  
  37.         while (w--)
  38.         {
  39.                 int ui = u >> 16;
  40.                 int vi = v >> 16;
  41.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  42.                 {
  43.                         int uf = u & 0xffff;
  44.                         int vf = v & 0xffff;
  45.                         byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
  46.                         byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
  47.                         byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
  48.                         byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
  49.                         int xa = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
  50.                         int t;
  51.                         xa = fz_mul255(xa, alpha);
  52.                         t = 255 - xa;
  53.                         for (k = 0; k < n1; k++)
  54.                         {
  55.                                 int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
  56.                                 dp[k] = fz_mul255(x, alpha) + fz_mul255(dp[k], t);
  57.                         }
  58.                         dp[n1] = xa + fz_mul255(dp[n1], t);
  59.                         if (hp)
  60.                                 hp[0] = xa + fz_mul255(hp[n1], t);
  61.                 }
  62.                 dp += n;
  63.                 if (hp)
  64.                         hp++;
  65.                 u += fa;
  66.                 v += fb;
  67.         }
  68. }
  69.  
  70. /* Special case code for gray -> rgb */
  71. static inline void
  72. fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
  73. {
  74.         while (w--)
  75.         {
  76.                 int ui = u >> 16;
  77.                 int vi = v >> 16;
  78.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  79.                 {
  80.                         int uf = u & 0xffff;
  81.                         int vf = v & 0xffff;
  82.                         byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
  83.                         byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
  84.                         byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
  85.                         byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
  86.                         int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
  87.                         int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
  88.                         int t;
  89.                         x = fz_mul255(x, alpha);
  90.                         y = fz_mul255(y, alpha);
  91.                         t = 255 - y;
  92.                         dp[0] = x + fz_mul255(dp[0], t);
  93.                         dp[1] = x + fz_mul255(dp[1], t);
  94.                         dp[2] = x + fz_mul255(dp[2], t);
  95.                         dp[3] = y + fz_mul255(dp[3], t);
  96.                         if (hp)
  97.                                 hp[0] = y + fz_mul255(hp[0], t);
  98.                 }
  99.                 dp += 4;
  100.                 if (hp)
  101.                         hp++;
  102.                 u += fa;
  103.                 v += fb;
  104.         }
  105. }
  106.  
  107. static inline void
  108. fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
  109. {
  110.         int k;
  111.         int n1 = n-1;
  112.  
  113.         while (w--)
  114.         {
  115.                 int ui = u >> 16;
  116.                 int vi = v >> 16;
  117.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  118.                 {
  119.                         byte *sample = sp + ((vi * sw + ui) * n);
  120.                         int a = fz_mul255(sample[n-1], alpha);
  121.                         int t = 255 - a;
  122.                         for (k = 0; k < n1; k++)
  123.                                 dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
  124.                         dp[n1] = a + fz_mul255(dp[n1], t);
  125.                         if (hp)
  126.                                 hp[0] = a + fz_mul255(hp[n1], t);
  127.                 }
  128.                 dp += n;
  129.                 if (hp)
  130.                         hp++;
  131.                 u += fa;
  132.                 v += fb;
  133.         }
  134. }
  135.  
  136. static inline void
  137. fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
  138. {
  139.         while (w--)
  140.         {
  141.                 int ui = u >> 16;
  142.                 int vi = v >> 16;
  143.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  144.                 {
  145.                         byte *sample = sp + ((vi * sw + ui) * 2);
  146.                         int x = fz_mul255(sample[0], alpha);
  147.                         int a = fz_mul255(sample[1], alpha);
  148.                         int t = 255 - a;
  149.                         dp[0] = x + fz_mul255(dp[0], t);
  150.                         dp[1] = x + fz_mul255(dp[1], t);
  151.                         dp[2] = x + fz_mul255(dp[2], t);
  152.                         dp[3] = a + fz_mul255(dp[3], t);
  153.                         if (hp)
  154.                                 hp[0] = a + fz_mul255(hp[0], t);
  155.                 }
  156.                 dp += 4;
  157.                 if (hp)
  158.                         hp++;
  159.                 u += fa;
  160.                 v += fb;
  161.         }
  162. }
  163.  
  164. /* Blend premultiplied source image over destination */
  165.  
  166. static inline void
  167. fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
  168. {
  169.         int k;
  170.         int n1 = n-1;
  171.  
  172.         while (w--)
  173.         {
  174.                 int ui = u >> 16;
  175.                 int vi = v >> 16;
  176.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  177.                 {
  178.                         int uf = u & 0xffff;
  179.                         int vf = v & 0xffff;
  180.                         byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
  181.                         byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
  182.                         byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
  183.                         byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
  184.                         int y = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
  185.                         int t = 255 - y;
  186.                         for (k = 0; k < n1; k++)
  187.                         {
  188.                                 int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
  189.                                 dp[k] = x + fz_mul255(dp[k], t);
  190.                         }
  191.                         dp[n1] = y + fz_mul255(dp[n1], t);
  192.                         if (hp)
  193.                                 hp[0] = y + fz_mul255(hp[0], t);
  194.                 }
  195.                 dp += n;
  196.                 if (hp)
  197.                         hp++;
  198.                 u += fa;
  199.                 v += fb;
  200.         }
  201. }
  202.  
  203. static inline void
  204. fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
  205. {
  206.         while (w--)
  207.         {
  208.                 int ui = u >> 16;
  209.                 int vi = v >> 16;
  210.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  211.                 {
  212.                         int uf = u & 0xffff;
  213.                         int vf = v & 0xffff;
  214.                         byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
  215.                         byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
  216.                         byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
  217.                         byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
  218.                         int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
  219.                         int t = 255 - y;
  220.                         int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
  221.                         dp[0] = x + fz_mul255(dp[0], t);
  222.                         dp[1] = x + fz_mul255(dp[1], t);
  223.                         dp[2] = x + fz_mul255(dp[2], t);
  224.                         dp[3] = y + fz_mul255(dp[3], t);
  225.                         if (hp)
  226.                                 hp[0] = y + fz_mul255(hp[0], t);
  227.                 }
  228.                 dp += 4;
  229.                 if (hp)
  230.                         hp++;
  231.                 u += fa;
  232.                 v += fb;
  233.         }
  234. }
  235.  
  236. static inline void
  237. fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
  238. {
  239.         int k;
  240.         int n1 = n-1;
  241.  
  242.         while (w--)
  243.         {
  244.                 int ui = u >> 16;
  245.                 int vi = v >> 16;
  246.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  247.                 {
  248.                         byte *sample = sp + ((vi * sw + ui) * n);
  249.                         int a = sample[n1];
  250.                         int t = 255 - a;
  251.                         for (k = 0; k < n1; k++)
  252.                                 dp[k] = sample[k] + fz_mul255(dp[k], t);
  253.                         dp[n1] = a + fz_mul255(dp[n1], t);
  254.                         if (hp)
  255.                                 hp[0] = a + fz_mul255(hp[0], t);
  256.                 }
  257.                 dp += n;
  258.                 if (hp)
  259.                         hp++;
  260.                 u += fa;
  261.                 v += fb;
  262.         }
  263. }
  264.  
  265. static inline void
  266. fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
  267. {
  268.         while (w--)
  269.         {
  270.                 int ui = u >> 16;
  271.                 int vi = v >> 16;
  272.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  273.                 {
  274.                         byte *sample = sp + ((vi * sw + ui) * 2);
  275.                         int x = sample[0];
  276.                         int a = sample[1];
  277.                         int t = 255 - a;
  278.                         dp[0] = x + fz_mul255(dp[0], t);
  279.                         dp[1] = x + fz_mul255(dp[1], t);
  280.                         dp[2] = x + fz_mul255(dp[2], t);
  281.                         dp[3] = a + fz_mul255(dp[3], t);
  282.                         if (hp)
  283.                                 hp[0] = a + fz_mul255(hp[0], t);
  284.                 }
  285.                 dp += 4;
  286.                 if (hp)
  287.                         hp++;
  288.                 u += fa;
  289.                 v += fb;
  290.         }
  291. }
  292.  
  293. /* Blend non-premultiplied color in source image mask over destination */
  294.  
  295. static inline void
  296. fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
  297. {
  298.         int n1 = n - 1;
  299.         int sa = color[n1];
  300.         int k;
  301.  
  302.         while (w--)
  303.         {
  304.                 int ui = u >> 16;
  305.                 int vi = v >> 16;
  306.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  307.                 {
  308.                         int uf = u & 0xffff;
  309.                         int vf = v & 0xffff;
  310.                         byte *a = sample_nearest(sp, sw, sh, 1, ui, vi);
  311.                         byte *b = sample_nearest(sp, sw, sh, 1, ui+1, vi);
  312.                         byte *c = sample_nearest(sp, sw, sh, 1, ui, vi+1);
  313.                         byte *d = sample_nearest(sp, sw, sh, 1, ui+1, vi+1);
  314.                         int ma = bilerp(a[0], b[0], c[0], d[0], uf, vf);
  315.                         int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
  316.                         for (k = 0; k < n1; k++)
  317.                                 dp[k] = FZ_BLEND(color[k], dp[k], masa);
  318.                         dp[n1] = FZ_BLEND(255, dp[n1], masa);
  319.                         if (hp)
  320.                                 hp[0] = FZ_BLEND(255, hp[0], masa);
  321.                 }
  322.                 dp += n;
  323.                 if (hp)
  324.                         hp++;
  325.                 u += fa;
  326.                 v += fb;
  327.         }
  328. }
  329.  
  330. static inline void
  331. fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
  332. {
  333.         int n1 = n-1;
  334.         int sa = color[n1];
  335.         int k;
  336.  
  337.         while (w--)
  338.         {
  339.                 int ui = u >> 16;
  340.                 int vi = v >> 16;
  341.                 if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
  342.                 {
  343.                         int ma = sp[vi * sw + ui];
  344.                         int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
  345.                         for (k = 0; k < n1; k++)
  346.                                 dp[k] = FZ_BLEND(color[k], dp[k], masa);
  347.                         dp[n1] = FZ_BLEND(255, dp[n1], masa);
  348.                         if (hp)
  349.                                 hp[n1] = FZ_BLEND(255, hp[n1], masa);
  350.                 }
  351.                 dp += n;
  352.                 if (hp)
  353.                         hp++;
  354.                 u += fa;
  355.                 v += fb;
  356.         }
  357. }
  358.  
  359. static void
  360. fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
  361. {
  362.         if (alpha == 255)
  363.         {
  364.                 switch (n)
  365.                 {
  366.                 case 1: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
  367.                 case 2: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
  368.                 case 4: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
  369.                 default: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
  370.                 }
  371.         }
  372.         else if (alpha > 0)
  373.         {
  374.                 switch (n)
  375.                 {
  376.                 case 1: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
  377.                 case 2: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
  378.                 case 4: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
  379.                 default: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
  380.                 }
  381.         }
  382. }
  383.  
  384. static void
  385. fz_paint_affine_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
  386. {
  387.         if (alpha == 255)
  388.         {
  389.                 fz_paint_affine_solid_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, hp);
  390.         }
  391.         else if (alpha > 0)
  392.         {
  393.                 fz_paint_affine_alpha_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
  394.         }
  395. }
  396.  
  397. static void
  398. fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */, byte *hp)
  399. {
  400.         if (alpha == 255)
  401.         {
  402.                 switch (n)
  403.                 {
  404.                 case 1: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
  405.                 case 2: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
  406.                 case 4: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
  407.                 default: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
  408.                 }
  409.         }
  410.         else if (alpha > 0)
  411.         {
  412.                 switch (n)
  413.                 {
  414.                 case 1: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
  415.                 case 2: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
  416.                 case 4: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
  417.                 default: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
  418.                 }
  419.         }
  420. }
  421.  
  422. static void
  423. fz_paint_affine_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
  424. {
  425.         if (alpha == 255)
  426.         {
  427.                 fz_paint_affine_solid_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, hp);
  428.         }
  429.         else if (alpha > 0)
  430.         {
  431.                 fz_paint_affine_alpha_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
  432.         }
  433. }
  434.  
  435. static void
  436. fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
  437. {
  438.         switch (n)
  439.         {
  440.         case 2: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
  441.         case 4: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
  442.         default: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
  443.         }
  444. }
  445.  
  446. static void
  447. fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
  448. {
  449.         switch (n)
  450.         {
  451.         case 2: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
  452.         case 4: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
  453.         default: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
  454.         }
  455. }
  456.  
  457. /* Draw an image with an affine transform on destination */
  458.  
  459. static void
  460. fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color, int alpha)
  461. {
  462.         byte *dp, *sp, *hp;
  463.         int u, v, fa, fb, fc, fd;
  464.         int x, y, w, h;
  465.         int sw, sh, n, hw;
  466.         fz_matrix inv;
  467.         fz_bbox bbox;
  468.         int dolerp;
  469.         void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp);
  470.  
  471.         /* grid fit the image */
  472.         if (fz_is_rectilinear(ctm))
  473.         {
  474.                 ctm.a = roundup(ctm.a);
  475.                 ctm.b = roundup(ctm.b);
  476.                 ctm.c = roundup(ctm.c);
  477.                 ctm.d = roundup(ctm.d);
  478.                 ctm.e = floorf(ctm.e);
  479.                 ctm.f = floorf(ctm.f);
  480.         }
  481.  
  482.         /* turn on interpolation for upscaled and non-rectilinear transforms */
  483.         dolerp = 0;
  484.         if (!fz_is_rectilinear(ctm))
  485.                 dolerp = 1;
  486.         if (sqrtf(ctm.a * ctm.a + ctm.b * ctm.b) > img->w)
  487.                 dolerp = 1;
  488.         if (sqrtf(ctm.c * ctm.c + ctm.d * ctm.d) > img->h)
  489.                 dolerp = 1;
  490.  
  491.         /* except when we shouldn't, at large magnifications */
  492.         if (!img->interpolate)
  493.         {
  494.                 if (sqrtf(ctm.a * ctm.a + ctm.b * ctm.b) > img->w * 2)
  495.                         dolerp = 0;
  496.                 if (sqrtf(ctm.c * ctm.c + ctm.d * ctm.d) > img->h * 2)
  497.                         dolerp = 0;
  498.         }
  499.  
  500.         bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect));
  501.         bbox = fz_intersect_bbox(bbox, scissor);
  502.         x = bbox.x0;
  503.         y = bbox.y0;
  504.         w = bbox.x1 - bbox.x0;
  505.         h = bbox.y1 - bbox.y0;
  506.  
  507.         /* map from screen space (x,y) to image space (u,v) */
  508.         inv = fz_scale(1.0f / img->w, -1.0f / img->h);
  509.         inv = fz_concat(inv, fz_translate(0, 1));
  510.         inv = fz_concat(inv, ctm);
  511.         inv = fz_invert_matrix(inv);
  512.  
  513.         fa = inv.a * 65536;
  514.         fb = inv.b * 65536;
  515.         fc = inv.c * 65536;
  516.         fd = inv.d * 65536;
  517.  
  518.         /* Calculate initial texture positions. Do a half step to start. */
  519.         u = (fa * x) + (fc * y) + inv.e * 65536 + ((fa + fc) >> 1);
  520.         v = (fb * x) + (fd * y) + inv.f * 65536 + ((fb + fd) >> 1);
  521.  
  522.         dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
  523.         n = dst->n;
  524.         sp = img->samples;
  525.         sw = img->w;
  526.         sh = img->h;
  527.         if (shape)
  528.         {
  529.                 hw = shape->w;
  530.                 hp = shape->samples + ((y - shape->y) * hw) + x - dst->x;
  531.         }
  532.         else
  533.         {
  534.                 hw = 0;
  535.                 hp = NULL;
  536.         }
  537.  
  538.         /* TODO: if (fb == 0 && fa == 1) call fz_paint_span */
  539.  
  540.         if (dst->n == 4 && img->n == 2)
  541.         {
  542.                 assert(color == NULL);
  543.                 if (dolerp)
  544.                         paintfn = fz_paint_affine_g2rgb_lerp;
  545.                 else
  546.                         paintfn = fz_paint_affine_g2rgb_near;
  547.         }
  548.         else
  549.         {
  550.                 if (dolerp)
  551.                 {
  552.                         if (color)
  553.                                 paintfn = fz_paint_affine_color_lerp;
  554.                         else
  555.                                 paintfn = fz_paint_affine_lerp;
  556.                 }
  557.                 else
  558.                 {
  559.                         if (color)
  560.                                 paintfn = fz_paint_affine_color_near;
  561.                         else
  562.                                 paintfn = fz_paint_affine_near;
  563.                 }
  564.         }
  565.  
  566.         while (h--)
  567.         {
  568.                 paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color, hp);
  569.                 dp += dst->w * n;
  570.                 hp += hw;
  571.                 u += fc;
  572.                 v += fd;
  573.         }
  574. }
  575.  
  576. void
  577. fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, byte *color)
  578. {
  579.         assert(img->n == 1);
  580.         fz_paint_image_imp(dst, scissor, shape, img, ctm, color, 255);
  581. }
  582.  
  583. void
  584. fz_paint_image(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha)
  585. {
  586.         assert(dst->n == img->n || (dst->n == 4 && img->n == 2));
  587.         fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha);
  588. }
  589.