Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "mupdf.h"
  3.  
  4. #define HUGENUM 32000 /* how far to extend axial/radial shadings */
  5. #define FUNSEGS 32 /* size of sampled mesh for function-based shadings */
  6. #define RADSEGS 32 /* how many segments to generate for radial meshes */
  7. #define SUBDIV 3 /* how many levels to subdivide patches */
  8.  
  9. struct vertex
  10. {
  11.         float x, y;
  12.         float c[FZ_MAX_COLORS];
  13. };
  14.  
  15. static void
  16. pdf_grow_mesh(fz_shade *shade, int amount)
  17. {
  18.         if (shade->mesh_len + amount < shade->mesh_cap)
  19.                 return;
  20.  
  21.         if (shade->mesh_cap == 0)
  22.                 shade->mesh_cap = 1024;
  23.  
  24.         while (shade->mesh_len + amount > shade->mesh_cap)
  25.                 shade->mesh_cap = (shade->mesh_cap * 3) / 2;
  26.  
  27.         shade->mesh = fz_realloc(shade->mesh, shade->mesh_cap, sizeof(float));
  28. }
  29.  
  30. static void
  31. pdf_add_vertex(fz_shade *shade, struct vertex *v)
  32. {
  33.         int ncomp = shade->use_function ? 1 : shade->colorspace->n;
  34.         int i;
  35.         pdf_grow_mesh(shade, 2 + ncomp);
  36.         shade->mesh[shade->mesh_len++] = v->x;
  37.         shade->mesh[shade->mesh_len++] = v->y;
  38.         for (i = 0; i < ncomp; i++)
  39.                 shade->mesh[shade->mesh_len++] = v->c[i];
  40. }
  41.  
  42. static void
  43. pdf_add_triangle(fz_shade *shade,
  44.         struct vertex *v0,
  45.         struct vertex *v1,
  46.         struct vertex *v2)
  47. {
  48.         pdf_add_vertex(shade, v0);
  49.         pdf_add_vertex(shade, v1);
  50.         pdf_add_vertex(shade, v2);
  51. }
  52.  
  53. static void
  54. pdf_add_quad(fz_shade *shade,
  55.         struct vertex *v0,
  56.         struct vertex *v1,
  57.         struct vertex *v2,
  58.         struct vertex *v3)
  59. {
  60.         pdf_add_triangle(shade, v0, v1, v3);
  61.         pdf_add_triangle(shade, v1, v3, v2);
  62. }
  63.  
  64. /* Subdivide and tesselate tensor-patches */
  65.  
  66. typedef struct pdf_tensor_patch_s pdf_tensor_patch;
  67.  
  68. struct pdf_tensor_patch_s
  69. {
  70.         fz_point pole[4][4];
  71.         float color[4][FZ_MAX_COLORS];
  72. };
  73.  
  74. static void
  75. triangulate_patch(pdf_tensor_patch p, fz_shade *shade)
  76. {
  77.         struct vertex v0, v1, v2, v3;
  78.  
  79.         v0.x = p.pole[0][0].x;
  80.         v0.y = p.pole[0][0].y;
  81.         memcpy(v0.c, p.color[0], sizeof(v0.c));
  82.  
  83.         v1.x = p.pole[0][3].x;
  84.         v1.y = p.pole[0][3].y;
  85.         memcpy(v1.c, p.color[1], sizeof(v1.c));
  86.  
  87.         v2.x = p.pole[3][3].x;
  88.         v2.y = p.pole[3][3].y;
  89.         memcpy(v2.c, p.color[2], sizeof(v2.c));
  90.  
  91.         v3.x = p.pole[3][0].x;
  92.         v3.y = p.pole[3][0].y;
  93.         memcpy(v3.c, p.color[3], sizeof(v3.c));
  94.  
  95.         pdf_add_quad(shade, &v0, &v1, &v2, &v3);
  96. }
  97.  
  98. static inline void midcolor(float *c, float *c1, float *c2)
  99. {
  100.         int i;
  101.         for (i = 0; i < FZ_MAX_COLORS; i++)
  102.                 c[i] = (c1[i] + c2[i]) * 0.5f;
  103. }
  104.  
  105. static void
  106. split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
  107. {
  108.         /*
  109.         split bezier curve given by control points pole[0]..pole[3]
  110.         using de casteljau algo at midpoint and build two new
  111.         bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
  112.         should be multiplies by polestep == 1 for vertical bezier
  113.         curves in patch and == 4 for horizontal bezier curves due
  114.         to C's multi-dimensional matrix memory layout.
  115.         */
  116.  
  117.         float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
  118.         float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
  119.  
  120.         q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
  121.         q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
  122.         q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
  123.         q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
  124.  
  125.         q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
  126.         q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
  127.         q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
  128.         q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
  129.  
  130.         q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
  131.         q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
  132.         q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
  133.         q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
  134.  
  135.         q0[0 * polestep].x = pole[0 * polestep].x;
  136.         q0[0 * polestep].y = pole[0 * polestep].y;
  137.         q1[3 * polestep].x = pole[3 * polestep].x;
  138.         q1[3 * polestep].y = pole[3 * polestep].y;
  139. }
  140.  
  141. static void
  142. split_stripe(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
  143. {
  144.         /*
  145.         split all horizontal bezier curves in patch,
  146.         creating two new patches with half the width.
  147.         */
  148.         split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
  149.         split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
  150.         split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
  151.         split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
  152.  
  153.         /* interpolate the colors for the two new patches. */
  154.         memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
  155.         memcpy(s0->color[1], p->color[1], sizeof(s0->color[1]));
  156.         midcolor(s0->color[2], p->color[1], p->color[2]);
  157.         midcolor(s0->color[3], p->color[0], p->color[3]);
  158.  
  159.         memcpy(s1->color[0], s0->color[3], sizeof(s1->color[0]));
  160.         memcpy(s1->color[1], s0->color[2], sizeof(s1->color[1]));
  161.         memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
  162.         memcpy(s1->color[3], p->color[3], sizeof(s1->color[3]));
  163. }
  164.  
  165. static void
  166. draw_stripe(pdf_tensor_patch *p, fz_shade *shade, int depth)
  167. {
  168.         pdf_tensor_patch s0, s1;
  169.  
  170.         /* split patch into two half-height patches */
  171.         split_stripe(p, &s0, &s1);
  172.  
  173.         depth--;
  174.         if (depth == 0)
  175.         {
  176.                 /* if no more subdividing, draw two new patches... */
  177.                 triangulate_patch(s0, shade);
  178.                 triangulate_patch(s1, shade);
  179.         }
  180.         else
  181.         {
  182.                 /* ...otherwise, continue subdividing. */
  183.                 draw_stripe(&s0, shade, depth);
  184.                 draw_stripe(&s1, shade, depth);
  185.         }
  186. }
  187.  
  188. static void
  189. split_patch(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
  190. {
  191.         /*
  192.         split all vertical bezier curves in patch,
  193.         creating two new patches with half the height.
  194.         */
  195.         split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
  196.         split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
  197.         split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
  198.         split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
  199.  
  200.         /* interpolate the colors for the two new patches. */
  201.         memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
  202.         midcolor(s0->color[1], p->color[0], p->color[1]);
  203.         midcolor(s0->color[2], p->color[2], p->color[3]);
  204.         memcpy(s0->color[3], p->color[3], sizeof(s0->color[3]));
  205.  
  206.         memcpy(s1->color[0], s0->color[1], sizeof(s1->color[0]));
  207.         memcpy(s1->color[1], p->color[1], sizeof(s1->color[1]));
  208.         memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
  209.         memcpy(s1->color[3], s0->color[2], sizeof(s1->color[3]));
  210. }
  211.  
  212. static void
  213. draw_patch(fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth)
  214. {
  215.         pdf_tensor_patch s0, s1;
  216.  
  217.         /* split patch into two half-width patches */
  218.         split_patch(p, &s0, &s1);
  219.  
  220.         depth--;
  221.         if (depth == 0)
  222.         {
  223.                 /* if no more subdividing, draw two new patches... */
  224.                 draw_stripe(&s0, shade, origdepth);
  225.                 draw_stripe(&s1, shade, origdepth);
  226.         }
  227.         else
  228.         {
  229.                 /* ...otherwise, continue subdividing. */
  230.                 draw_patch(shade, &s0, depth, origdepth);
  231.                 draw_patch(shade, &s1, depth, origdepth);
  232.         }
  233. }
  234.  
  235. static fz_point
  236. pdf_compute_tensor_interior(
  237.         fz_point a, fz_point b, fz_point c, fz_point d,
  238.         fz_point e, fz_point f, fz_point g, fz_point h)
  239. {
  240.         fz_point pt;
  241.  
  242.         /* see equations at page 330 in pdf 1.7 */
  243.  
  244.         pt.x = -4 * a.x;
  245.         pt.x += 6 * (b.x + c.x);
  246.         pt.x += -2 * (d.x + e.x);
  247.         pt.x += 3 * (f.x + g.x);
  248.         pt.x += -1 * h.x;
  249.         pt.x /= 9;
  250.  
  251.         pt.y = -4 * a.y;
  252.         pt.y += 6 * (b.y + c.y);
  253.         pt.y += -2 * (d.y + e.y);
  254.         pt.y += 3 * (f.y + g.y);
  255.         pt.y += -1 * h.y;
  256.         pt.y /= 9;
  257.  
  258.         return pt;
  259. }
  260.  
  261. static void
  262. pdf_make_tensor_patch(pdf_tensor_patch *p, int type, fz_point *pt)
  263. {
  264.         if (type == 6)
  265.         {
  266.                 /* see control point stream order at page 325 in pdf 1.7 */
  267.  
  268.                 p->pole[0][0] = pt[0];
  269.                 p->pole[0][1] = pt[1];
  270.                 p->pole[0][2] = pt[2];
  271.                 p->pole[0][3] = pt[3];
  272.                 p->pole[1][3] = pt[4];
  273.                 p->pole[2][3] = pt[5];
  274.                 p->pole[3][3] = pt[6];
  275.                 p->pole[3][2] = pt[7];
  276.                 p->pole[3][1] = pt[8];
  277.                 p->pole[3][0] = pt[9];
  278.                 p->pole[2][0] = pt[10];
  279.                 p->pole[1][0] = pt[11];
  280.  
  281.                 /* see equations at page 330 in pdf 1.7 */
  282.  
  283.                 p->pole[1][1] = pdf_compute_tensor_interior(
  284.                         p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
  285.                         p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
  286.  
  287.                 p->pole[1][2] = pdf_compute_tensor_interior(
  288.                         p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
  289.                         p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
  290.  
  291.                 p->pole[2][1] = pdf_compute_tensor_interior(
  292.                         p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
  293.                         p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
  294.  
  295.                 p->pole[2][2] = pdf_compute_tensor_interior(
  296.                         p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
  297.                         p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
  298.         }
  299.         else if (type == 7)
  300.         {
  301.                 /* see control point stream order at page 330 in pdf 1.7 */
  302.  
  303.                 p->pole[0][0] = pt[0];
  304.                 p->pole[0][1] = pt[1];
  305.                 p->pole[0][2] = pt[2];
  306.                 p->pole[0][3] = pt[3];
  307.                 p->pole[1][3] = pt[4];
  308.                 p->pole[2][3] = pt[5];
  309.                 p->pole[3][3] = pt[6];
  310.                 p->pole[3][2] = pt[7];
  311.                 p->pole[3][1] = pt[8];
  312.                 p->pole[3][0] = pt[9];
  313.                 p->pole[2][0] = pt[10];
  314.                 p->pole[1][0] = pt[11];
  315.                 p->pole[1][1] = pt[12];
  316.                 p->pole[1][2] = pt[13];
  317.                 p->pole[2][2] = pt[14];
  318.                 p->pole[2][1] = pt[15];
  319.         }
  320. }
  321.  
  322. /* Sample various functions into lookup tables */
  323.  
  324. static void
  325. pdf_sample_composite_shade_function(fz_shade *shade, pdf_function *func, float t0, float t1)
  326. {
  327.         int i;
  328.         float t;
  329.  
  330.         for (i = 0; i < 256; i++)
  331.         {
  332.                 t = t0 + (i / 255.0f) * (t1 - t0);
  333.                 pdf_eval_function(func, &t, 1, shade->function[i], shade->colorspace->n);
  334.                 shade->function[i][shade->colorspace->n] = 1;
  335.         }
  336. }
  337.  
  338. static void
  339. pdf_sample_component_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
  340. {
  341.         int i, k;
  342.         float t;
  343.  
  344.         for (i = 0; i < 256; i++)
  345.         {
  346.                 t = t0 + (i / 255.0f) * (t1 - t0);
  347.                 for (k = 0; k < funcs; k++)
  348.                         pdf_eval_function(func[k], &t, 1, &shade->function[i][k], 1);
  349.                 shade->function[i][k] = 1;
  350.         }
  351. }
  352.  
  353. static void
  354. pdf_sample_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
  355. {
  356.         shade->use_function = 1;
  357.         if (funcs == 1)
  358.                 pdf_sample_composite_shade_function(shade, func[0], t0, t1);
  359.         else
  360.                 pdf_sample_component_shade_function(shade, funcs, func, t0, t1);
  361. }
  362.  
  363. /* Type 1-3 -- Function-based, axial and radial shadings */
  364.  
  365. static void
  366. pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_function *func)
  367. {
  368.         fz_obj *obj;
  369.         float x0, y0, x1, y1;
  370.         fz_matrix matrix;
  371.         struct vertex v[4];
  372.         int xx, yy;
  373.         float x, y;
  374.         float xn, yn;
  375.         int i;
  376.  
  377.         x0 = y0 = 0;
  378.         x1 = y1 = 1;
  379.         obj = fz_dict_gets(dict, "Domain");
  380.         if (fz_array_len(obj) == 4)
  381.         {
  382.                 x0 = fz_to_real(fz_array_get(obj, 0));
  383.                 x1 = fz_to_real(fz_array_get(obj, 1));
  384.                 y0 = fz_to_real(fz_array_get(obj, 2));
  385.                 y1 = fz_to_real(fz_array_get(obj, 3));
  386.         }
  387.  
  388.         matrix = fz_identity;
  389.         obj = fz_dict_gets(dict, "Matrix");
  390.         if (fz_array_len(obj) == 6)
  391.                 matrix = pdf_to_matrix(obj);
  392.  
  393.         for (yy = 0; yy < FUNSEGS; yy++)
  394.         {
  395.                 y = y0 + (y1 - y0) * yy / FUNSEGS;
  396.                 yn = y0 + (y1 - y0) * (yy + 1) / FUNSEGS;
  397.  
  398.                 for (xx = 0; xx < FUNSEGS; xx++)
  399.                 {
  400.                         x = x0 + (x1 - x0) * xx / FUNSEGS;
  401.                         xn = x0 + (x1 - x0) * (xx + 1) / FUNSEGS;
  402.  
  403.                         v[0].x = x; v[0].y = y;
  404.                         v[1].x = xn; v[1].y = y;
  405.                         v[2].x = xn; v[2].y = yn;
  406.                         v[3].x = x; v[3].y = yn;
  407.  
  408.                         for (i = 0; i < 4; i++)
  409.                         {
  410.                                 fz_point pt;
  411.                                 float fv[2];
  412.  
  413.                                 fv[0] = v[i].x;
  414.                                 fv[1] = v[i].y;
  415.                                 pdf_eval_function(func, fv, 2, v[i].c, shade->colorspace->n);
  416.  
  417.                                 pt.x = v[i].x;
  418.                                 pt.y = v[i].y;
  419.                                 pt = fz_transform_point(matrix, pt);
  420.                                 v[i].x = pt.x;
  421.                                 v[i].y = pt.y;
  422.                         }
  423.  
  424.                         pdf_add_quad(shade, &v[0], &v[1], &v[2], &v[3]);
  425.                 }
  426.         }
  427. }
  428.  
  429. static void
  430. pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
  431. {
  432.         fz_obj *obj;
  433.         float d0, d1;
  434.         int e0, e1;
  435.         float x0, y0, x1, y1;
  436.         struct vertex p1, p2;
  437.  
  438.         obj = fz_dict_gets(dict, "Coords");
  439.         x0 = fz_to_real(fz_array_get(obj, 0));
  440.         y0 = fz_to_real(fz_array_get(obj, 1));
  441.         x1 = fz_to_real(fz_array_get(obj, 2));
  442.         y1 = fz_to_real(fz_array_get(obj, 3));
  443.  
  444.         d0 = 0;
  445.         d1 = 1;
  446.         obj = fz_dict_gets(dict, "Domain");
  447.         if (fz_array_len(obj) == 2)
  448.         {
  449.                 d0 = fz_to_real(fz_array_get(obj, 0));
  450.                 d1 = fz_to_real(fz_array_get(obj, 1));
  451.         }
  452.  
  453.         e0 = e1 = 0;
  454.         obj = fz_dict_gets(dict, "Extend");
  455.         if (fz_array_len(obj) == 2)
  456.         {
  457.                 e0 = fz_to_bool(fz_array_get(obj, 0));
  458.                 e1 = fz_to_bool(fz_array_get(obj, 1));
  459.         }
  460.  
  461.         pdf_sample_shade_function(shade, funcs, func, d0, d1);
  462.  
  463.         shade->type = FZ_LINEAR;
  464.  
  465.         shade->extend[0] = e0;
  466.         shade->extend[1] = e1;
  467.  
  468.         p1.x = x0;
  469.         p1.y = y0;
  470.         p1.c[0] = 0;
  471.         pdf_add_vertex(shade, &p1);
  472.  
  473.         p2.x = x1;
  474.         p2.y = y1;
  475.         p2.c[0] = 0;
  476.         pdf_add_vertex(shade, &p2);
  477. }
  478.  
  479. static void
  480. pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
  481. {
  482.         fz_obj *obj;
  483.         float d0, d1;
  484.         int e0, e1;
  485.         float x0, y0, r0, x1, y1, r1;
  486.         struct vertex p1, p2;
  487.  
  488.         obj = fz_dict_gets(dict, "Coords");
  489.         x0 = fz_to_real(fz_array_get(obj, 0));
  490.         y0 = fz_to_real(fz_array_get(obj, 1));
  491.         r0 = fz_to_real(fz_array_get(obj, 2));
  492.         x1 = fz_to_real(fz_array_get(obj, 3));
  493.         y1 = fz_to_real(fz_array_get(obj, 4));
  494.         r1 = fz_to_real(fz_array_get(obj, 5));
  495.  
  496.         d0 = 0;
  497.         d1 = 1;
  498.         obj = fz_dict_gets(dict, "Domain");
  499.         if (fz_array_len(obj) == 2)
  500.         {
  501.                 d0 = fz_to_real(fz_array_get(obj, 0));
  502.                 d1 = fz_to_real(fz_array_get(obj, 1));
  503.         }
  504.  
  505.         e0 = e1 = 0;
  506.         obj = fz_dict_gets(dict, "Extend");
  507.         if (fz_array_len(obj) == 2)
  508.         {
  509.                 e0 = fz_to_bool(fz_array_get(obj, 0));
  510.                 e1 = fz_to_bool(fz_array_get(obj, 1));
  511.         }
  512.  
  513.         pdf_sample_shade_function(shade, funcs, func, d0, d1);
  514.  
  515.         shade->type = FZ_RADIAL;
  516.  
  517.         shade->extend[0] = e0;
  518.         shade->extend[1] = e1;
  519.  
  520.         p1.x = x0;
  521.         p1.y = y0;
  522.         p1.c[0] = r0;
  523.         pdf_add_vertex(shade, &p1);
  524.  
  525.         p2.x = x1;
  526.         p2.y = y1;
  527.         p2.c[0] = r1;
  528.         pdf_add_vertex(shade, &p2);
  529. }
  530.  
  531. /* Type 4-7 -- Triangle and patch mesh shadings */
  532.  
  533. static inline float read_sample(fz_stream *stream, int bits, float min, float max)
  534. {
  535.         /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */
  536.         float bitscale = 1 / (powf(2, bits) - 1);
  537.         return min + fz_read_bits(stream, bits) * (max - min) * bitscale;
  538. }
  539.  
  540. struct mesh_params
  541. {
  542.         int vprow;
  543.         int bpflag;
  544.         int bpcoord;
  545.         int bpcomp;
  546.         float x0, x1;
  547.         float y0, y1;
  548.         float c0[FZ_MAX_COLORS];
  549.         float c1[FZ_MAX_COLORS];
  550. };
  551.  
  552. static void
  553. pdf_load_mesh_params(pdf_xref *xref, fz_obj *dict, struct mesh_params *p)
  554. {
  555.         fz_obj *obj;
  556.         int i, n;
  557.  
  558.         p->x0 = p->y0 = 0;
  559.         p->x1 = p->y1 = 1;
  560.         for (i = 0; i < FZ_MAX_COLORS; i++)
  561.         {
  562.                 p->c0[i] = 0;
  563.                 p->c1[i] = 1;
  564.         }
  565.  
  566.         p->vprow = fz_to_int(fz_dict_gets(dict, "VerticesPerRow"));
  567.         p->bpflag = fz_to_int(fz_dict_gets(dict, "BitsPerFlag"));
  568.         p->bpcoord = fz_to_int(fz_dict_gets(dict, "BitsPerCoordinate"));
  569.         p->bpcomp = fz_to_int(fz_dict_gets(dict, "BitsPerComponent"));
  570.  
  571.         obj = fz_dict_gets(dict, "Decode");
  572.         if (fz_array_len(obj) >= 6)
  573.         {
  574.                 n = (fz_array_len(obj) - 4) / 2;
  575.                 p->x0 = fz_to_real(fz_array_get(obj, 0));
  576.                 p->x1 = fz_to_real(fz_array_get(obj, 1));
  577.                 p->y0 = fz_to_real(fz_array_get(obj, 2));
  578.                 p->y1 = fz_to_real(fz_array_get(obj, 3));
  579.                 for (i = 0; i < n; i++)
  580.                 {
  581.                         p->c0[i] = fz_to_real(fz_array_get(obj, 4 + i * 2));
  582.                         p->c1[i] = fz_to_real(fz_array_get(obj, 5 + i * 2));
  583.                 }
  584.         }
  585.  
  586.         if (p->vprow < 2)
  587.                 p->vprow = 2;
  588.  
  589.         if (p->bpflag != 2 && p->bpflag != 4 && p->bpflag != 8)
  590.                 p->bpflag = 8;
  591.  
  592.         if (p->bpcoord != 1 && p->bpcoord != 2 && p->bpcoord != 4 &&
  593.                 p->bpcoord != 8 && p->bpcoord != 12 && p->bpcoord != 16 &&
  594.                 p->bpcoord != 24 && p->bpcoord != 32)
  595.                 p->bpcoord = 8;
  596.  
  597.         if (p->bpcomp != 1 && p->bpcomp != 2 && p->bpcomp != 4 &&
  598.                 p->bpcomp != 8 && p->bpcomp != 12 && p->bpcomp != 16)
  599.                 p->bpcomp = 8;
  600. }
  601.  
  602. static void
  603. pdf_load_type4_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
  604.         int funcs, pdf_function **func, fz_stream *stream)
  605. {
  606.         struct mesh_params p;
  607.         struct vertex va, vb, vc, vd;
  608.         int ncomp;
  609.         int flag;
  610.         int i;
  611.  
  612.         pdf_load_mesh_params(xref, dict, &p);
  613.  
  614.         if (funcs > 0)
  615.         {
  616.                 ncomp = 1;
  617.                 pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
  618.         }
  619.         else
  620.                 ncomp = shade->colorspace->n;
  621.  
  622.         while (!fz_is_eof_bits(stream))
  623.         {
  624.                 flag = fz_read_bits(stream, p.bpflag);
  625.                 vd.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  626.                 vd.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  627.                 for (i = 0; i < ncomp; i++)
  628.                         vd.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
  629.  
  630.                 switch (flag)
  631.                 {
  632.                 case 0: /* start new triangle */
  633.                         va = vd;
  634.  
  635.                         fz_read_bits(stream, p.bpflag);
  636.                         vb.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  637.                         vb.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  638.                         for (i = 0; i < ncomp; i++)
  639.                                 vb.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
  640.  
  641.                         fz_read_bits(stream, p.bpflag);
  642.                         vc.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  643.                         vc.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  644.                         for (i = 0; i < ncomp; i++)
  645.                                 vc.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
  646.  
  647.                         pdf_add_triangle(shade, &va, &vb, &vc);
  648.                         break;
  649.  
  650.                 case 1: /* Vb, Vc, Vd */
  651.                         va = vb;
  652.                         vb = vc;
  653.                         vc = vd;
  654.                         pdf_add_triangle(shade, &va, &vb, &vc);
  655.                         break;
  656.  
  657.                 case 2: /* Va, Vc, Vd */
  658.                         vb = vc;
  659.                         vc = vd;
  660.                         pdf_add_triangle(shade, &va, &vb, &vc);
  661.                         break;
  662.                 }
  663.         }
  664. }
  665.  
  666. static void
  667. pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
  668.         int funcs, pdf_function **func, fz_stream *stream)
  669. {
  670.         struct mesh_params p;
  671.         struct vertex *buf, *ref;
  672.         int first;
  673.         int ncomp;
  674.         int i, k;
  675.  
  676.         pdf_load_mesh_params(xref, dict, &p);
  677.  
  678.         if (funcs > 0)
  679.         {
  680.                 ncomp = 1;
  681.                 pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
  682.         }
  683.         else
  684.                 ncomp = shade->colorspace->n;
  685.  
  686.         ref = fz_calloc(p.vprow, sizeof(struct vertex));
  687.         buf = fz_calloc(p.vprow, sizeof(struct vertex));
  688.         first = 1;
  689.  
  690.         while (!fz_is_eof_bits(stream))
  691.         {
  692.                 for (i = 0; i < p.vprow; i++)
  693.                 {
  694.                         buf[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  695.                         buf[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  696.                         for (k = 0; k < ncomp; k++)
  697.                                 buf[i].c[k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
  698.                 }
  699.  
  700.                 if (!first)
  701.                         for (i = 0; i < p.vprow - 1; i++)
  702.                                 pdf_add_quad(shade,
  703.                                         &ref[i], &ref[i+1], &buf[i+1], &buf[i]);
  704.  
  705.                 memcpy(ref, buf, p.vprow * sizeof(struct vertex));
  706.                 first = 0;
  707.         }
  708.  
  709.         free(ref);
  710.         free(buf);
  711. }
  712.  
  713. /* Type 6 & 7 -- Patch mesh shadings */
  714.  
  715. static void
  716. pdf_load_type6_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
  717.         int funcs, pdf_function **func, fz_stream *stream)
  718. {
  719.         struct mesh_params p;
  720.         int haspatch, hasprevpatch;
  721.         float prevc[4][FZ_MAX_COLORS];
  722.         fz_point prevp[12];
  723.         int ncomp;
  724.         int i, k;
  725.  
  726.         pdf_load_mesh_params(xref, dict, &p);
  727.  
  728.         if (funcs > 0)
  729.         {
  730.                 ncomp = 1;
  731.                 pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
  732.         }
  733.         else
  734.                 ncomp = shade->colorspace->n;
  735.  
  736.         hasprevpatch = 0;
  737.  
  738.         while (!fz_is_eof_bits(stream))
  739.         {
  740.                 float c[4][FZ_MAX_COLORS];
  741.                 fz_point v[12];
  742.                 int startcolor;
  743.                 int startpt;
  744.                 int flag;
  745.  
  746.                 flag = fz_read_bits(stream, p.bpflag);
  747.  
  748.                 if (flag == 0)
  749.                 {
  750.                         startpt = 0;
  751.                         startcolor = 0;
  752.                 }
  753.                 else
  754.                 {
  755.                         startpt = 4;
  756.                         startcolor = 2;
  757.                 }
  758.  
  759.                 for (i = startpt; i < 12; i++)
  760.                 {
  761.                         v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  762.                         v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  763.                 }
  764.  
  765.                 for (i = startcolor; i < 4; i++)
  766.                 {
  767.                         for (k = 0; k < ncomp; k++)
  768.                                 c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
  769.                 }
  770.  
  771.                 haspatch = 0;
  772.  
  773.                 if (flag == 0)
  774.                 {
  775.                         haspatch = 1;
  776.                 }
  777.                 else if (flag == 1 && hasprevpatch)
  778.                 {
  779.                         v[0] = prevp[3];
  780.                         v[1] = prevp[4];
  781.                         v[2] = prevp[5];
  782.                         v[3] = prevp[6];
  783.                         memcpy(c[0], prevc[1], ncomp * sizeof(float));
  784.                         memcpy(c[1], prevc[2], ncomp * sizeof(float));
  785.  
  786.                         haspatch = 1;
  787.                 }
  788.                 else if (flag == 2 && hasprevpatch)
  789.                 {
  790.                         v[0] = prevp[6];
  791.                         v[1] = prevp[7];
  792.                         v[2] = prevp[8];
  793.                         v[3] = prevp[9];
  794.                         memcpy(c[0], prevc[2], ncomp * sizeof(float));
  795.                         memcpy(c[1], prevc[3], ncomp * sizeof(float));
  796.  
  797.                         haspatch = 1;
  798.                 }
  799.                 else if (flag == 3 && hasprevpatch)
  800.                 {
  801.                         v[0] = prevp[ 9];
  802.                         v[1] = prevp[10];
  803.                         v[2] = prevp[11];
  804.                         v[3] = prevp[ 0];
  805.                         memcpy(c[0], prevc[3], ncomp * sizeof(float));
  806.                         memcpy(c[1], prevc[0], ncomp * sizeof(float));
  807.  
  808.                         haspatch = 1;
  809.                 }
  810.  
  811.                 if (haspatch)
  812.                 {
  813.                         pdf_tensor_patch patch;
  814.  
  815.                         pdf_make_tensor_patch(&patch, 6, v);
  816.  
  817.                         for (i = 0; i < 4; i++)
  818.                                 memcpy(patch.color[i], c[i], ncomp * sizeof(float));
  819.  
  820.                         draw_patch(shade, &patch, SUBDIV, SUBDIV);
  821.  
  822.                         for (i = 0; i < 12; i++)
  823.                                 prevp[i] = v[i];
  824.  
  825.                         for (i = 0; i < 4; i++)
  826.                                 memcpy(prevc[i], c[i], ncomp * sizeof(float));
  827.  
  828.                         hasprevpatch = 1;
  829.                 }
  830.         }
  831. }
  832.  
  833. static void
  834. pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
  835.         int funcs, pdf_function **func, fz_stream *stream)
  836. {
  837.         struct mesh_params p;
  838.         int haspatch, hasprevpatch;
  839.         float prevc[4][FZ_MAX_COLORS];
  840.         fz_point prevp[16];
  841.         int ncomp;
  842.         int i, k;
  843.  
  844.         pdf_load_mesh_params(xref, dict, &p);
  845.  
  846.         if (funcs > 0)
  847.         {
  848.                 ncomp = 1;
  849.                 pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
  850.         }
  851.         else
  852.                 ncomp = shade->colorspace->n;
  853.  
  854.         hasprevpatch = 0;
  855.  
  856.         while (!fz_is_eof_bits(stream))
  857.         {
  858.                 float c[4][FZ_MAX_COLORS];
  859.                 fz_point v[16];
  860.                 int startcolor;
  861.                 int startpt;
  862.                 int flag;
  863.  
  864.                 flag = fz_read_bits(stream, p.bpflag);
  865.  
  866.                 if (flag == 0)
  867.                 {
  868.                         startpt = 0;
  869.                         startcolor = 0;
  870.                 }
  871.                 else
  872.                 {
  873.                         startpt = 4;
  874.                         startcolor = 2;
  875.                 }
  876.  
  877.                 for (i = startpt; i < 16; i++)
  878.                 {
  879.                         v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
  880.                         v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
  881.                 }
  882.  
  883.                 for (i = startcolor; i < 4; i++)
  884.                 {
  885.                         for (k = 0; k < ncomp; k++)
  886.                                 c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
  887.                 }
  888.  
  889.                 haspatch = 0;
  890.  
  891.                 if (flag == 0)
  892.                 {
  893.                         haspatch = 1;
  894.                 }
  895.                 else if (flag == 1 && hasprevpatch)
  896.                 {
  897.                         v[0] = prevp[3];
  898.                         v[1] = prevp[4];
  899.                         v[2] = prevp[5];
  900.                         v[3] = prevp[6];
  901.                         memcpy(c[0], prevc[1], ncomp * sizeof(float));
  902.                         memcpy(c[1], prevc[2], ncomp * sizeof(float));
  903.  
  904.                         haspatch = 1;
  905.                 }
  906.                 else if (flag == 2 && hasprevpatch)
  907.                 {
  908.                         v[0] = prevp[6];
  909.                         v[1] = prevp[7];
  910.                         v[2] = prevp[8];
  911.                         v[3] = prevp[9];
  912.                         memcpy(c[0], prevc[2], ncomp * sizeof(float));
  913.                         memcpy(c[1], prevc[3], ncomp * sizeof(float));
  914.  
  915.                         haspatch = 1;
  916.                 }
  917.                 else if (flag == 3 && hasprevpatch)
  918.                 {
  919.                         v[0] = prevp[ 9];
  920.                         v[1] = prevp[10];
  921.                         v[2] = prevp[11];
  922.                         v[3] = prevp[ 0];
  923.                         memcpy(c[0], prevc[3], ncomp * sizeof(float));
  924.                         memcpy(c[1], prevc[0], ncomp * sizeof(float));
  925.  
  926.                         haspatch = 1;
  927.                 }
  928.  
  929.                 if (haspatch)
  930.                 {
  931.                         pdf_tensor_patch patch;
  932.  
  933.                         pdf_make_tensor_patch(&patch, 7, v);
  934.  
  935.                         for (i = 0; i < 4; i++)
  936.                                 memcpy(patch.color[i], c[i], ncomp * sizeof(float));
  937.  
  938.                         draw_patch(shade, &patch, SUBDIV, SUBDIV);
  939.  
  940.                         for (i = 0; i < 16; i++)
  941.                                 prevp[i] = v[i];
  942.  
  943.                         for (i = 0; i < 4; i++)
  944.                                 memcpy(prevc[i], c[i], FZ_MAX_COLORS * sizeof(float));
  945.  
  946.                         hasprevpatch = 1;
  947.                 }
  948.         }
  949. }
  950.  
  951. /* Load all of the shading dictionary parameters, then switch on the shading type. */
  952.  
  953. static fz_error
  954. pdf_load_shading_dict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix transform)
  955. {
  956.         fz_error error;
  957.         fz_shade *shade;
  958.         pdf_function *func[FZ_MAX_COLORS] = { NULL };
  959.         fz_stream *stream = NULL;
  960.         fz_obj *obj;
  961.         int funcs;
  962.         int type;
  963.         int i;
  964.  
  965.         shade = fz_malloc(sizeof(fz_shade));
  966.         shade->refs = 1;
  967.         shade->type = FZ_MESH;
  968.         shade->use_background = 0;
  969.         shade->use_function = 0;
  970.         shade->matrix = transform;
  971.         shade->bbox = fz_infinite_rect;
  972.         shade->extend[0] = 0;
  973.         shade->extend[1] = 0;
  974.  
  975.         shade->mesh_len = 0;
  976.         shade->mesh_cap = 0;
  977.         shade->mesh = NULL;
  978.  
  979.         shade->colorspace = NULL;
  980.  
  981.         funcs = 0;
  982.  
  983.         obj = fz_dict_gets(dict, "ShadingType");
  984.         type = fz_to_int(obj);
  985.  
  986.         obj = fz_dict_gets(dict, "ColorSpace");
  987.         if (!obj)
  988.         {
  989.                 fz_drop_shade(shade);
  990.                 return fz_throw("shading colorspace is missing");
  991.         }
  992.         error = pdf_load_colorspace(&shade->colorspace, xref, obj);
  993.         if (error)
  994.         {
  995.                 fz_drop_shade(shade);
  996.                 return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
  997.         }
  998.  
  999.         obj = fz_dict_gets(dict, "Background");
  1000.         if (obj)
  1001.         {
  1002.                 shade->use_background = 1;
  1003.                 for (i = 0; i < shade->colorspace->n; i++)
  1004.                         shade->background[i] = fz_to_real(fz_array_get(obj, i));
  1005.         }
  1006.  
  1007.         obj = fz_dict_gets(dict, "BBox");
  1008.         if (fz_is_array(obj))
  1009.         {
  1010.                 shade->bbox = pdf_to_rect(obj);
  1011.         }
  1012.  
  1013.         obj = fz_dict_gets(dict, "Function");
  1014.         if (fz_is_dict(obj))
  1015.         {
  1016.                 funcs = 1;
  1017.  
  1018.                 error = pdf_load_function(&func[0], xref, obj);
  1019.                 if (error)
  1020.                 {
  1021.                         error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
  1022.                         goto cleanup;
  1023.                 }
  1024.         }
  1025.         else if (fz_is_array(obj))
  1026.         {
  1027.                 funcs = fz_array_len(obj);
  1028.                 if (funcs != 1 && funcs != shade->colorspace->n)
  1029.                 {
  1030.                         error = fz_throw("incorrect number of shading functions");
  1031.                         goto cleanup;
  1032.                 }
  1033.  
  1034.                 for (i = 0; i < funcs; i++)
  1035.                 {
  1036.                         error = pdf_load_function(&func[i], xref, fz_array_get(obj, i));
  1037.                         if (error)
  1038.                         {
  1039.                                 error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
  1040.                                 goto cleanup;
  1041.                         }
  1042.                 }
  1043.         }
  1044.  
  1045.         if (type >= 4 && type <= 7)
  1046.         {
  1047.                 error = pdf_open_stream(&stream, xref, fz_to_num(dict), fz_to_gen(dict));
  1048.                 if (error)
  1049.                 {
  1050.                         error = fz_rethrow(error, "cannot open shading stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
  1051.                         goto cleanup;
  1052.                 }
  1053.         }
  1054.  
  1055.         switch (type)
  1056.         {
  1057.         case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break;
  1058.         case 2: pdf_load_axial_shading(shade, xref, dict, funcs, func); break;
  1059.         case 3: pdf_load_radial_shading(shade, xref, dict, funcs, func); break;
  1060.         case 4: pdf_load_type4_shade(shade, xref, dict, funcs, func, stream); break;
  1061.         case 5: pdf_load_type5_shade(shade, xref, dict, funcs, func, stream); break;
  1062.         case 6: pdf_load_type6_shade(shade, xref, dict, funcs, func, stream); break;
  1063.         case 7: pdf_load_type7_shade(shade, xref, dict, funcs, func, stream); break;
  1064.         default:
  1065.                 error = fz_throw("unknown shading type: %d", type);
  1066.                 goto cleanup;
  1067.         }
  1068.  
  1069.         if (stream)
  1070.                 fz_close(stream);
  1071.         for (i = 0; i < funcs; i++)
  1072.                 if (func[i])
  1073.                         pdf_drop_function(func[i]);
  1074.  
  1075.         *shadep = shade;
  1076.         return fz_okay;
  1077.  
  1078. cleanup:
  1079.         if (stream)
  1080.                 fz_close(stream);
  1081.         for (i = 0; i < funcs; i++)
  1082.                 if (func[i])
  1083.                         pdf_drop_function(func[i]);
  1084.         fz_drop_shade(shade);
  1085.  
  1086.         return fz_rethrow(error, "cannot load shading type %d (%d %d R)", type, fz_to_num(dict), fz_to_gen(dict));
  1087. }
  1088.  
  1089. fz_error
  1090. pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *dict)
  1091. {
  1092.         fz_error error;
  1093.         fz_matrix mat;
  1094.         fz_obj *obj;
  1095.  
  1096.         if ((*shadep = pdf_find_item(xref->store, fz_drop_shade, dict)))
  1097.         {
  1098.                 fz_keep_shade(*shadep);
  1099.                 return fz_okay;
  1100.         }
  1101.  
  1102.         /* Type 2 pattern dictionary */
  1103.         if (fz_dict_gets(dict, "PatternType"))
  1104.         {
  1105.                 obj = fz_dict_gets(dict, "Matrix");
  1106.                 if (obj)
  1107.                         mat = pdf_to_matrix(obj);
  1108.                 else
  1109.                         mat = fz_identity;
  1110.  
  1111.                 obj = fz_dict_gets(dict, "ExtGState");
  1112.                 if (obj)
  1113.                 {
  1114.                         if (fz_dict_gets(obj, "CA") || fz_dict_gets(obj, "ca"))
  1115.                         {
  1116.                                 fz_warn("shading with alpha not supported");
  1117.                         }
  1118.                 }
  1119.  
  1120.                 obj = fz_dict_gets(dict, "Shading");
  1121.                 if (!obj)
  1122.                         return fz_throw("syntaxerror: missing shading dictionary");
  1123.  
  1124.                 error = pdf_load_shading_dict(shadep, xref, obj, mat);
  1125.                 if (error)
  1126.                         return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
  1127.         }
  1128.  
  1129.         /* Naked shading dictionary */
  1130.         else
  1131.         {
  1132.                 error = pdf_load_shading_dict(shadep, xref, dict, fz_identity);
  1133.                 if (error)
  1134.                         return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
  1135.         }
  1136.  
  1137.         pdf_store_item(xref->store, fz_keep_shade, fz_drop_shade, dict, *shadep);
  1138.  
  1139.         return fz_okay;
  1140. }
  1141.