1 #include "mupdf/fitz.h"
4 enum { MAXN = 2 + FZ_MAX_COLORS };
6 static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0, int cx1, const int *restrict v0, const int *restrict v1, int n)
14 /* Ensure that fx0 is left edge, and fx1 is right */
18 int t = fx0; fx0 = fx1; fx1 = t;
19 v = v0; v0 = v1; v1 = v;
24 /* Clip fx0, fx1 to range */
29 x0 = (fx0 > cx0 ? fx0 : cx0);
30 x1 = (fx1 < cx1 ? fx1 : cx1);
36 div = 1.0f / (fx1 - fx0);
38 for (k = 0; k < n; k++)
40 dc[k] = (v1[k] - v0[k]) * div;
41 c[k] = v0[k] + dc[k] * mul;
44 p = pix->samples + ((x0 - pix->x) + (y - pix->y) * pix->w) * pix->n;
47 for (k = 0; k < n; k++)
56 typedef struct edge_data_s edge_data;
65 static inline void prepare_edge(const float *restrict vtop, const float *restrict vbot, edge_data *restrict edge, float y, int n)
67 float r = 1.0f / (vbot[1] - vtop[1]);
68 float t = (y - vtop[1]) * r;
69 float diff = vbot[0] - vtop[0];
72 edge->x = vtop[0] + diff * t;
75 for (i = 0; i < n; i++)
77 diff = vbot[i+2] - vtop[i+2];
78 edge->v[i] = (int)(65536.0f * (vtop[i+2] + diff * t));
79 edge->v[i+MAXN] = (int)(65536.0f * diff * r);
83 static inline void step_edge(edge_data *edge, int n)
89 for (i = 0; i < n; i++)
91 edge->v[i] += edge->v[i + MAXN];
96 fz_paint_triangle(fz_pixmap *pix, float *v[3], int n, const fz_irect *bbox)
104 if (v[1][1] < v[0][1]) top = 1; else bot = 1;
105 if (v[2][1] < v[top][1]) top = 2;
106 else if (v[2][1] > v[bot][1]) bot = 2;
107 if (v[top][1] == v[bot][1]) return;
109 /* Test if the triangle is completely outside the scissor rect */
110 if (v[bot][1] < bbox->y0) return;
111 if (v[top][1] > bbox->y1) return;
113 /* Magic! Ensure that mid/top/bot are all different */
116 assert(top != bot && top != mid && mid != bot);
118 minx = fz_maxi(bbox->x0, pix->x);
119 maxx = fz_mini(bbox->x1, pix->x + pix->w);
121 y = ceilf(fz_max(bbox->y0, v[top][1]));
122 y1 = ceilf(fz_min(bbox->y1, v[mid][1]));
125 prepare_edge(v[top], v[bot], &e0, y, n);
128 prepare_edge(v[top], v[mid], &e1, y, n);
132 paint_scan(pix, y, (int)e0.x, (int)e1.x, minx, maxx, &e0.v[0], &e1.v[0], n);
140 y1 = ceilf(fz_min(bbox->y1, v[bot][1]));
143 prepare_edge(v[mid], v[bot], &e1, y, n);
147 paint_scan(pix, y, (int)e0.x, (int)e1.x, minx, maxx, &e0.v[0], &e1.v[0], n);
158 struct paint_tri_data
163 const fz_irect *bbox;
164 fz_color_converter cc;
168 prepare_vertex(void *arg, fz_vertex *v, const float *input)
170 struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
171 fz_shade *shade = ptd->shade;
172 fz_pixmap *dest = ptd->dest;
173 float *output = v->c;
176 if (shade->use_function)
177 output[0] = input[0] * 255;
180 ptd->cc.convert(&ptd->cc, output, input);
181 for (i = 0; i < dest->colorspace->n; i++)
187 do_paint_tri(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv)
189 struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
193 vertices[0] = (float *)av;
194 vertices[1] = (float *)bv;
195 vertices[2] = (float *)cv;
198 fz_paint_triangle(dest, vertices, 2 + dest->colorspace->n, ptd->bbox);
202 fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox)
204 unsigned char clut[256][FZ_MAX_COLORS];
205 fz_pixmap *temp = NULL;
206 fz_pixmap *conv = NULL;
207 float color[FZ_MAX_COLORS];
208 struct paint_tri_data ptd = { 0 };
217 fz_concat(&local_ctm, &shade->matrix, ctm);
219 if (shade->use_function)
221 fz_color_converter cc;
222 fz_lookup_color_converter(&cc, ctx, dest->colorspace, shade->colorspace);
223 for (i = 0; i < 256; i++)
225 cc.convert(&cc, color, shade->function[i]);
226 for (k = 0; k < dest->colorspace->n; k++)
227 clut[i][k] = color[k] * 255;
228 clut[i][k] = shade->function[i][shade->colorspace->n] * 255;
230 conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox);
231 temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox);
232 fz_clear_pixmap(ctx, temp);
244 fz_init_cached_color_converter(ctx, &ptd.cc, temp->colorspace, shade->colorspace);
245 fz_process_mesh(ctx, shade, &local_ctm, &prepare_vertex, &do_paint_tri, &ptd);
247 if (shade->use_function)
249 unsigned char *s = temp->samples;
250 unsigned char *d = conv->samples;
251 int len = temp->w * temp->h;
255 int a = fz_mul255(*s++, clut[v][conv->n - 1]);
256 for (k = 0; k < conv->n - 1; k++)
257 *d++ = fz_mul255(clut[v][k], a);
260 fz_paint_pixmap(dest, conv, 255);
261 fz_drop_pixmap(ctx, conv);
262 fz_drop_pixmap(ctx, temp);
267 fz_fin_cached_color_converter(&ptd.cc);
271 fz_drop_pixmap(ctx, conv);
272 fz_drop_pixmap(ctx, temp);