]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - QRScanner/mobile/jni/fitz/draw-mesh.c
Add MuPDF native source codes
[hornmich/skoda-qr-demo.git] / QRScanner / mobile / jni / fitz / draw-mesh.c
1 #include "mupdf/fitz.h"
2 #include "draw-imp.h"
3
4 enum { MAXN = 2 + FZ_MAX_COLORS };
5
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)
7 {
8         unsigned char *p;
9         int c[MAXN], dc[MAXN];
10         int k, w;
11         float div, mul;
12         int x0, x1;
13
14         /* Ensure that fx0 is left edge, and fx1 is right */
15         if (fx0 > fx1)
16         {
17                 const int *v;
18                 int t = fx0; fx0 = fx1; fx1 = t;
19                 v = v0; v0 = v1; v1 = v;
20         }
21         else if (fx0 == fx1)
22                 return;
23
24         /* Clip fx0, fx1 to range */
25         if (fx0 >= cx1)
26                 return;
27         if (fx1 <= cx0)
28                 return;
29         x0 = (fx0 > cx0 ? fx0 : cx0);
30         x1 = (fx1 < cx1 ? fx1 : cx1);
31
32         w = x1 - x0;
33         if (w == 0)
34                 return;
35
36         div = 1.0f / (fx1 - fx0);
37         mul = (x0 - fx0);
38         for (k = 0; k < n; k++)
39         {
40                 dc[k] = (v1[k] - v0[k]) * div;
41                 c[k] = v0[k] + dc[k] * mul;
42         }
43
44         p = pix->samples + ((x0 - pix->x) + (y - pix->y) * pix->w) * pix->n;
45         while (w--)
46         {
47                 for (k = 0; k < n; k++)
48                 {
49                         *p++ = c[k]>>16;
50                         c[k] += dc[k];
51                 }
52                 *p++ = 255;
53         }
54 }
55
56 typedef struct edge_data_s edge_data;
57
58 struct edge_data_s
59 {
60         float x;
61         float dx;
62         int v[2*MAXN];
63 };
64
65 static inline void prepare_edge(const float *restrict vtop, const float *restrict vbot, edge_data *restrict edge, float y, int n)
66 {
67         float r = 1.0f / (vbot[1] - vtop[1]);
68         float t = (y - vtop[1]) * r;
69         float diff = vbot[0] - vtop[0];
70         int i;
71
72         edge->x = vtop[0] + diff * t;
73         edge->dx = diff * r;
74
75         for (i = 0; i < n; i++)
76         {
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);
80         }
81 }
82
83 static inline void step_edge(edge_data *edge, int n)
84 {
85         int i;
86
87         edge->x += edge->dx;
88
89         for (i = 0; i < n; i++)
90         {
91                 edge->v[i] += edge->v[i + MAXN];
92         }
93 }
94
95 static void
96 fz_paint_triangle(fz_pixmap *pix, float *v[3], int n, const fz_irect *bbox)
97 {
98         edge_data e0, e1;
99         int top, mid, bot;
100         float y, y1;
101         int minx, maxx;
102
103         top = bot = 0;
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;
108
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;
112
113         /* Magic! Ensure that mid/top/bot are all different */
114         mid = 3^top^bot;
115
116         assert(top != bot && top != mid && mid != bot);
117
118         minx = fz_maxi(bbox->x0, pix->x);
119         maxx = fz_mini(bbox->x1, pix->x + pix->w);
120
121         y = ceilf(fz_max(bbox->y0, v[top][1]));
122         y1 = ceilf(fz_min(bbox->y1, v[mid][1]));
123
124         n -= 2;
125         prepare_edge(v[top], v[bot], &e0, y, n);
126         if (y < y1)
127         {
128                 prepare_edge(v[top], v[mid], &e1, y, n);
129
130                 do
131                 {
132                         paint_scan(pix, y, (int)e0.x, (int)e1.x, minx, maxx, &e0.v[0], &e1.v[0], n);
133                         step_edge(&e0, n);
134                         step_edge(&e1, n);
135                         y ++;
136                 }
137                 while (y < y1);
138         }
139
140         y1 = ceilf(fz_min(bbox->y1, v[bot][1]));
141         if (y < y1)
142         {
143                 prepare_edge(v[mid], v[bot], &e1, y, n);
144
145                 do
146                 {
147                         paint_scan(pix, y, (int)e0.x, (int)e1.x, minx, maxx, &e0.v[0], &e1.v[0], n);
148                         y ++;
149                         if (y >= y1)
150                                 break;
151                         step_edge(&e0, n);
152                         step_edge(&e1, n);
153                 }
154                 while (1);
155         }
156 }
157
158 struct paint_tri_data
159 {
160         fz_context *ctx;
161         fz_shade *shade;
162         fz_pixmap *dest;
163         const fz_irect *bbox;
164         fz_color_converter cc;
165 };
166
167 static void
168 prepare_vertex(void *arg, fz_vertex *v, const float *input)
169 {
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;
174         int i;
175
176         if (shade->use_function)
177                 output[0] = input[0] * 255;
178         else
179         {
180                 ptd->cc.convert(&ptd->cc, output, input);
181                 for (i = 0; i < dest->colorspace->n; i++)
182                         output[i] *= 255;
183         }
184 }
185
186 static void
187 do_paint_tri(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv)
188 {
189         struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
190         float *vertices[3];
191         fz_pixmap *dest;
192
193         vertices[0] = (float *)av;
194         vertices[1] = (float *)bv;
195         vertices[2] = (float *)cv;
196
197         dest = ptd->dest;
198         fz_paint_triangle(dest, vertices, 2 + dest->colorspace->n, ptd->bbox);
199 }
200
201 void
202 fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox)
203 {
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 };
209         int i, k;
210         fz_matrix local_ctm;
211
212         fz_var(temp);
213         fz_var(conv);
214
215         fz_try(ctx)
216         {
217                 fz_concat(&local_ctm, &shade->matrix, ctm);
218
219                 if (shade->use_function)
220                 {
221                         fz_color_converter cc;
222                         fz_lookup_color_converter(&cc, ctx, dest->colorspace, shade->colorspace);
223                         for (i = 0; i < 256; i++)
224                         {
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;
229                         }
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);
233                 }
234                 else
235                 {
236                         temp = dest;
237                 }
238
239                 ptd.ctx = ctx;
240                 ptd.dest = temp;
241                 ptd.shade = shade;
242                 ptd.bbox = bbox;
243
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);
246
247                 if (shade->use_function)
248                 {
249                         unsigned char *s = temp->samples;
250                         unsigned char *d = conv->samples;
251                         int len = temp->w * temp->h;
252                         while (len--)
253                         {
254                                 int v = *s++;
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);
258                                 *d++ = a;
259                         }
260                         fz_paint_pixmap(dest, conv, 255);
261                         fz_drop_pixmap(ctx, conv);
262                         fz_drop_pixmap(ctx, temp);
263                 }
264         }
265         fz_always(ctx)
266         {
267                 fz_fin_cached_color_converter(&ptd.cc);
268         }
269         fz_catch(ctx)
270         {
271                 fz_drop_pixmap(ctx, conv);
272                 fz_drop_pixmap(ctx, temp);
273                 fz_rethrow(ctx);
274         }
275 }