Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. static inline int unhex(int a)
  5. {
  6.         if (a >= 'A' && a <= 'F') return a - 'A' + 0xA;
  7.         if (a >= 'a' && a <= 'f') return a - 'a' + 0xA;
  8.         if (a >= '0' && a <= '9') return a - '0';
  9.         return 0;
  10. }
  11.  
  12. void
  13. xps_parse_brush(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node)
  14. {
  15.         /* SolidColorBrushes are handled in a special case and will never show up here */
  16.         if (!strcmp(xml_tag(node), "ImageBrush"))
  17.                 xps_parse_image_brush(ctx, ctm, area, base_uri, dict, node);
  18.         else if (!strcmp(xml_tag(node), "VisualBrush"))
  19.                 xps_parse_visual_brush(ctx, ctm, area, base_uri, dict, node);
  20.         else if (!strcmp(xml_tag(node), "LinearGradientBrush"))
  21.                 xps_parse_linear_gradient_brush(ctx, ctm, area, base_uri, dict, node);
  22.         else if (!strcmp(xml_tag(node), "RadialGradientBrush"))
  23.                 xps_parse_radial_gradient_brush(ctx, ctm, area, base_uri, dict, node);
  24.         else
  25.                 fz_warn("unknown brush tag: %s", xml_tag(node));
  26. }
  27.  
  28. void
  29. xps_parse_element(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *node)
  30. {
  31.         if (!strcmp(xml_tag(node), "Path"))
  32.                 xps_parse_path(ctx, ctm, base_uri, dict, node);
  33.         if (!strcmp(xml_tag(node), "Glyphs"))
  34.                 xps_parse_glyphs(ctx, ctm, base_uri, dict, node);
  35.         if (!strcmp(xml_tag(node), "Canvas"))
  36.                 xps_parse_canvas(ctx, ctm, area, base_uri, dict, node);
  37.         /* skip unknown tags (like Foo.Resources and similar) */
  38. }
  39.  
  40. void
  41. xps_begin_opacity(xps_context *ctx, fz_matrix ctm, fz_rect area,
  42.         char *base_uri, xps_resource *dict,
  43.         char *opacity_att, xml_element *opacity_mask_tag)
  44. {
  45.         float opacity;
  46.  
  47.         if (!opacity_att && !opacity_mask_tag)
  48.                 return;
  49.  
  50.         opacity = 1;
  51.         if (opacity_att)
  52.                 opacity = fz_atof(opacity_att);
  53.  
  54.         if (opacity_mask_tag && !strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush"))
  55.         {
  56.                 char *scb_opacity_att = xml_att(opacity_mask_tag, "Opacity");
  57.                 char *scb_color_att = xml_att(opacity_mask_tag, "Color");
  58.                 if (scb_opacity_att)
  59.                         opacity = opacity * fz_atof(scb_opacity_att);
  60.                 if (scb_color_att)
  61.                 {
  62.                         fz_colorspace *colorspace;
  63.                         float samples[32];
  64.                         xps_parse_color(ctx, base_uri, scb_color_att, &colorspace, samples);
  65.                         opacity = opacity * samples[0];
  66.                 }
  67.                 opacity_mask_tag = NULL;
  68.         }
  69.  
  70.         if (ctx->opacity_top + 1 < nelem(ctx->opacity))
  71.         {
  72.                 ctx->opacity[ctx->opacity_top + 1] = ctx->opacity[ctx->opacity_top] * opacity;
  73.                 ctx->opacity_top++;
  74.         }
  75.  
  76.         if (opacity_mask_tag)
  77.         {
  78.                 fz_begin_mask(ctx->dev, area, 0, NULL, NULL);
  79.                 xps_parse_brush(ctx, ctm, area, base_uri, dict, opacity_mask_tag);
  80.                 fz_end_mask(ctx->dev);
  81.         }
  82. }
  83.  
  84. void
  85. xps_end_opacity(xps_context *ctx, char *base_uri, xps_resource *dict,
  86.         char *opacity_att, xml_element *opacity_mask_tag)
  87. {
  88.         if (!opacity_att && !opacity_mask_tag)
  89.                 return;
  90.  
  91.         if (ctx->opacity_top > 0)
  92.                 ctx->opacity_top--;
  93.  
  94.         if (opacity_mask_tag)
  95.         {
  96.                 if (strcmp(xml_tag(opacity_mask_tag), "SolidColorBrush"))
  97.                         fz_pop_clip(ctx->dev);
  98.         }
  99. }
  100.  
  101. void
  102. xps_parse_render_transform(xps_context *ctx, char *transform, fz_matrix *matrix)
  103. {
  104.         float args[6];
  105.         char *s = transform;
  106.         int i;
  107.  
  108.         args[0] = 1; args[1] = 0;
  109.         args[2] = 0; args[3] = 1;
  110.         args[4] = 0; args[5] = 0;
  111.  
  112.         for (i = 0; i < 6 && *s; i++)
  113.         {
  114.                 args[i] = fz_atof(s);
  115.                 while (*s && *s != ',')
  116.                         s++;
  117.                 if (*s == ',')
  118.                         s++;
  119.         }
  120.  
  121.         matrix->a = args[0]; matrix->b = args[1];
  122.         matrix->c = args[2]; matrix->d = args[3];
  123.         matrix->e = args[4]; matrix->f = args[5];
  124. }
  125.  
  126. void
  127. xps_parse_matrix_transform(xps_context *ctx, xml_element *root, fz_matrix *matrix)
  128. {
  129.         char *transform;
  130.  
  131.         *matrix = fz_identity;
  132.  
  133.         if (!strcmp(xml_tag(root), "MatrixTransform"))
  134.         {
  135.                 transform = xml_att(root, "Matrix");
  136.                 if (transform)
  137.                         xps_parse_render_transform(ctx, transform, matrix);
  138.         }
  139. }
  140.  
  141. void
  142. xps_parse_rectangle(xps_context *ctx, char *text, fz_rect *rect)
  143. {
  144.         float args[4];
  145.         char *s = text;
  146.         int i;
  147.  
  148.         args[0] = 0; args[1] = 0;
  149.         args[2] = 1; args[3] = 1;
  150.  
  151.         for (i = 0; i < 4 && *s; i++)
  152.         {
  153.                 args[i] = fz_atof(s);
  154.                 while (*s && *s != ',')
  155.                         s++;
  156.                 if (*s == ',')
  157.                         s++;
  158.         }
  159.  
  160.         rect->x0 = args[0];
  161.         rect->y0 = args[1];
  162.         rect->x1 = args[0] + args[2];
  163.         rect->y1 = args[1] + args[3];
  164. }
  165.  
  166. static int count_commas(char *s)
  167. {
  168.         int n = 0;
  169.         while (*s)
  170.         {
  171.                 if (*s == ',')
  172.                         n ++;
  173.                 s ++;
  174.         }
  175.         return n;
  176. }
  177.  
  178. void
  179. xps_parse_color(xps_context *ctx, char *base_uri, char *string,
  180.                 fz_colorspace **csp, float *samples)
  181. {
  182.         char *p;
  183.         int i, n;
  184.         char buf[1024];
  185.         char *profile;
  186.  
  187.         *csp = fz_device_rgb;
  188.  
  189.         samples[0] = 1;
  190.         samples[1] = 0;
  191.         samples[2] = 0;
  192.         samples[3] = 0;
  193.  
  194.         if (string[0] == '#')
  195.         {
  196.                 if (strlen(string) == 9)
  197.                 {
  198.                         samples[0] = unhex(string[1]) * 16 + unhex(string[2]);
  199.                         samples[1] = unhex(string[3]) * 16 + unhex(string[4]);
  200.                         samples[2] = unhex(string[5]) * 16 + unhex(string[6]);
  201.                         samples[3] = unhex(string[7]) * 16 + unhex(string[8]);
  202.                 }
  203.                 else
  204.                 {
  205.                         samples[0] = 255;
  206.                         samples[1] = unhex(string[1]) * 16 + unhex(string[2]);
  207.                         samples[2] = unhex(string[3]) * 16 + unhex(string[4]);
  208.                         samples[3] = unhex(string[5]) * 16 + unhex(string[6]);
  209.                 }
  210.  
  211.                 samples[0] /= 255;
  212.                 samples[1] /= 255;
  213.                 samples[2] /= 255;
  214.                 samples[3] /= 255;
  215.         }
  216.  
  217.         else if (string[0] == 's' && string[1] == 'c' && string[2] == '#')
  218.         {
  219.                 if (count_commas(string) == 2)
  220.                         sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3);
  221.                 if (count_commas(string) == 3)
  222.                         sscanf(string, "sc#%g,%g,%g,%g", samples, samples + 1, samples + 2, samples + 3);
  223.         }
  224.  
  225.         else if (strstr(string, "ContextColor ") == string)
  226.         {
  227.                 /* Crack the string for profile name and sample values */
  228.                 fz_strlcpy(buf, string, sizeof buf);
  229.  
  230.                 profile = strchr(buf, ' ');
  231.                 if (!profile)
  232.                 {
  233.                         fz_warn("cannot find icc profile uri in '%s'", string);
  234.                         return;
  235.                 }
  236.  
  237.                 *profile++ = 0;
  238.                 p = strchr(profile, ' ');
  239.                 if (!p)
  240.                 {
  241.                         fz_warn("cannot find component values in '%s'", profile);
  242.                         return;
  243.                 }
  244.  
  245.                 *p++ = 0;
  246.                 n = count_commas(p) + 1;
  247.                 i = 0;
  248.                 while (i < n)
  249.                 {
  250.                         samples[i++] = fz_atof(p);
  251.                         p = strchr(p, ',');
  252.                         if (!p)
  253.                                 break;
  254.                         p ++;
  255.                         if (*p == ' ')
  256.                                 p ++;
  257.                 }
  258.                 while (i < n)
  259.                 {
  260.                         samples[i++] = 0;
  261.                 }
  262.  
  263.                 /* TODO: load ICC profile */
  264.                 switch (n)
  265.                 {
  266.                 case 2: *csp = fz_device_gray; break;
  267.                 case 4: *csp = fz_device_rgb; break;
  268.                 case 5: *csp = fz_device_cmyk; break;
  269.                 default: *csp = fz_device_gray; break;
  270.                 }
  271.         }
  272. }
  273.  
  274. void
  275. xps_set_color(xps_context *ctx, fz_colorspace *colorspace, float *samples)
  276. {
  277.         int i;
  278.         ctx->colorspace = colorspace;
  279.         for (i = 0; i < colorspace->n; i++)
  280.                 ctx->color[i] = samples[i + 1];
  281.         ctx->alpha = samples[0] * ctx->opacity[ctx->opacity_top];
  282. }
  283.