Coverage Report

Created: 2023-06-07 06:20

/src/mupdf/source/fitz/shade.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
#include <string.h>
26
#include <math.h>
27
28
typedef struct
29
{
30
  fz_shade *shade;
31
  fz_shade_prepare_fn *prepare;
32
  fz_shade_process_fn *process;
33
  void *process_arg;
34
  int ncomp;
35
} fz_mesh_processor;
36
37
39.5k
#define SWAP(a,b) {fz_vertex *t = (a); (a) = (b); (b) = t;}
38
39
static inline void
40
paint_tri(fz_context *ctx, fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2)
41
14.0k
{
42
14.0k
  if (painter->process)
43
14.0k
  {
44
14.0k
    painter->process(ctx, painter->process_arg, v0, v1, v2);
45
14.0k
  }
46
14.0k
}
47
48
static inline void
49
paint_quad(fz_context *ctx, fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2, fz_vertex *v3)
50
1.56M
{
51
  /* For a quad with corners (in clockwise or anticlockwise order) are
52
   * v0, v1, v2, v3. We can choose to split in in various different ways.
53
   * Arbitrarily we can pick v0, v1, v3 for the first triangle. We then
54
   * have to choose between v1, v2, v3 or v3, v2, v1 (or their equivalent
55
   * rotations) for the second triangle.
56
   *
57
   * v1, v2, v3 has the property that both triangles share the same
58
   * winding (useful if we were ever doing simple back face culling).
59
   *
60
   * v3, v2, v1 has the property that all the 'shared' edges (both
61
   * within this quad, and with adjacent quads) are walked in the same
62
   * direction every time. This can be useful in that depending on the
63
   * implementation/rounding etc walking from A -> B can hit different
64
   * pixels than walking from B->A.
65
   *
66
   * In the event neither of these things matter at the moment, as all
67
   * the process functions where it matters order the edges from top to
68
   * bottom before walking them.
69
   */
70
1.56M
  if (painter->process)
71
1.56M
  {
72
1.56M
    painter->process(ctx, painter->process_arg, v0, v1, v3);
73
1.56M
    painter->process(ctx, painter->process_arg, v3, v2, v1);
74
1.56M
  }
75
1.56M
}
76
77
static inline void
78
fz_prepare_color(fz_context *ctx, fz_mesh_processor *painter, fz_vertex *v, float *c)
79
5.40M
{
80
5.40M
  if (painter->prepare)
81
5.40M
  {
82
5.40M
    painter->prepare(ctx, painter->process_arg, v, c);
83
5.40M
  }
84
5.40M
}
85
86
static inline void
87
fz_prepare_vertex(fz_context *ctx, fz_mesh_processor *painter, fz_vertex *v, fz_matrix ctm, float x, float y, float *c)
88
225k
{
89
225k
  v->p = fz_transform_point_xy(x, y, ctm);
90
225k
  if (painter->prepare)
91
225k
  {
92
225k
    painter->prepare(ctx, painter->process_arg, v, c);
93
225k
  }
94
225k
}
95
96
static void
97
fz_process_shade_type1(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
98
2
{
99
2
  float *p = shade->u.f.fn_vals;
100
2
  int xdivs = shade->u.f.xdivs;
101
2
  int ydivs = shade->u.f.ydivs;
102
2
  float x0 = shade->u.f.domain[0][0];
103
2
  float y0 = shade->u.f.domain[0][1];
104
2
  float x1 = shade->u.f.domain[1][0];
105
2
  float y1 = shade->u.f.domain[1][1];
106
2
  int xx, yy;
107
2
  float y, yn, x;
108
2
  fz_vertex vs[2][2];
109
2
  fz_vertex *v = vs[0];
110
2
  fz_vertex *vn = vs[1];
111
2
  int n = fz_colorspace_n(ctx, shade->colorspace);
112
113
2
  ctm = fz_concat(shade->u.f.matrix, ctm);
114
115
2
  y = y0;
116
130
  for (yy = 0; yy < ydivs; yy++)
117
128
  {
118
128
    yn = y0 + (y1 - y0) * (yy + 1) / ydivs;
119
120
128
    x = x0;
121
122
128
    fz_prepare_vertex(ctx, painter, &v[0], ctm, x, y, p);
123
128
    p += n;
124
128
    fz_prepare_vertex(ctx, painter, &v[1], ctm, x, yn, p + xdivs * n);
125
126
8.32k
    for (xx = 0; xx < xdivs; xx++)
127
8.19k
    {
128
8.19k
      x = x0 + (x1 - x0) * (xx + 1) / xdivs;
129
130
8.19k
      fz_prepare_vertex(ctx, painter, &vn[0], ctm, x, y, p);
131
8.19k
      p += n;
132
8.19k
      fz_prepare_vertex(ctx, painter, &vn[1], ctm, x, yn, p + xdivs * n);
133
134
8.19k
      paint_quad(ctx, painter, &v[0], &vn[0], &vn[1], &v[1]);
135
8.19k
      SWAP(v,vn);
136
8.19k
    }
137
128
    y = yn;
138
128
  }
139
2
}
140
141
20
#define HUGENUM 32000 /* how far to extend linear/radial shadings */
142
143
static fz_point
144
fz_point_on_circle(fz_point p, float r, float theta)
145
132k
{
146
132k
  p.x = p.x + cosf(theta) * r;
147
132k
  p.y = p.y + sinf(theta) * r;
148
132k
  return p;
149
132k
}
150
151
static void
152
fz_process_shade_type2(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter, fz_rect scissor)
153
57.9k
{
154
57.9k
  fz_point p0, p1, dir;
155
57.9k
  fz_vertex v0, v1, v2, v3;
156
57.9k
  fz_vertex e0, e1;
157
57.9k
  float theta;
158
57.9k
  float zero = 0;
159
57.9k
  float one = 1;
160
57.9k
  float r;
161
162
57.9k
  p0.x = shade->u.l_or_r.coords[0][0];
163
57.9k
  p0.y = shade->u.l_or_r.coords[0][1];
164
57.9k
  p1.x = shade->u.l_or_r.coords[1][0];
165
57.9k
  p1.y = shade->u.l_or_r.coords[1][1];
166
57.9k
  dir.x = p0.y - p1.y;
167
57.9k
  dir.y = p1.x - p0.x;
168
57.9k
  p0 = fz_transform_point(p0, ctm);
169
57.9k
  p1 = fz_transform_point(p1, ctm);
170
57.9k
  dir = fz_transform_vector(dir, ctm);
171
57.9k
  theta = atan2f(dir.y, dir.x);
172
173
57.9k
  if (fz_is_infinite_rect(scissor)) {
174
0
    r = HUGENUM; /* Not ideal, but it'll do for now */
175
57.9k
  } else {
176
57.9k
    float x = p0.x - scissor.x0;
177
57.9k
    float y = p0.y - scissor.y0;
178
57.9k
    if (x < scissor.x1 - p0.x)
179
56.1k
      x = scissor.x1 - p0.x;
180
57.9k
    if (x < p0.x - scissor.x1)
181
0
      x = p0.x - scissor.x1;
182
57.9k
    if (x < scissor.x1 - p1.x)
183
530
      x = scissor.x1 - p1.x;
184
57.9k
    if (y < scissor.y1 - p0.y)
185
19.7k
      y = scissor.y1 - p0.y;
186
57.9k
    if (y < p0.y - scissor.y1)
187
0
      y = p0.y - scissor.y1;
188
57.9k
    if (y < scissor.y1 - p1.y)
189
1.28k
      y = scissor.y1 - p1.y;
190
57.9k
    r = x+y;
191
57.9k
  }
192
57.9k
  v0.p = fz_point_on_circle(p0, r, theta);
193
57.9k
  v1.p = fz_point_on_circle(p1, r, theta);
194
57.9k
  v2.p.x = 2*p0.x - v0.p.x;
195
57.9k
  v2.p.y = 2*p0.y - v0.p.y;
196
57.9k
  v3.p.x = 2*p1.x - v1.p.x;
197
57.9k
  v3.p.y = 2*p1.y - v1.p.y;
198
199
57.9k
  fz_prepare_color(ctx, painter, &v0, &zero);
200
57.9k
  fz_prepare_color(ctx, painter, &v1, &one);
201
57.9k
  fz_prepare_color(ctx, painter, &v2, &zero);
202
57.9k
  fz_prepare_color(ctx, painter, &v3, &one);
203
204
57.9k
  paint_quad(ctx, painter, &v0, &v2, &v3, &v1);
205
206
57.9k
  if (shade->u.l_or_r.extend[0] || shade->u.l_or_r.extend[1]) {
207
57.9k
    float d = fabsf(p1.x - p0.x);
208
57.9k
    float e = fabsf(p1.y - p0.y);
209
57.9k
    if (d < e)
210
4.84k
      d = e;
211
57.9k
    if (d != 0)
212
57.9k
      r /= d;
213
57.9k
  }
214
57.9k
  if (shade->u.l_or_r.extend[0])
215
57.9k
  {
216
57.9k
    e0.p.x = v0.p.x - (p1.x - p0.x) * r;
217
57.9k
    e0.p.y = v0.p.y - (p1.y - p0.y) * r;
218
57.9k
    fz_prepare_color(ctx, painter, &e0, &zero);
219
220
57.9k
    e1.p.x = v2.p.x - (p1.x - p0.x) * r;
221
57.9k
    e1.p.y = v2.p.y - (p1.y - p0.y) * r;
222
57.9k
    fz_prepare_color(ctx, painter, &e1, &zero);
223
224
57.9k
    paint_quad(ctx, painter, &e0, &v0, &v2, &e1);
225
57.9k
  }
226
227
57.9k
  if (shade->u.l_or_r.extend[1])
228
57.9k
  {
229
57.9k
    e0.p.x = v1.p.x + (p1.x - p0.x) * r;
230
57.9k
    e0.p.y = v1.p.y + (p1.y - p0.y) * r;
231
57.9k
    fz_prepare_color(ctx, painter, &e0, &one);
232
233
57.9k
    e1.p.x = v3.p.x + (p1.x - p0.x) * r;
234
57.9k
    e1.p.y = v3.p.y + (p1.y - p0.y) * r;
235
57.9k
    fz_prepare_color(ctx, painter, &e1, &one);
236
237
57.9k
    paint_quad(ctx, painter, &e0, &v1, &v3, &e1);
238
57.9k
  }
239
57.9k
}
240
241
static void
242
fz_paint_annulus(fz_context *ctx, fz_matrix ctm,
243
    fz_point p0, float r0, float c0,
244
    fz_point p1, float r1, float c1,
245
    int count,
246
    fz_mesh_processor *painter)
247
56
{
248
56
  fz_vertex t0, t1, t2, t3, b0, b1, b2, b3;
249
56
  float theta, step, a, b;
250
56
  int i;
251
252
56
  theta = atan2f(p1.y - p0.y, p1.x - p0.x);
253
56
  step = FZ_PI / count;
254
255
56
  a = 0;
256
2.07k
  for (i = 1; i <= count; i++)
257
2.01k
  {
258
2.01k
    b = i * step;
259
260
2.01k
    t0.p = fz_transform_point(fz_point_on_circle(p0, r0, theta + a), ctm);
261
2.01k
    t1.p = fz_transform_point(fz_point_on_circle(p0, r0, theta + b), ctm);
262
2.01k
    t2.p = fz_transform_point(fz_point_on_circle(p1, r1, theta + a), ctm);
263
2.01k
    t3.p = fz_transform_point(fz_point_on_circle(p1, r1, theta + b), ctm);
264
2.01k
    b0.p = fz_transform_point(fz_point_on_circle(p0, r0, theta - a), ctm);
265
2.01k
    b1.p = fz_transform_point(fz_point_on_circle(p0, r0, theta - b), ctm);
266
2.01k
    b2.p = fz_transform_point(fz_point_on_circle(p1, r1, theta - a), ctm);
267
2.01k
    b3.p = fz_transform_point(fz_point_on_circle(p1, r1, theta - b), ctm);
268
269
2.01k
    fz_prepare_color(ctx, painter, &t0, &c0);
270
2.01k
    fz_prepare_color(ctx, painter, &t1, &c0);
271
2.01k
    fz_prepare_color(ctx, painter, &t2, &c1);
272
2.01k
    fz_prepare_color(ctx, painter, &t3, &c1);
273
2.01k
    fz_prepare_color(ctx, painter, &b0, &c0);
274
2.01k
    fz_prepare_color(ctx, painter, &b1, &c0);
275
2.01k
    fz_prepare_color(ctx, painter, &b2, &c1);
276
2.01k
    fz_prepare_color(ctx, painter, &b3, &c1);
277
278
2.01k
    paint_quad(ctx, painter, &t0, &t2, &t3, &t1);
279
2.01k
    paint_quad(ctx, painter, &b0, &b2, &b3, &b1);
280
281
2.01k
    a = b;
282
2.01k
  }
283
56
}
284
285
static void
286
fz_process_shade_type3(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
287
19
{
288
19
  fz_point p0, p1;
289
19
  float r0, r1;
290
19
  fz_point e;
291
19
  float er, rs;
292
19
  int count;
293
294
19
  p0.x = shade->u.l_or_r.coords[0][0];
295
19
  p0.y = shade->u.l_or_r.coords[0][1];
296
19
  r0 = shade->u.l_or_r.coords[0][2];
297
298
19
  p1.x = shade->u.l_or_r.coords[1][0];
299
19
  p1.y = shade->u.l_or_r.coords[1][1];
300
19
  r1 = shade->u.l_or_r.coords[1][2];
301
302
  /* number of segments for a half-circle */
303
19
  count = 4 * sqrtf(fz_matrix_expansion(ctm) * fz_max(r0, r1));
304
19
  if (count < 3)
305
1
    count = 3;
306
19
  if (count > 1024)
307
0
    count = 1024;
308
309
19
  if (shade->u.l_or_r.extend[0])
310
18
  {
311
18
    if (r0 < r1)
312
17
      rs = r0 / (r0 - r1);
313
1
    else
314
1
      rs = -HUGENUM;
315
316
18
    e.x = p0.x + (p1.x - p0.x) * rs;
317
18
    e.y = p0.y + (p1.y - p0.y) * rs;
318
18
    er = r0 + (r1 - r0) * rs;
319
320
18
    fz_paint_annulus(ctx, ctm, e, er, 0, p0, r0, 0, count, painter);
321
18
  }
322
323
19
  fz_paint_annulus(ctx, ctm, p0, r0, 0, p1, r1, 1, count, painter);
324
325
19
  if (shade->u.l_or_r.extend[1])
326
19
  {
327
19
    if (r0 > r1)
328
0
      rs = r1 / (r1 - r0);
329
19
    else
330
19
      rs = -HUGENUM;
331
332
19
    e.x = p1.x + (p0.x - p1.x) * rs;
333
19
    e.y = p1.y + (p0.y - p1.y) * rs;
334
19
    er = r1 + (r0 - r1) * rs;
335
336
19
    fz_paint_annulus(ctx, ctm, p1, r1, 1, e, er, 1, count, painter);
337
19
  }
338
19
}
339
340
static inline float read_sample(fz_context *ctx, fz_stream *stream, int bits, float min, float max)
341
2.50M
{
342
  /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */
343
2.50M
  float bitscale = 1 / (powf(2, bits) - 1);
344
2.50M
  return min + fz_read_bits(ctx, stream, bits) * (max - min) * bitscale;
345
2.50M
}
346
347
static void
348
fz_process_shade_type4(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
349
62
{
350
62
  fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
351
62
  fz_vertex v[4];
352
62
  fz_vertex *va = &v[0];
353
62
  fz_vertex *vb = &v[1];
354
62
  fz_vertex *vc = &v[2];
355
62
  fz_vertex *vd = &v[3];
356
62
  int flag, i, ncomp = painter->ncomp;
357
62
  int bpflag = shade->u.m.bpflag;
358
62
  int bpcoord = shade->u.m.bpcoord;
359
62
  int bpcomp = shade->u.m.bpcomp;
360
62
  float x0 = shade->u.m.x0;
361
62
  float x1 = shade->u.m.x1;
362
62
  float y0 = shade->u.m.y0;
363
62
  float y1 = shade->u.m.y1;
364
62
  const float *c0 = shade->u.m.c0;
365
62
  const float *c1 = shade->u.m.c1;
366
62
  float x, y, c[FZ_MAX_COLORS];
367
62
  int first_triangle = 1;
368
369
124
  fz_try(ctx)
370
124
  {
371
14.0k
    while (!fz_is_eof_bits(ctx, stream))
372
14.0k
    {
373
14.0k
      flag = fz_read_bits(ctx, stream, bpflag);
374
14.0k
      x = read_sample(ctx, stream, bpcoord, x0, x1);
375
14.0k
      y = read_sample(ctx, stream, bpcoord, y0, y1);
376
56.0k
      for (i = 0; i < ncomp; i++)
377
42.0k
        c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]);
378
14.0k
      fz_prepare_vertex(ctx, painter, vd, ctm, x, y, c);
379
380
14.0k
      if (first_triangle)
381
62
      {
382
62
        if (flag != 0)
383
5
        {
384
5
          fz_warn(ctx, "ignoring non-zero edge flags for first vertex in mesh");
385
5
          flag = 0;
386
5
        }
387
62
        first_triangle = 0;
388
62
      }
389
390
14.0k
      switch (flag)
391
14.0k
      {
392
12.5k
      default:
393
12.5k
        fz_warn(ctx, "ignoring out of range edge flag in mesh");
394
        /* fallthrough */
395
396
13.7k
      case 0: /* start new triangle */
397
13.7k
        SWAP(va, vd);
398
399
13.7k
        fz_read_bits(ctx, stream, bpflag);
400
13.7k
        x = read_sample(ctx, stream, bpcoord, x0, x1);
401
13.7k
        y = read_sample(ctx, stream, bpcoord, y0, y1);
402
54.9k
        for (i = 0; i < ncomp; i++)
403
41.2k
          c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]);
404
13.7k
        fz_prepare_vertex(ctx, painter, vb, ctm, x, y, c);
405
406
13.7k
        fz_read_bits(ctx, stream, bpflag);
407
13.7k
        x = read_sample(ctx, stream, bpcoord, x0, x1);
408
13.7k
        y = read_sample(ctx, stream, bpcoord, y0, y1);
409
54.9k
        for (i = 0; i < ncomp; i++)
410
41.2k
          c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]);
411
13.7k
        fz_prepare_vertex(ctx, painter, vc, ctm, x, y, c);
412
413
13.7k
        paint_tri(ctx, painter, va, vb, vc);
414
13.7k
        break;
415
416
93
      case 1: /* Vb, Vc, Vd */
417
93
        SWAP(va, vb);
418
93
        SWAP(vb, vc);
419
93
        SWAP(vc, vd);
420
93
        paint_tri(ctx, painter, va, vb, vc);
421
93
        break;
422
423
180
      case 2: /* Va, Vc, Vd */
424
180
        SWAP(vb, vc);
425
180
        SWAP(vc, vd);
426
180
        paint_tri(ctx, painter, va, vb, vc);
427
180
        break;
428
14.0k
      }
429
14.0k
    }
430
62
  }
431
124
  fz_always(ctx)
432
62
  {
433
62
    fz_drop_stream(ctx, stream);
434
62
  }
435
62
  fz_catch(ctx)
436
0
  {
437
0
    fz_rethrow(ctx);
438
0
  }
439
62
}
440
441
static void
442
fz_process_shade_type5(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
443
36
{
444
36
  fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
445
36
  fz_vertex *buf = NULL;
446
36
  fz_vertex *ref = NULL;
447
36
  int first;
448
36
  int ncomp = painter->ncomp;
449
36
  int i, k;
450
36
  int vprow = shade->u.m.vprow;
451
36
  int bpcoord = shade->u.m.bpcoord;
452
36
  int bpcomp = shade->u.m.bpcomp;
453
36
  float x0 = shade->u.m.x0;
454
36
  float x1 = shade->u.m.x1;
455
36
  float y0 = shade->u.m.y0;
456
36
  float y1 = shade->u.m.y1;
457
36
  const float *c0 = shade->u.m.c0;
458
36
  const float *c1 = shade->u.m.c1;
459
36
  float x, y, c[FZ_MAX_COLORS];
460
461
36
  fz_var(buf);
462
36
  fz_var(ref);
463
464
72
  fz_try(ctx)
465
72
  {
466
36
    ref = fz_malloc_array(ctx, vprow, fz_vertex);
467
36
    buf = fz_malloc_array(ctx, vprow, fz_vertex);
468
36
    first = 1;
469
470
16.9k
    while (!fz_is_eof_bits(ctx, stream))
471
16.9k
    {
472
184k
      for (i = 0; i < vprow; i++)
473
167k
      {
474
167k
        x = read_sample(ctx, stream, bpcoord, x0, x1);
475
167k
        y = read_sample(ctx, stream, bpcoord, y0, y1);
476
335k
        for (k = 0; k < ncomp; k++)
477
168k
          c[k] = read_sample(ctx, stream, bpcomp, c0[k], c1[k]);
478
167k
        fz_prepare_vertex(ctx, painter, &buf[i], ctm, x, y, c);
479
167k
      }
480
481
16.9k
      if (!first)
482
166k
        for (i = 0; i < vprow - 1; i++)
483
149k
          paint_quad(ctx, painter, &ref[i], &ref[i+1], &buf[i+1], &buf[i]);
484
485
16.9k
      SWAP(ref,buf);
486
16.9k
      first = 0;
487
16.9k
    }
488
36
  }
489
72
  fz_always(ctx)
490
36
  {
491
36
    fz_free(ctx, ref);
492
36
    fz_free(ctx, buf);
493
36
    fz_drop_stream(ctx, stream);
494
36
  }
495
36
  fz_catch(ctx)
496
0
  {
497
0
    fz_rethrow(ctx);
498
0
  }
499
36
}
500
501
/* Subdivide and tessellate tensor-patches */
502
503
typedef struct
504
{
505
  fz_point pole[4][4];
506
  float color[4][FZ_MAX_COLORS];
507
} tensor_patch;
508
509
static void
510
triangulate_patch(fz_context *ctx, fz_mesh_processor *painter, tensor_patch *p)
511
1.23M
{
512
1.23M
  fz_vertex v0, v1, v2, v3;
513
514
1.23M
  v0.p = p->pole[0][0];
515
1.23M
  v1.p = p->pole[0][3];
516
1.23M
  v2.p = p->pole[3][3];
517
1.23M
  v3.p = p->pole[3][0];
518
519
1.23M
  fz_prepare_color(ctx, painter, &v0, p->color[0]);
520
1.23M
  fz_prepare_color(ctx, painter, &v1, p->color[1]);
521
1.23M
  fz_prepare_color(ctx, painter, &v2, p->color[2]);
522
1.23M
  fz_prepare_color(ctx, painter, &v3, p->color[3]);
523
524
1.23M
  paint_quad(ctx, painter, &v0, &v1, &v2, &v3);
525
1.23M
}
526
527
static inline void midcolor(float *c, float *c1, float *c2, int n)
528
2.42M
{
529
2.42M
  int i;
530
10.4M
  for (i = 0; i < n; i++)
531
8.03M
    c[i] = (c1[i] + c2[i]) * 0.5f;
532
2.42M
}
533
534
static void
535
split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
536
4.84M
{
537
  /*
538
  split bezier curve given by control points pole[0]..pole[3]
539
  using de casteljau algo at midpoint and build two new
540
  bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
541
  should be multiplies by polestep == 1 for vertical bezier
542
  curves in patch and == 4 for horizontal bezier curves due
543
  to C's multi-dimensional matrix memory layout.
544
  */
545
546
4.84M
  float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
547
4.84M
  float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
548
549
4.84M
  q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
550
4.84M
  q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
551
4.84M
  q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
552
4.84M
  q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
553
554
4.84M
  q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
555
4.84M
  q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
556
4.84M
  q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
557
4.84M
  q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
558
559
4.84M
  q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
560
4.84M
  q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
561
4.84M
  q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
562
4.84M
  q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
563
564
4.84M
  q0[0 * polestep].x = pole[0 * polestep].x;
565
4.84M
  q0[0 * polestep].y = pole[0 * polestep].y;
566
4.84M
  q1[3 * polestep].x = pole[3 * polestep].x;
567
4.84M
  q1[3 * polestep].y = pole[3 * polestep].y;
568
4.84M
}
569
570
static void
571
split_stripe(tensor_patch *p, tensor_patch *s0, tensor_patch *s1, int n)
572
1.07M
{
573
  /*
574
  split all horizontal bezier curves in patch,
575
  creating two new patches with half the width.
576
  */
577
1.07M
  split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
578
1.07M
  split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
579
1.07M
  split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
580
1.07M
  split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
581
582
  /* interpolate the colors for the two new patches. */
583
1.07M
  memcpy(s0->color[0], p->color[0], n * sizeof(s0->color[0][0]));
584
1.07M
  memcpy(s0->color[1], p->color[1], n * sizeof(s0->color[1][0]));
585
1.07M
  midcolor(s0->color[2], p->color[1], p->color[2], n);
586
1.07M
  midcolor(s0->color[3], p->color[0], p->color[3], n);
587
588
1.07M
  memcpy(s1->color[0], s0->color[3], n * sizeof(s1->color[0][0]));
589
1.07M
  memcpy(s1->color[1], s0->color[2], n * sizeof(s1->color[1][0]));
590
1.07M
  memcpy(s1->color[2], p->color[2], n * sizeof(s1->color[2][0]));
591
1.07M
  memcpy(s1->color[3], p->color[3], n * sizeof(s1->color[3][0]));
592
1.07M
}
593
594
static void
595
draw_stripe(fz_context *ctx, fz_mesh_processor *painter, tensor_patch *p, int depth)
596
1.07M
{
597
1.07M
  tensor_patch s0, s1;
598
599
  /* split patch into two half-height patches */
600
1.07M
  split_stripe(p, &s0, &s1, painter->ncomp);
601
602
1.07M
  depth--;
603
1.07M
  if (depth == 0)
604
615k
  {
605
    /* if no more subdividing, draw two new patches... */
606
615k
    triangulate_patch(ctx, painter, &s1);
607
615k
    triangulate_patch(ctx, painter, &s0);
608
615k
  }
609
461k
  else
610
461k
  {
611
    /* ...otherwise, continue subdividing. */
612
461k
    draw_stripe(ctx, painter, &s1, depth);
613
461k
    draw_stripe(ctx, painter, &s0, depth);
614
461k
  }
615
1.07M
}
616
617
static void
618
split_patch(tensor_patch *p, tensor_patch *s0, tensor_patch *s1, int n)
619
134k
{
620
  /*
621
  split all vertical bezier curves in patch,
622
  creating two new patches with half the height.
623
  */
624
134k
  split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
625
134k
  split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
626
134k
  split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
627
134k
  split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
628
629
  /* interpolate the colors for the two new patches. */
630
134k
  memcpy(s0->color[0], p->color[0], n * sizeof(s0->color[0][0]));
631
134k
  midcolor(s0->color[1], p->color[0], p->color[1], n);
632
134k
  midcolor(s0->color[2], p->color[2], p->color[3], n);
633
134k
  memcpy(s0->color[3], p->color[3], n * sizeof(s0->color[3][0]));
634
635
134k
  memcpy(s1->color[0], s0->color[1], n * sizeof(s1->color[0][0]));
636
134k
  memcpy(s1->color[1], p->color[1], n * sizeof(s1->color[1][0]));
637
134k
  memcpy(s1->color[2], p->color[2], n * sizeof(s1->color[2][0]));
638
134k
  memcpy(s1->color[3], s0->color[2], n * sizeof(s1->color[3][0]));
639
134k
}
640
641
static void
642
draw_patch(fz_context *ctx, fz_mesh_processor *painter, tensor_patch *p, int depth, int origdepth)
643
134k
{
644
134k
  tensor_patch s0, s1;
645
646
  /* split patch into two half-width patches */
647
134k
  split_patch(p, &s0, &s1, painter->ncomp);
648
649
134k
  depth--;
650
134k
  if (depth == 0)
651
76.8k
  {
652
    /* if no more subdividing, draw two new patches... */
653
76.8k
    draw_stripe(ctx, painter, &s0, origdepth);
654
76.8k
    draw_stripe(ctx, painter, &s1, origdepth);
655
76.8k
  }
656
57.6k
  else
657
57.6k
  {
658
    /* ...otherwise, continue subdividing. */
659
57.6k
    draw_patch(ctx, painter, &s0, depth, origdepth);
660
57.6k
    draw_patch(ctx, painter, &s1, depth, origdepth);
661
57.6k
  }
662
134k
}
663
664
static fz_point
665
compute_tensor_interior(
666
  fz_point a, fz_point b, fz_point c, fz_point d,
667
  fz_point e, fz_point f, fz_point g, fz_point h)
668
16.7k
{
669
16.7k
  fz_point pt;
670
671
  /* see equations at page 330 in pdf 1.7 */
672
673
16.7k
  pt.x = -4 * a.x;
674
16.7k
  pt.x += 6 * (b.x + c.x);
675
16.7k
  pt.x += -2 * (d.x + e.x);
676
16.7k
  pt.x += 3 * (f.x + g.x);
677
16.7k
  pt.x += -1 * h.x;
678
16.7k
  pt.x /= 9;
679
680
16.7k
  pt.y = -4 * a.y;
681
16.7k
  pt.y += 6 * (b.y + c.y);
682
16.7k
  pt.y += -2 * (d.y + e.y);
683
16.7k
  pt.y += 3 * (f.y + g.y);
684
16.7k
  pt.y += -1 * h.y;
685
16.7k
  pt.y /= 9;
686
687
16.7k
  return pt;
688
16.7k
}
689
690
static void
691
make_tensor_patch(tensor_patch *p, int type, fz_point *pt)
692
19.2k
{
693
19.2k
  if (type == 6)
694
4.17k
  {
695
    /* see control point stream order at page 325 in pdf 1.7 */
696
697
4.17k
    p->pole[0][0] = pt[0];
698
4.17k
    p->pole[0][1] = pt[1];
699
4.17k
    p->pole[0][2] = pt[2];
700
4.17k
    p->pole[0][3] = pt[3];
701
4.17k
    p->pole[1][3] = pt[4];
702
4.17k
    p->pole[2][3] = pt[5];
703
4.17k
    p->pole[3][3] = pt[6];
704
4.17k
    p->pole[3][2] = pt[7];
705
4.17k
    p->pole[3][1] = pt[8];
706
4.17k
    p->pole[3][0] = pt[9];
707
4.17k
    p->pole[2][0] = pt[10];
708
4.17k
    p->pole[1][0] = pt[11];
709
710
    /* see equations at page 330 in pdf 1.7 */
711
712
4.17k
    p->pole[1][1] = compute_tensor_interior(
713
4.17k
      p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
714
4.17k
      p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
715
716
4.17k
    p->pole[1][2] = compute_tensor_interior(
717
4.17k
      p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
718
4.17k
      p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
719
720
4.17k
    p->pole[2][1] = compute_tensor_interior(
721
4.17k
      p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
722
4.17k
      p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
723
724
4.17k
    p->pole[2][2] = compute_tensor_interior(
725
4.17k
      p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
726
4.17k
      p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
727
4.17k
  }
728
15.0k
  else if (type == 7)
729
15.0k
  {
730
    /* see control point stream order at page 330 in pdf 1.7 */
731
732
15.0k
    p->pole[0][0] = pt[0];
733
15.0k
    p->pole[0][1] = pt[1];
734
15.0k
    p->pole[0][2] = pt[2];
735
15.0k
    p->pole[0][3] = pt[3];
736
15.0k
    p->pole[1][3] = pt[4];
737
15.0k
    p->pole[2][3] = pt[5];
738
15.0k
    p->pole[3][3] = pt[6];
739
15.0k
    p->pole[3][2] = pt[7];
740
15.0k
    p->pole[3][1] = pt[8];
741
15.0k
    p->pole[3][0] = pt[9];
742
15.0k
    p->pole[2][0] = pt[10];
743
15.0k
    p->pole[1][0] = pt[11];
744
15.0k
    p->pole[1][1] = pt[12];
745
15.0k
    p->pole[1][2] = pt[13];
746
15.0k
    p->pole[2][2] = pt[14];
747
15.0k
    p->pole[2][1] = pt[15];
748
15.0k
  }
749
19.2k
}
750
751
/* FIXME: Nasty */
752
38.4k
#define SUBDIV 3 /* how many levels to subdivide patches */
753
754
static void
755
fz_process_shade_type6(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
756
68
{
757
68
  fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
758
68
  float color_storage[2][4][FZ_MAX_COLORS];
759
68
  fz_point point_storage[2][12];
760
68
  int store = 0;
761
68
  int ncomp = painter->ncomp;
762
68
  int i, k;
763
68
  int bpflag = shade->u.m.bpflag;
764
68
  int bpcoord = shade->u.m.bpcoord;
765
68
  int bpcomp = shade->u.m.bpcomp;
766
68
  float x0 = shade->u.m.x0;
767
68
  float x1 = shade->u.m.x1;
768
68
  float y0 = shade->u.m.y0;
769
68
  float y1 = shade->u.m.y1;
770
68
  const float *c0 = shade->u.m.c0;
771
68
  const float *c1 = shade->u.m.c1;
772
773
136
  fz_try(ctx)
774
136
  {
775
68
    float (*prevc)[FZ_MAX_COLORS] = NULL;
776
68
    fz_point *prevp = NULL;
777
17.3k
    while (!fz_is_eof_bits(ctx, stream))
778
17.3k
    {
779
17.3k
      float (*c)[FZ_MAX_COLORS] = color_storage[store];
780
17.3k
      fz_point *v = point_storage[store];
781
17.3k
      int startcolor;
782
17.3k
      int startpt;
783
17.3k
      int flag;
784
17.3k
      tensor_patch patch;
785
786
17.3k
      flag = fz_read_bits(ctx, stream, bpflag);
787
788
17.3k
      if (flag == 0)
789
1.33k
      {
790
1.33k
        startpt = 0;
791
1.33k
        startcolor = 0;
792
1.33k
      }
793
15.9k
      else
794
15.9k
      {
795
15.9k
        startpt = 4;
796
15.9k
        startcolor = 2;
797
15.9k
      }
798
799
161k
      for (i = startpt; i < 12; i++)
800
143k
      {
801
143k
        v[i].x = read_sample(ctx, stream, bpcoord, x0, x1);
802
143k
        v[i].y = read_sample(ctx, stream, bpcoord, y0, y1);
803
143k
        v[i] = fz_transform_point(v[i], ctm);
804
143k
      }
805
806
54.6k
      for (i = startcolor; i < 4; i++)
807
37.3k
      {
808
149k
        for (k = 0; k < ncomp; k++)
809
111k
          c[i][k] = read_sample(ctx, stream, bpcomp, c0[k], c1[k]);
810
37.3k
      }
811
812
17.3k
      if (flag == 0)
813
1.33k
      {
814
        /* No patch data to copy forwards */
815
1.33k
      }
816
15.9k
      else if (flag == 1 && prevc)
817
511
      {
818
511
        v[0] = prevp[3];
819
511
        v[1] = prevp[4];
820
511
        v[2] = prevp[5];
821
511
        v[3] = prevp[6];
822
511
        memcpy(c[0], prevc[1], ncomp * sizeof(float));
823
511
        memcpy(c[1], prevc[2], ncomp * sizeof(float));
824
511
      }
825
15.4k
      else if (flag == 2 && prevc)
826
902
      {
827
902
        v[0] = prevp[6];
828
902
        v[1] = prevp[7];
829
902
        v[2] = prevp[8];
830
902
        v[3] = prevp[9];
831
902
        memcpy(c[0], prevc[2], ncomp * sizeof(float));
832
902
        memcpy(c[1], prevc[3], ncomp * sizeof(float));
833
902
      }
834
14.5k
      else if (flag == 3 && prevc)
835
1.42k
      {
836
1.42k
        v[0] = prevp[ 9];
837
1.42k
        v[1] = prevp[10];
838
1.42k
        v[2] = prevp[11];
839
1.42k
        v[3] = prevp[ 0];
840
1.42k
        memcpy(c[0], prevc[3], ncomp * sizeof(float));
841
1.42k
        memcpy(c[1], prevc[0], ncomp * sizeof(float));
842
1.42k
      }
843
13.1k
      else
844
13.1k
        continue;
845
846
4.17k
      make_tensor_patch(&patch, 6, v);
847
848
20.8k
      for (i = 0; i < 4; i++)
849
16.7k
        memcpy(patch.color[i], c[i], ncomp * sizeof(float));
850
851
4.17k
      draw_patch(ctx, painter, &patch, SUBDIV, SUBDIV);
852
853
4.17k
      prevp = v;
854
4.17k
      prevc = c;
855
4.17k
      store ^= 1;
856
4.17k
    }
857
68
  }
858
136
  fz_always(ctx)
859
68
  {
860
68
    fz_drop_stream(ctx, stream);
861
68
  }
862
68
  fz_catch(ctx)
863
0
  {
864
0
    fz_rethrow(ctx);
865
0
  }
866
68
}
867
868
static void
869
fz_process_shade_type7(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
870
247
{
871
247
  fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
872
247
  int bpflag = shade->u.m.bpflag;
873
247
  int bpcoord = shade->u.m.bpcoord;
874
247
  int bpcomp = shade->u.m.bpcomp;
875
247
  float x0 = shade->u.m.x0;
876
247
  float x1 = shade->u.m.x1;
877
247
  float y0 = shade->u.m.y0;
878
247
  float y1 = shade->u.m.y1;
879
247
  const float *c0 = shade->u.m.c0;
880
247
  const float *c1 = shade->u.m.c1;
881
247
  float color_storage[2][4][FZ_MAX_COLORS];
882
247
  fz_point point_storage[2][16];
883
247
  int store = 0;
884
247
  int ncomp = painter->ncomp;
885
247
  int i, k;
886
247
  float (*prevc)[FZ_MAX_COLORS] = NULL;
887
247
  fz_point (*prevp) = NULL;
888
889
494
  fz_try(ctx)
890
494
  {
891
40.2k
    while (!fz_is_eof_bits(ctx, stream))
892
39.9k
    {
893
39.9k
      float (*c)[FZ_MAX_COLORS] = color_storage[store];
894
39.9k
      fz_point *v = point_storage[store];
895
39.9k
      int startcolor;
896
39.9k
      int startpt;
897
39.9k
      int flag;
898
39.9k
      tensor_patch patch;
899
900
39.9k
      flag = fz_read_bits(ctx, stream, bpflag);
901
902
39.9k
      if (flag == 0)
903
12.1k
      {
904
12.1k
        startpt = 0;
905
12.1k
        startcolor = 0;
906
12.1k
      }
907
27.7k
      else
908
27.7k
      {
909
27.7k
        startpt = 4;
910
27.7k
        startcolor = 2;
911
27.7k
      }
912
913
568k
      for (i = startpt; i < 16; i++)
914
528k
      {
915
528k
        v[i].x = read_sample(ctx, stream, bpcoord, x0, x1);
916
528k
        v[i].y = read_sample(ctx, stream, bpcoord, y0, y1);
917
528k
        v[i] = fz_transform_point(v[i], ctm);
918
528k
      }
919
920
144k
      for (i = startcolor; i < 4; i++)
921
104k
      {
922
442k
        for (k = 0; k < ncomp; k++)
923
338k
          c[i][k] = read_sample(ctx, stream, bpcomp, c0[k], c1[k]);
924
104k
      }
925
926
39.9k
      if (flag == 0)
927
12.1k
      {
928
        /* No patch data to copy forward */
929
12.1k
      }
930
27.7k
      else if (flag == 1 && prevc)
931
921
      {
932
921
        v[0] = prevp[3];
933
921
        v[1] = prevp[4];
934
921
        v[2] = prevp[5];
935
921
        v[3] = prevp[6];
936
921
        memcpy(c[0], prevc[1], ncomp * sizeof(float));
937
921
        memcpy(c[1], prevc[2], ncomp * sizeof(float));
938
921
      }
939
26.8k
      else if (flag == 2 && prevc)
940
880
      {
941
880
        v[0] = prevp[6];
942
880
        v[1] = prevp[7];
943
880
        v[2] = prevp[8];
944
880
        v[3] = prevp[9];
945
880
        memcpy(c[0], prevc[2], ncomp * sizeof(float));
946
880
        memcpy(c[1], prevc[3], ncomp * sizeof(float));
947
880
      }
948
25.9k
      else if (flag == 3 && prevc)
949
1.07k
      {
950
1.07k
        v[0] = prevp[ 9];
951
1.07k
        v[1] = prevp[10];
952
1.07k
        v[2] = prevp[11];
953
1.07k
        v[3] = prevp[ 0];
954
1.07k
        memcpy(c[0], prevc[3], ncomp * sizeof(float));
955
1.07k
        memcpy(c[1], prevc[0], ncomp * sizeof(float));
956
1.07k
      }
957
24.9k
      else
958
24.9k
        continue; /* We have no patch! */
959
960
15.0k
      make_tensor_patch(&patch, 7, v);
961
962
75.2k
      for (i = 0; i < 4; i++)
963
60.1k
        memcpy(patch.color[i], c[i], ncomp * sizeof(float));
964
965
15.0k
      draw_patch(ctx, painter, &patch, SUBDIV, SUBDIV);
966
967
15.0k
      prevp = v;
968
15.0k
      prevc = c;
969
15.0k
      store ^= 1;
970
15.0k
    }
971
247
  }
972
494
  fz_always(ctx)
973
247
  {
974
247
    fz_drop_stream(ctx, stream);
975
247
  }
976
247
  fz_catch(ctx)
977
0
  {
978
0
    fz_rethrow(ctx);
979
0
  }
980
247
}
981
982
void
983
fz_process_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_rect scissor,
984
    fz_shade_prepare_fn *prepare, fz_shade_process_fn *process, void *process_arg)
985
58.3k
{
986
58.3k
  fz_mesh_processor painter;
987
988
58.3k
  painter.shade = shade;
989
58.3k
  painter.prepare = prepare;
990
58.3k
  painter.process = process;
991
58.3k
  painter.process_arg = process_arg;
992
58.3k
  painter.ncomp = (shade->use_function > 0 ? 1 : fz_colorspace_n(ctx, shade->colorspace));
993
994
58.3k
  if (shade->type == FZ_FUNCTION_BASED)
995
2
    fz_process_shade_type1(ctx, shade, ctm, &painter);
996
58.3k
  else if (shade->type == FZ_LINEAR)
997
57.9k
    fz_process_shade_type2(ctx, shade, ctm, &painter, scissor);
998
432
  else if (shade->type == FZ_RADIAL)
999
19
    fz_process_shade_type3(ctx, shade, ctm, &painter);
1000
413
  else if (shade->type == FZ_MESH_TYPE4)
1001
62
    fz_process_shade_type4(ctx, shade, ctm, &painter);
1002
351
  else if (shade->type == FZ_MESH_TYPE5)
1003
36
    fz_process_shade_type5(ctx, shade, ctm, &painter);
1004
315
  else if (shade->type == FZ_MESH_TYPE6)
1005
68
    fz_process_shade_type6(ctx, shade, ctm, &painter);
1006
247
  else if (shade->type == FZ_MESH_TYPE7)
1007
247
    fz_process_shade_type7(ctx, shade, ctm, &painter);
1008
0
  else
1009
0
    fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected mesh type %d\n", shade->type);
1010
58.3k
}
1011
1012
static fz_rect
1013
fz_bound_mesh_type1(fz_context *ctx, fz_shade *shade)
1014
4
{
1015
4
  fz_rect bbox;
1016
4
  bbox.x0 = shade->u.f.domain[0][0];
1017
4
  bbox.y0 = shade->u.f.domain[0][1];
1018
4
  bbox.x1 = shade->u.f.domain[1][0];
1019
4
  bbox.y1 = shade->u.f.domain[1][1];
1020
4
  return fz_transform_rect(bbox, shade->u.f.matrix);
1021
4
}
1022
1023
static fz_rect
1024
fz_bound_mesh_type2(fz_context *ctx, fz_shade *shade)
1025
0
{
1026
  /* FIXME: If axis aligned and not extended, the bbox may only be
1027
   * infinite in one direction */
1028
0
  return fz_infinite_rect;
1029
0
}
1030
1031
static fz_rect
1032
fz_bound_mesh_type3(fz_context *ctx, fz_shade *shade)
1033
0
{
1034
0
  fz_rect bbox;
1035
0
  fz_point p0, p1;
1036
0
  float r0, r1;
1037
1038
0
  r0 = shade->u.l_or_r.coords[0][2];
1039
0
  r1 = shade->u.l_or_r.coords[1][2];
1040
1041
0
  if (shade->u.l_or_r.extend[0])
1042
0
  {
1043
0
    if (r0 >= r1)
1044
0
      return fz_infinite_rect;
1045
0
  }
1046
1047
0
  if (shade->u.l_or_r.extend[1])
1048
0
  {
1049
0
    if (r0 <= r1)
1050
0
      return fz_infinite_rect;
1051
0
  }
1052
1053
0
  p0.x = shade->u.l_or_r.coords[0][0];
1054
0
  p0.y = shade->u.l_or_r.coords[0][1];
1055
0
  p1.x = shade->u.l_or_r.coords[1][0];
1056
0
  p1.y = shade->u.l_or_r.coords[1][1];
1057
1058
0
  bbox.x0 = p0.x - r0; bbox.y0 = p0.y - r0;
1059
0
  bbox.x1 = p0.x + r0; bbox.y1 = p0.x + r0;
1060
0
  if (bbox.x0 > p1.x - r1)
1061
0
    bbox.x0 = p1.x - r1;
1062
0
  if (bbox.x1 < p1.x + r1)
1063
0
    bbox.x1 = p1.x + r1;
1064
0
  if (bbox.y0 > p1.y - r1)
1065
0
    bbox.y0 = p1.y - r1;
1066
0
  if (bbox.y1 < p1.y + r1)
1067
0
    bbox.y1 = p1.y + r1;
1068
0
  return bbox;
1069
0
}
1070
1071
static fz_rect
1072
fz_bound_mesh_type4567(fz_context *ctx, fz_shade *shade)
1073
654
{
1074
654
  fz_rect bbox;
1075
654
  bbox.x0 = fz_min(shade->u.m.x0, shade->u.m.x1);
1076
654
  bbox.y0 = fz_min(shade->u.m.y0, shade->u.m.y1);
1077
654
  bbox.x1 = fz_max(shade->u.m.x0, shade->u.m.x1);
1078
654
  bbox.y1 = fz_max(shade->u.m.y0, shade->u.m.y1);
1079
654
  return bbox;
1080
654
}
1081
1082
static fz_rect
1083
fz_bound_mesh(fz_context *ctx, fz_shade *shade)
1084
658
{
1085
658
  if (shade->type == FZ_FUNCTION_BASED)
1086
4
    return fz_bound_mesh_type1(ctx, shade);
1087
654
  else if (shade->type == FZ_LINEAR)
1088
0
    return fz_bound_mesh_type2(ctx, shade);
1089
654
  else if (shade->type == FZ_RADIAL)
1090
0
    return fz_bound_mesh_type3(ctx, shade);
1091
654
  else if (shade->type == FZ_MESH_TYPE4 ||
1092
654
    shade->type == FZ_MESH_TYPE5 ||
1093
654
    shade->type == FZ_MESH_TYPE6 ||
1094
654
    shade->type == FZ_MESH_TYPE7)
1095
654
    return fz_bound_mesh_type4567(ctx, shade);
1096
0
  else
1097
0
    fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected mesh type %d\n", shade->type);
1098
658
}
1099
1100
fz_shade *
1101
fz_keep_shade(fz_context *ctx, fz_shade *shade)
1102
5.14k
{
1103
5.14k
  return fz_keep_storable(ctx, &shade->storable);
1104
5.14k
}
1105
1106
void
1107
fz_drop_shade_imp(fz_context *ctx, fz_storable *shade_)
1108
6.85k
{
1109
6.85k
  fz_shade *shade = (fz_shade *)shade_;
1110
1111
6.85k
  fz_drop_colorspace(ctx, shade->colorspace);
1112
6.85k
  if (shade->type == FZ_FUNCTION_BASED)
1113
2
    fz_free(ctx, shade->u.f.fn_vals);
1114
6.85k
  fz_drop_compressed_buffer(ctx, shade->buffer);
1115
6.85k
  fz_free(ctx, shade);
1116
6.85k
}
1117
1118
void
1119
fz_drop_shade(fz_context *ctx, fz_shade *shade)
1120
1.53M
{
1121
1.53M
  fz_drop_storable(ctx, &shade->storable);
1122
1.53M
}
1123
1124
fz_rect
1125
fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm)
1126
123k
{
1127
123k
  ctm = fz_concat(shade->matrix, ctm);
1128
123k
  if (shade->type != FZ_LINEAR && shade->type != FZ_RADIAL)
1129
658
  {
1130
658
    fz_rect rect = fz_bound_mesh(ctx, shade);
1131
658
    rect = fz_intersect_rect(rect, shade->bbox);
1132
658
    return fz_transform_rect(rect, ctm);
1133
658
  }
1134
122k
  return fz_transform_rect(shade->bbox, ctm);
1135
123k
}