Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7640 views
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_shade *shade;
161
fz_pixmap *dest;
162
const fz_irect *bbox;
163
fz_color_converter cc;
164
};
165
166
static void
167
prepare_vertex(fz_context *ctx, void *arg, fz_vertex *v, const float *input)
168
{
169
struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
170
fz_shade *shade = ptd->shade;
171
fz_pixmap *dest = ptd->dest;
172
float *output = v->c;
173
int i;
174
175
if (shade->use_function)
176
output[0] = input[0] * 255;
177
else
178
{
179
ptd->cc.convert(ctx, &ptd->cc, output, input);
180
for (i = 0; i < dest->colorspace->n; i++)
181
output[i] *= 255;
182
}
183
}
184
185
static void
186
do_paint_tri(fz_context *ctx, void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv)
187
{
188
struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
189
float *vertices[3];
190
fz_pixmap *dest;
191
192
vertices[0] = (float *)av;
193
vertices[1] = (float *)bv;
194
vertices[2] = (float *)cv;
195
196
dest = ptd->dest;
197
fz_paint_triangle(dest, vertices, 2 + dest->colorspace->n, ptd->bbox);
198
}
199
200
void
201
fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap *dest, const fz_irect *bbox)
202
{
203
unsigned char clut[256][FZ_MAX_COLORS];
204
fz_pixmap *temp = NULL;
205
fz_pixmap *conv = NULL;
206
float color[FZ_MAX_COLORS];
207
struct paint_tri_data ptd = { 0 };
208
int i, k;
209
fz_matrix local_ctm;
210
211
fz_var(temp);
212
fz_var(conv);
213
214
fz_try(ctx)
215
{
216
fz_concat(&local_ctm, &shade->matrix, ctm);
217
218
if (shade->use_function)
219
{
220
fz_color_converter cc;
221
fz_lookup_color_converter(ctx, &cc, dest->colorspace, shade->colorspace);
222
for (i = 0; i < 256; i++)
223
{
224
cc.convert(ctx, &cc, color, shade->function[i]);
225
for (k = 0; k < dest->colorspace->n; k++)
226
clut[i][k] = color[k] * 255;
227
clut[i][k] = shade->function[i][shade->colorspace->n] * 255;
228
}
229
conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox);
230
temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox);
231
fz_clear_pixmap(ctx, temp);
232
}
233
else
234
{
235
temp = dest;
236
}
237
238
ptd.dest = temp;
239
ptd.shade = shade;
240
ptd.bbox = bbox;
241
242
fz_init_cached_color_converter(ctx, &ptd.cc, temp->colorspace, shade->colorspace);
243
fz_process_mesh(ctx, shade, &local_ctm, &prepare_vertex, &do_paint_tri, &ptd);
244
245
if (shade->use_function)
246
{
247
unsigned char *s = temp->samples;
248
unsigned char *d = conv->samples;
249
int len = temp->w * temp->h;
250
while (len--)
251
{
252
int v = *s++;
253
int a = fz_mul255(*s++, clut[v][conv->n - 1]);
254
for (k = 0; k < conv->n - 1; k++)
255
*d++ = fz_mul255(clut[v][k], a);
256
*d++ = a;
257
}
258
fz_paint_pixmap(dest, conv, 255);
259
fz_drop_pixmap(ctx, conv);
260
fz_drop_pixmap(ctx, temp);
261
}
262
}
263
fz_always(ctx)
264
{
265
fz_fin_cached_color_converter(ctx, &ptd.cc);
266
}
267
fz_catch(ctx)
268
{
269
fz_drop_pixmap(ctx, conv);
270
fz_drop_pixmap(ctx, temp);
271
fz_rethrow(ctx);
272
}
273
}
274
275