Coverage Report

Created: 2025-11-07 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/pdf/pdf-shade.c
Line
Count
Source
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
#include "mupdf/pdf.h"
25
26
/* Sample various functions into lookup tables */
27
28
static void
29
pdf_sample_composite_shade_function(fz_context *ctx, float *shade, int n, pdf_function *func, float t0, float t1)
30
0
{
31
0
  int i;
32
0
  float t;
33
34
0
  for (i = 0; i < 256; i++)
35
0
  {
36
0
    t = t0 + (i / 255.0f) * (t1 - t0);
37
0
    pdf_eval_function(ctx, func, &t, 1, shade, n);
38
0
    shade += n;
39
0
    *shade++ = 1;
40
0
  }
41
0
}
42
43
static void
44
pdf_sample_component_shade_function(fz_context *ctx, float *shade, int funcs, pdf_function **func, float t0, float t1)
45
0
{
46
0
  int i, k;
47
0
  float t;
48
49
0
  for (i = 0; i < 256; i++)
50
0
  {
51
0
    t = t0 + (i / 255.0f) * (t1 - t0);
52
0
    for (k = 0; k < funcs; k++)
53
0
      pdf_eval_function(ctx, func[k], &t, 1, shade++, 1);
54
0
    *shade++ = 1;
55
0
  }
56
0
}
57
58
void
59
pdf_sample_shade_function(fz_context *ctx, float *samples, int n, int funcs, pdf_function **func, float t0, float t1)
60
0
{
61
0
  if (funcs == 1)
62
0
    pdf_sample_composite_shade_function(ctx, samples, n, func[0], t0, t1);
63
0
  else
64
0
    pdf_sample_component_shade_function(ctx, samples, funcs, func, t0, t1);
65
0
}
66
67
static void
68
make_sampled_shade_function(fz_context *ctx, fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
69
0
{
70
0
  int n = shade->colorspace->n;
71
0
  if (funcs != 1)
72
0
    n = funcs;
73
0
  shade->function_stride = n + 1;
74
0
  shade->function = Memento_label(fz_malloc(ctx, sizeof(float) * 256 * shade->function_stride), "shade samples");
75
76
0
  pdf_sample_shade_function(ctx, shade->function, n, funcs, func, t0, t1);
77
0
}
78
79
/* Type 1-3 -- Function-based, linear and radial shadings */
80
81
0
#define FUNSEGS 256 /* size of sampled mesh for function-based shadings */
82
83
static void
84
pdf_load_function_based_shading(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
85
0
{
86
0
  pdf_obj *obj;
87
0
  float x0, y0, x1, y1;
88
0
  float fv[2];
89
0
  int xx, yy, zz;
90
0
  int xdivs, ydivs;
91
0
  float *p;
92
0
  int n = fz_colorspace_n(ctx, shade->colorspace);
93
94
0
  x0 = y0 = 0;
95
0
  x1 = y1 = 1;
96
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Domain));
97
0
  if (obj)
98
0
  {
99
0
    x0 = pdf_array_get_real(ctx, obj, 0);
100
0
    x1 = pdf_array_get_real(ctx, obj, 1);
101
0
    y0 = pdf_array_get_real(ctx, obj, 2);
102
0
    y1 = pdf_array_get_real(ctx, obj, 3);
103
0
  }
104
105
0
  xdivs = FUNSEGS;
106
0
  ydivs = FUNSEGS;
107
108
0
  shade->u.f.matrix = pdf_dict_get_matrix(ctx, dict, PDF_NAME(Matrix));
109
0
  shade->u.f.xdivs = xdivs;
110
0
  shade->u.f.ydivs = ydivs;
111
0
  shade->u.f.fn_vals = Memento_label(fz_malloc(ctx, (xdivs+1)*(ydivs+1)*n*sizeof(float)), "shade_fn_vals");
112
0
  shade->u.f.domain[0][0] = x0;
113
0
  shade->u.f.domain[0][1] = y0;
114
0
  shade->u.f.domain[1][0] = x1;
115
0
  shade->u.f.domain[1][1] = y1;
116
117
0
  p = shade->u.f.fn_vals;
118
0
  if (funcs == 1)
119
0
  {
120
0
    for (yy = 0; yy <= ydivs; yy++)
121
0
    {
122
0
      fv[1] = y0 + (y1 - y0) * yy / ydivs;
123
124
0
      for (xx = 0; xx <= xdivs; xx++)
125
0
      {
126
0
        fv[0] = x0 + (x1 - x0) * xx / xdivs;
127
128
0
        pdf_eval_function(ctx, func[0], fv, 2, p, n);
129
0
        p += n;
130
0
      }
131
0
    }
132
0
  }
133
0
  else
134
0
  {
135
0
    if (funcs != n)
136
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "Expected 1 2in, n-out function, or n 2 in, 1-out functions");
137
138
0
    for (yy = 0; yy <= ydivs; yy++)
139
0
    {
140
0
      fv[1] = y0 + (y1 - y0) * yy / ydivs;
141
142
0
      for (xx = 0; xx <= xdivs; xx++)
143
0
      {
144
0
        fv[0] = x0 + (x1 - x0) * xx / xdivs;
145
146
0
        for (zz = 0; zz < n; zz++)
147
0
        {
148
0
          pdf_eval_function(ctx, func[zz], fv, 2, p, 1);
149
0
          p ++;
150
0
        }
151
0
      }
152
0
    }
153
0
  }
154
0
}
155
156
static void
157
pdf_load_linear_shading(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
158
0
{
159
0
  pdf_obj *obj;
160
0
  float d0, d1;
161
0
  int e0, e1;
162
163
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Coords));
164
0
  shade->u.l_or_r.coords[0][0] = pdf_array_get_real(ctx, obj, 0);
165
0
  shade->u.l_or_r.coords[0][1] = pdf_array_get_real(ctx, obj, 1);
166
0
  shade->u.l_or_r.coords[1][0] = pdf_array_get_real(ctx, obj, 2);
167
0
  shade->u.l_or_r.coords[1][1] = pdf_array_get_real(ctx, obj, 3);
168
169
0
  d0 = 0;
170
0
  d1 = 1;
171
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Domain));
172
0
  if (obj)
173
0
  {
174
0
    d0 = pdf_array_get_real(ctx, obj, 0);
175
0
    d1 = pdf_array_get_real(ctx, obj, 1);
176
0
  }
177
178
0
  e0 = e1 = 0;
179
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Extend));
180
0
  if (obj)
181
0
  {
182
0
    e0 = pdf_array_get_bool(ctx, obj, 0);
183
0
    e1 = pdf_array_get_bool(ctx, obj, 1);
184
0
  }
185
186
0
  make_sampled_shade_function(ctx, shade, funcs, func, d0, d1);
187
188
0
  shade->u.l_or_r.extend[0] = e0;
189
0
  shade->u.l_or_r.extend[1] = e1;
190
0
}
191
192
static void
193
pdf_load_radial_shading(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
194
0
{
195
0
  pdf_obj *obj;
196
0
  float d0, d1;
197
0
  int e0, e1;
198
199
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Coords));
200
0
  shade->u.l_or_r.coords[0][0] = pdf_array_get_real(ctx, obj, 0);
201
0
  shade->u.l_or_r.coords[0][1] = pdf_array_get_real(ctx, obj, 1);
202
0
  shade->u.l_or_r.coords[0][2] = pdf_array_get_real(ctx, obj, 2);
203
0
  shade->u.l_or_r.coords[1][0] = pdf_array_get_real(ctx, obj, 3);
204
0
  shade->u.l_or_r.coords[1][1] = pdf_array_get_real(ctx, obj, 4);
205
0
  shade->u.l_or_r.coords[1][2] = pdf_array_get_real(ctx, obj, 5);
206
207
0
  d0 = 0;
208
0
  d1 = 1;
209
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Domain));
210
0
  if (obj)
211
0
  {
212
0
    d0 = pdf_array_get_real(ctx, obj, 0);
213
0
    d1 = pdf_array_get_real(ctx, obj, 1);
214
0
  }
215
216
0
  e0 = e1 = 0;
217
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Extend));
218
0
  if (obj)
219
0
  {
220
0
    e0 = pdf_array_get_bool(ctx, obj, 0);
221
0
    e1 = pdf_array_get_bool(ctx, obj, 1);
222
0
  }
223
224
0
  make_sampled_shade_function(ctx, shade, funcs, func, d0, d1);
225
226
0
  shade->u.l_or_r.extend[0] = e0;
227
0
  shade->u.l_or_r.extend[1] = e1;
228
0
}
229
230
/* Type 4-7 -- Triangle and patch mesh shadings */
231
232
struct mesh_params
233
{
234
  int vprow;
235
  int bpflag;
236
  int bpcoord;
237
  int bpcomp;
238
  float x0, x1;
239
  float y0, y1;
240
  float c0[FZ_MAX_COLORS];
241
  float c1[FZ_MAX_COLORS];
242
};
243
244
static void
245
pdf_load_mesh_params(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict)
246
0
{
247
0
  pdf_obj *obj;
248
0
  int i, n;
249
250
0
  shade->u.m.x0 = shade->u.m.y0 = 0;
251
0
  shade->u.m.x1 = shade->u.m.y1 = 1;
252
0
  for (i = 0; i < FZ_MAX_COLORS; i++)
253
0
  {
254
0
    shade->u.m.c0[i] = 0;
255
0
    shade->u.m.c1[i] = 1;
256
0
  }
257
258
0
  shade->u.m.vprow = pdf_dict_get_int(ctx, dict, PDF_NAME(VerticesPerRow));
259
0
  shade->u.m.bpflag = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerFlag));
260
0
  shade->u.m.bpcoord = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerCoordinate));
261
0
  shade->u.m.bpcomp = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerComponent));
262
263
0
  obj = pdf_dict_get(ctx, dict, PDF_NAME(Decode));
264
0
  if (pdf_array_len(ctx, obj) >= 6)
265
0
  {
266
0
    n = fz_mini(FZ_MAX_COLORS, (pdf_array_len(ctx, obj) - 4) / 2);
267
0
    shade->u.m.x0 = pdf_array_get_real(ctx, obj, 0);
268
0
    shade->u.m.x1 = pdf_array_get_real(ctx, obj, 1);
269
0
    shade->u.m.y0 = pdf_array_get_real(ctx, obj, 2);
270
0
    shade->u.m.y1 = pdf_array_get_real(ctx, obj, 3);
271
0
    for (i = 0; i < n; i++)
272
0
    {
273
0
      shade->u.m.c0[i] = pdf_array_get_real(ctx, obj, 4 + i * 2);
274
0
      shade->u.m.c1[i] = pdf_array_get_real(ctx, obj, 5 + i * 2);
275
0
    }
276
0
  }
277
278
0
  if (shade->u.m.vprow < 2 && shade->type == 5)
279
0
  {
280
0
    fz_warn(ctx, "Too few vertices per row (%d)", shade->u.m.vprow);
281
0
    shade->u.m.vprow = 2;
282
0
  }
283
284
0
  if (shade->u.m.bpflag != 2 && shade->u.m.bpflag != 4 && shade->u.m.bpflag != 8 &&
285
0
    shade->type != 5)
286
0
  {
287
0
    fz_warn(ctx, "Invalid number of bits per flag (%d)", shade->u.m.bpflag);
288
0
    shade->u.m.bpflag = 8;
289
0
  }
290
291
0
  if (shade->u.m.bpcoord != 1 && shade->u.m.bpcoord != 2 && shade->u.m.bpcoord != 4 &&
292
0
    shade->u.m.bpcoord != 8 && shade->u.m.bpcoord != 12 && shade->u.m.bpcoord != 16 &&
293
0
    shade->u.m.bpcoord != 24 && shade->u.m.bpcoord != 32)
294
0
  {
295
0
    fz_warn(ctx, "Invalid number of bits per coordinate (%d)", shade->u.m.bpcoord);
296
0
    shade->u.m.bpcoord = 8;
297
0
  }
298
299
0
  if (shade->u.m.bpcomp != 1 && shade->u.m.bpcomp != 2 && shade->u.m.bpcomp != 4 &&
300
0
    shade->u.m.bpcomp != 8 && shade->u.m.bpcomp != 12 && shade->u.m.bpcomp != 16)
301
0
  {
302
0
    fz_warn(ctx, "Invalid number of bits per component (%d)", shade->u.m.bpcomp);
303
0
    shade->u.m.bpcomp = 8;
304
0
  }
305
0
}
306
307
static void
308
pdf_load_type4_shade(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
309
0
{
310
0
  pdf_load_mesh_params(ctx, doc, shade, dict);
311
312
0
  if (funcs > 0)
313
0
    make_sampled_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
314
315
0
  shade->buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict), 0);
316
0
}
317
318
static void
319
pdf_load_type5_shade(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
320
0
{
321
0
  pdf_load_mesh_params(ctx, doc, shade, dict);
322
323
0
  if (funcs > 0)
324
0
    make_sampled_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
325
326
0
  shade->buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict), 0);
327
0
}
328
329
/* Type 6 & 7 -- Patch mesh shadings */
330
331
static void
332
pdf_load_type6_shade(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
333
0
{
334
0
  pdf_load_mesh_params(ctx, doc, shade, dict);
335
336
0
  if (funcs > 0)
337
0
    make_sampled_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
338
339
0
  shade->buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict), 0);
340
0
}
341
342
static void
343
pdf_load_type7_shade(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict, int funcs, pdf_function **func)
344
0
{
345
0
  pdf_load_mesh_params(ctx, doc, shade, dict);
346
347
0
  if (funcs > 0)
348
0
    make_sampled_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
349
350
0
  shade->buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict), 0);
351
0
}
352
353
/* Load all of the shading dictionary parameters, then switch on the shading type. */
354
355
static fz_shade *
356
pdf_load_shading_dict(fz_context *ctx, pdf_document *doc, pdf_obj *dict, fz_matrix transform)
357
0
{
358
0
  fz_shade *shade = NULL;
359
0
  pdf_function *func[FZ_MAX_COLORS] = { NULL };
360
0
  pdf_obj *obj;
361
0
  int funcs = 0;
362
0
  int type = 0;
363
0
  int i, in, out, n;
364
365
0
  fz_var(shade);
366
0
  fz_var(func);
367
0
  fz_var(funcs);
368
0
  fz_var(type);
369
370
0
  fz_try(ctx)
371
0
  {
372
0
    shade = fz_malloc_struct(ctx, fz_shade);
373
0
    FZ_INIT_STORABLE(shade, 1, fz_drop_shade_imp);
374
0
    shade->type = FZ_MESH_TYPE4;
375
0
    shade->use_background = 0;
376
0
    shade->function_stride = 0;
377
0
    shade->matrix = transform;
378
0
    shade->bbox = fz_infinite_rect;
379
380
0
    shade->colorspace = NULL;
381
382
0
    funcs = 0;
383
384
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(ShadingType));
385
0
    type = pdf_to_int(ctx, obj);
386
387
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(ColorSpace));
388
0
    if (!obj)
389
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "shading colorspace is missing");
390
0
    shade->colorspace = pdf_load_colorspace(ctx, obj);
391
0
    n = fz_colorspace_n(ctx, shade->colorspace);
392
393
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(Background));
394
0
    if (obj)
395
0
    {
396
0
      shade->use_background = 1;
397
0
      for (i = 0; i < n; i++)
398
0
        shade->background[i] = pdf_array_get_real(ctx, obj, i);
399
0
    }
400
401
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(BBox));
402
0
    if (pdf_is_array(ctx, obj))
403
0
      shade->bbox = pdf_to_rect(ctx, obj);
404
405
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(Function));
406
0
    if (pdf_is_dict(ctx, obj))
407
0
    {
408
0
      funcs = 1;
409
410
0
      if (type == 1)
411
0
        in = 2;
412
0
      else
413
0
        in = 1;
414
0
      out = n;
415
416
0
      func[0] = pdf_load_function(ctx, obj, in, out);
417
0
      if (!func[0])
418
0
        fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj));
419
0
    }
420
0
    else if (pdf_is_array(ctx, obj))
421
0
    {
422
0
      funcs = pdf_array_len(ctx, obj);
423
0
      if (funcs != 1 && funcs != n)
424
0
      {
425
0
        funcs = 0;
426
0
        fz_throw(ctx, FZ_ERROR_SYNTAX, "incorrect number of shading functions");
427
0
      }
428
0
      if (funcs > FZ_MAX_COLORS)
429
0
      {
430
0
        funcs = 0;
431
0
        fz_throw(ctx, FZ_ERROR_SYNTAX, "too many shading functions");
432
0
      }
433
434
0
      if (type == 1)
435
0
        in = 2;
436
0
      else
437
0
        in = 1;
438
0
      out = 1;
439
440
0
      for (i = 0; i < funcs; i++)
441
0
      {
442
0
        func[i] = pdf_load_function(ctx, pdf_array_get(ctx, obj, i), in, out);
443
0
        if (!func[i])
444
0
          fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj));
445
0
      }
446
0
    }
447
0
    else if (type < 4)
448
0
    {
449
      /* Functions are compulsory for types 1,2,3 */
450
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot load shading function (%d 0 R)", pdf_to_num(ctx, obj));
451
0
    }
452
453
0
    shade->type = type;
454
0
    switch (type)
455
0
    {
456
0
    case 1: pdf_load_function_based_shading(ctx, doc, shade, dict, funcs, func); break;
457
0
    case 2: pdf_load_linear_shading(ctx, doc, shade, dict, funcs, func); break;
458
0
    case 3: pdf_load_radial_shading(ctx, doc, shade, dict, funcs, func); break;
459
0
    case 4: pdf_load_type4_shade(ctx, doc, shade, dict, funcs, func); break;
460
0
    case 5: pdf_load_type5_shade(ctx, doc, shade, dict, funcs, func); break;
461
0
    case 6: pdf_load_type6_shade(ctx, doc, shade, dict, funcs, func); break;
462
0
    case 7: pdf_load_type7_shade(ctx, doc, shade, dict, funcs, func); break;
463
0
    default:
464
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown shading type: %d", type);
465
0
    }
466
0
  }
467
0
  fz_always(ctx)
468
0
  {
469
0
    for (i = 0; i < funcs; i++)
470
0
      pdf_drop_function(ctx, func[i]);
471
0
  }
472
0
  fz_catch(ctx)
473
0
  {
474
0
    fz_drop_shade(ctx, shade);
475
0
    fz_rethrow(ctx);
476
0
  }
477
0
  return shade;
478
0
}
479
480
static size_t
481
fz_shade_size(fz_context *ctx, fz_shade *s)
482
0
{
483
0
  size_t f = 0;
484
0
  if (s == NULL)
485
0
    return 0;
486
0
  if (s->function_stride)
487
0
    f = sizeof(float) * s->function_stride * 256;
488
0
  if (s->type == FZ_FUNCTION_BASED)
489
0
    return sizeof(*s) + sizeof(float) * s->u.f.xdivs * s->u.f.ydivs * fz_colorspace_n(ctx, s->colorspace) + f;
490
0
  return sizeof(*s) + fz_compressed_buffer_size(s->buffer) + f;
491
0
}
492
493
fz_shade *
494
pdf_load_shading(fz_context *ctx, pdf_document *doc, pdf_obj *dict)
495
0
{
496
0
  fz_matrix mat;
497
0
  pdf_obj *obj;
498
0
  fz_shade *shade;
499
500
0
  if ((shade = pdf_find_item(ctx, fz_drop_shade_imp, dict)) != NULL)
501
0
  {
502
0
    return shade;
503
0
  }
504
505
  /* Type 2 pattern dictionary */
506
0
  if (pdf_dict_get(ctx, dict, PDF_NAME(PatternType)))
507
0
  {
508
0
    mat = pdf_dict_get_matrix(ctx, dict, PDF_NAME(Matrix));
509
510
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(ExtGState));
511
0
    if (obj)
512
0
    {
513
0
      if (pdf_dict_get(ctx, obj, PDF_NAME(CA)) || pdf_dict_get(ctx, obj, PDF_NAME(ca)))
514
0
      {
515
0
        fz_warn(ctx, "shading with alpha not supported");
516
0
      }
517
0
    }
518
519
0
    obj = pdf_dict_get(ctx, dict, PDF_NAME(Shading));
520
0
    if (!obj)
521
0
      fz_throw(ctx, FZ_ERROR_SYNTAX, "missing shading dictionary");
522
523
0
    shade = pdf_load_shading_dict(ctx, doc, obj, mat);
524
0
  }
525
526
  /* Naked shading dictionary */
527
0
  else
528
0
  {
529
0
    shade = pdf_load_shading_dict(ctx, doc, dict, fz_identity);
530
0
  }
531
532
0
  pdf_store_item(ctx, dict, shade, fz_shade_size(ctx, shade));
533
534
0
  return shade;
535
0
}