Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. #define TILE
  5.  
  6. /*
  7.  * Parse a tiling brush (visual and image brushes at this time) common
  8.  * properties. Use the callback to draw the individual tiles.
  9.  */
  10.  
  11. enum { TILE_NONE, TILE_TILE, TILE_FLIP_X, TILE_FLIP_Y, TILE_FLIP_X_Y };
  12.  
  13. struct closure
  14. {
  15.         char *base_uri;
  16.         xps_resource *dict;
  17.         xml_element *root;
  18.         void *user;
  19.         void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*);
  20. };
  21.  
  22. static void
  23. xps_paint_tiling_brush_clipped(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, struct closure *c)
  24. {
  25.         fz_path *path = fz_new_path();
  26.         fz_moveto(path, viewbox.x0, viewbox.y0);
  27.         fz_lineto(path, viewbox.x0, viewbox.y1);
  28.         fz_lineto(path, viewbox.x1, viewbox.y1);
  29.         fz_lineto(path, viewbox.x1, viewbox.y0);
  30.         fz_closepath(path);
  31.         fz_clip_path(ctx->dev, path, NULL, 0, ctm);
  32.         fz_free_path(path);
  33.         c->func(ctx, ctm, viewbox, c->base_uri, c->dict, c->root, c->user);
  34.         fz_pop_clip(ctx->dev);
  35. }
  36.  
  37. static void
  38. xps_paint_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect viewbox, int tile_mode, struct closure *c)
  39. {
  40.         fz_matrix ttm;
  41.  
  42.         xps_paint_tiling_brush_clipped(ctx, ctm, viewbox, c);
  43.  
  44.         if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
  45.         {
  46.                 ttm = fz_concat(fz_translate(viewbox.x1 * 2, 0), ctm);
  47.                 ttm = fz_concat(fz_scale(-1, 1), ttm);
  48.                 xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c);
  49.         }
  50.  
  51.         if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
  52.         {
  53.                 ttm = fz_concat(fz_translate(0, viewbox.y1 * 2), ctm);
  54.                 ttm = fz_concat(fz_scale(1, -1), ttm);
  55.                 xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c);
  56.         }
  57.  
  58.         if (tile_mode == TILE_FLIP_X_Y)
  59.         {
  60.                 ttm = fz_concat(fz_translate(viewbox.x1 * 2, viewbox.y1 * 2), ctm);
  61.                 ttm = fz_concat(fz_scale(-1, -1), ttm);
  62.                 xps_paint_tiling_brush_clipped(ctx, ttm, viewbox, c);
  63.         }
  64. }
  65.  
  66. void
  67. xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
  68.         char *base_uri, xps_resource *dict, xml_element *root,
  69.         void (*func)(xps_context*, fz_matrix, fz_rect, char*, xps_resource*, xml_element*, void*), void *user)
  70. {
  71.         xml_element *node;
  72.         struct closure c;
  73.  
  74.         char *opacity_att;
  75.         char *transform_att;
  76.         char *viewbox_att;
  77.         char *viewport_att;
  78.         char *tile_mode_att;
  79.         char *viewbox_units_att;
  80.         char *viewport_units_att;
  81.  
  82.         xml_element *transform_tag = NULL;
  83.  
  84.         fz_matrix transform;
  85.         fz_rect viewbox;
  86.         fz_rect viewport;
  87.         float xstep, ystep;
  88.         float xscale, yscale;
  89.         int tile_mode;
  90.  
  91.         opacity_att = xml_att(root, "Opacity");
  92.         transform_att = xml_att(root, "Transform");
  93.         viewbox_att = xml_att(root, "Viewbox");
  94.         viewport_att = xml_att(root, "Viewport");
  95.         tile_mode_att = xml_att(root, "TileMode");
  96.         viewbox_units_att = xml_att(root, "ViewboxUnits");
  97.         viewport_units_att = xml_att(root, "ViewportUnits");
  98.  
  99.         c.base_uri = base_uri;
  100.         c.dict = dict;
  101.         c.root = root;
  102.         c.user = user;
  103.         c.func = func;
  104.  
  105.         for (node = xml_down(root); node; node = xml_next(node))
  106.         {
  107.                 if (!strcmp(xml_tag(node), "ImageBrush.Transform"))
  108.                         transform_tag = xml_down(node);
  109.                 if (!strcmp(xml_tag(node), "VisualBrush.Transform"))
  110.                         transform_tag = xml_down(node);
  111.         }
  112.  
  113.         xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);
  114.  
  115.         transform = fz_identity;
  116.         if (transform_att)
  117.                 xps_parse_render_transform(ctx, transform_att, &transform);
  118.         if (transform_tag)
  119.                 xps_parse_matrix_transform(ctx, transform_tag, &transform);
  120.         ctm = fz_concat(transform, ctm);
  121.  
  122.         viewbox = fz_unit_rect;
  123.         if (viewbox_att)
  124.                 xps_parse_rectangle(ctx, viewbox_att, &viewbox);
  125.  
  126.         viewport = fz_unit_rect;
  127.         if (viewport_att)
  128.                 xps_parse_rectangle(ctx, viewport_att, &viewport);
  129.  
  130.         /* some sanity checks on the viewport/viewbox size */
  131.         if (fabsf(viewport.x1 - viewport.x0) < 0.01f) return;
  132.         if (fabsf(viewport.y1 - viewport.y0) < 0.01f) return;
  133.         if (fabsf(viewbox.x1 - viewbox.x0) < 0.01f) return;
  134.         if (fabsf(viewbox.y1 - viewbox.y0) < 0.01f) return;
  135.  
  136.         xstep = viewbox.x1 - viewbox.x0;
  137.         ystep = viewbox.y1 - viewbox.y0;
  138.  
  139.         xscale = (viewport.x1 - viewport.x0) / xstep;
  140.         yscale = (viewport.y1 - viewport.y0) / ystep;
  141.  
  142.         tile_mode = TILE_NONE;
  143.         if (tile_mode_att)
  144.         {
  145.                 if (!strcmp(tile_mode_att, "None"))
  146.                         tile_mode = TILE_NONE;
  147.                 if (!strcmp(tile_mode_att, "Tile"))
  148.                         tile_mode = TILE_TILE;
  149.                 if (!strcmp(tile_mode_att, "FlipX"))
  150.                         tile_mode = TILE_FLIP_X;
  151.                 if (!strcmp(tile_mode_att, "FlipY"))
  152.                         tile_mode = TILE_FLIP_Y;
  153.                 if (!strcmp(tile_mode_att, "FlipXY"))
  154.                         tile_mode = TILE_FLIP_X_Y;
  155.         }
  156.  
  157.         if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
  158.                 xstep *= 2;
  159.         if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
  160.                 ystep *= 2;
  161.  
  162.         xps_begin_opacity(ctx, ctm, area, base_uri, dict, opacity_att, NULL);
  163.  
  164.         ctm = fz_concat(fz_translate(viewport.x0, viewport.y0), ctm);
  165.         ctm = fz_concat(fz_scale(xscale, yscale), ctm);
  166.         ctm = fz_concat(fz_translate(-viewbox.x0, -viewbox.y0), ctm);
  167.  
  168.         if (tile_mode != TILE_NONE)
  169.         {
  170.                 int x0, y0, x1, y1;
  171.                 fz_matrix invctm = fz_invert_matrix(ctm);
  172.                 area = fz_transform_rect(invctm, area);
  173.                 x0 = floorf(area.x0 / xstep);
  174.                 y0 = floorf(area.y0 / ystep);
  175.                 x1 = ceilf(area.x1 / xstep);
  176.                 y1 = ceilf(area.y1 / ystep);
  177.  
  178. #ifdef TILE
  179.                 {
  180.                         int n = (x1 - x0) * (y1 - y0);
  181.                         fz_rect bigview = viewbox;
  182.                         bigview.x1 = bigview.x0 + xstep;
  183.                         bigview.y1 = bigview.y0 + ystep;
  184.                         if (n > 1)
  185.                                 fz_begin_tile(ctx->dev, area, bigview, xstep, ystep, ctm);
  186.                         if (n > 0)
  187.                                 xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c);
  188.                         if (n > 1)
  189.                                 fz_end_tile(ctx->dev);
  190.                 }
  191. #else
  192.                 {
  193.                         int x, y;
  194.                         for (y = y0; y < y1; y++)
  195.                         {
  196.                                 for (x = x0; x < x1; x++)
  197.                                 {
  198.                                         fz_matrix ttm = fz_concat(fz_translate(xstep * x, ystep * y), ctm);
  199.                                         xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c);
  200.                                 }
  201.                         }
  202.                 }
  203. #endif
  204.         }
  205.         else
  206.         {
  207.                 xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c);
  208.         }
  209.  
  210.         xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);
  211. }
  212.  
  213. static void
  214. xps_paint_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
  215.         char *base_uri, xps_resource *dict, xml_element *root, void *visual_tag)
  216. {
  217.         xps_parse_element(ctx, ctm, area, base_uri, dict, (xml_element *)visual_tag);
  218. }
  219.  
  220. void
  221. xps_parse_visual_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
  222.         char *base_uri, xps_resource *dict, xml_element *root)
  223. {
  224.         xml_element *node;
  225.  
  226.         char *visual_uri;
  227.         char *visual_att;
  228.         xml_element *visual_tag = NULL;
  229.  
  230.         visual_att = xml_att(root, "Visual");
  231.  
  232.         for (node = xml_down(root); node; node = xml_next(node))
  233.         {
  234.                 if (!strcmp(xml_tag(node), "VisualBrush.Visual"))
  235.                         visual_tag = xml_down(node);
  236.         }
  237.  
  238.         visual_uri = base_uri;
  239.         xps_resolve_resource_reference(ctx, dict, &visual_att, &visual_tag, &visual_uri);
  240.  
  241.         if (visual_tag)
  242.         {
  243.                 xps_parse_tiling_brush(ctx, ctm, area,
  244.                         visual_uri, dict, root, xps_paint_visual_brush, visual_tag);
  245.         }
  246. }
  247.  
  248. void
  249. xps_parse_canvas(xps_context *ctx, fz_matrix ctm, fz_rect area, char *base_uri, xps_resource *dict, xml_element *root)
  250. {
  251.         xps_resource *new_dict = NULL;
  252.         xml_element *node;
  253.         char *opacity_mask_uri;
  254.         int code;
  255.  
  256.         char *transform_att;
  257.         char *clip_att;
  258.         char *opacity_att;
  259.         char *opacity_mask_att;
  260.  
  261.         xml_element *transform_tag = NULL;
  262.         xml_element *clip_tag = NULL;
  263.         xml_element *opacity_mask_tag = NULL;
  264.  
  265.         fz_matrix transform;
  266.  
  267.         transform_att = xml_att(root, "RenderTransform");
  268.         clip_att = xml_att(root, "Clip");
  269.         opacity_att = xml_att(root, "Opacity");
  270.         opacity_mask_att = xml_att(root, "OpacityMask");
  271.  
  272.         for (node = xml_down(root); node; node = xml_next(node))
  273.         {
  274.                 if (!strcmp(xml_tag(node), "Canvas.Resources") && xml_down(node))
  275.                 {
  276.                         code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xml_down(node));
  277.                         if (code)
  278.                                 fz_catch(code, "cannot load Canvas.Resources");
  279.                         else
  280.                         {
  281.                                 new_dict->parent = dict;
  282.                                 dict = new_dict;
  283.                         }
  284.                 }
  285.  
  286.                 if (!strcmp(xml_tag(node), "Canvas.RenderTransform"))
  287.                         transform_tag = xml_down(node);
  288.                 if (!strcmp(xml_tag(node), "Canvas.Clip"))
  289.                         clip_tag = xml_down(node);
  290.                 if (!strcmp(xml_tag(node), "Canvas.OpacityMask"))
  291.                         opacity_mask_tag = xml_down(node);
  292.         }
  293.  
  294.         opacity_mask_uri = base_uri;
  295.         xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);
  296.         xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL);
  297.         xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);
  298.  
  299.         transform = fz_identity;
  300.         if (transform_att)
  301.                 xps_parse_render_transform(ctx, transform_att, &transform);
  302.         if (transform_tag)
  303.                 xps_parse_matrix_transform(ctx, transform_tag, &transform);
  304.         ctm = fz_concat(transform, ctm);
  305.  
  306.         if (clip_att || clip_tag)
  307.                 xps_clip(ctx, ctm, dict, clip_att, clip_tag);
  308.  
  309.         xps_begin_opacity(ctx, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
  310.  
  311.         for (node = xml_down(root); node; node = xml_next(node))
  312.         {
  313.                 xps_parse_element(ctx, ctm, area, base_uri, dict, node);
  314.         }
  315.  
  316.         xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
  317.  
  318.         if (clip_att || clip_tag)
  319.                 fz_pop_clip(ctx->dev);
  320.  
  321.         if (new_dict)
  322.                 xps_free_resource_dictionary(ctx, new_dict);
  323. }
  324.  
  325. void
  326. xps_parse_fixed_page(xps_context *ctx, fz_matrix ctm, xps_page *page)
  327. {
  328.         xml_element *node;
  329.         xps_resource *dict;
  330.         char base_uri[1024];
  331.         fz_rect area;
  332.         char *s;
  333.         int code;
  334.  
  335.         fz_strlcpy(base_uri, page->name, sizeof base_uri);
  336.         s = strrchr(base_uri, '/');
  337.         if (s)
  338.                 s[1] = 0;
  339.  
  340.         dict = NULL;
  341.  
  342.         ctx->opacity_top = 0;
  343.         ctx->opacity[0] = 1;
  344.  
  345.         if (!page->root)
  346.                 return;
  347.  
  348.         area = fz_transform_rect(fz_scale(page->width, page->height), fz_unit_rect);
  349.  
  350.         for (node = xml_down(page->root); node; node = xml_next(node))
  351.         {
  352.                 if (!strcmp(xml_tag(node), "FixedPage.Resources") && xml_down(node))
  353.                 {
  354.                         code = xps_parse_resource_dictionary(ctx, &dict, base_uri, xml_down(node));
  355.                         if (code)
  356.                                 fz_catch(code, "cannot load FixedPage.Resources");
  357.                 }
  358.                 xps_parse_element(ctx, ctm, area, base_uri, dict, node);
  359.         }
  360.  
  361.         if (dict)
  362.         {
  363.                 xps_free_resource_dictionary(ctx, dict);
  364.         }
  365. }
  366.