static void xps_parse_poly_line_segment(fz_context *doc, fz_path *path, fz_xml *root, int stroking, int *skipped_stroke) { char *points_att = fz_xml_att(root, "Points"); char *is_stroked_att = fz_xml_att(root, "IsStroked"); int is_stroked; float x, y; char *s; if (!points_att) { fz_warn(doc, "PolyLineSegment element has no points"); return; } is_stroked = 1; if (is_stroked_att && !strcmp(is_stroked_att, "false")) is_stroked = 0; if (!is_stroked) *skipped_stroke = 1; s = points_att; while (*s != 0) { while (*s == ' ') s++; s = xps_parse_point(s, &x, &y); if (stroking && !is_stroked) fz_moveto(doc, path, x, y); else fz_lineto(doc, path, x, y); } }
static void xps_load_links_in_path(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, char *base_uri, xps_resource *dict, fz_xml *root, fz_link **link) { char *navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri"); if (navigate_uri_att) { char *transform_att = fz_xml_att(root, "RenderTransform"); fz_xml *transform_tag = fz_xml_down(fz_xml_find_down(root, "Path.RenderTransform")); char *data_att = fz_xml_att(root, "Data"); fz_xml *data_tag = fz_xml_down(fz_xml_find_down(root, "Path.Data")); fz_path *path = NULL; int fill_rule; fz_matrix local_ctm; fz_rect area; xps_resolve_resource_reference(ctx, doc, dict, &data_att, &data_tag, NULL); xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL); xps_parse_transform(ctx, doc, transform_att, transform_tag, &local_ctm, ctm); if (data_att) path = xps_parse_abbreviated_geometry(ctx, doc, data_att, &fill_rule); else if (data_tag) path = xps_parse_path_geometry(ctx, doc, dict, data_tag, 0, &fill_rule); if (path) { fz_bound_path(ctx, path, NULL, &local_ctm, &area); fz_drop_path(ctx, path); xps_add_link(ctx, doc, &area, base_uri, navigate_uri_att, link); } } }
static void svg_run_ellipse(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, const svg_state *inherit_state) { svg_state local_state = *inherit_state; char *cx_att = fz_xml_att(node, "cx"); char *cy_att = fz_xml_att(node, "cy"); char *rx_att = fz_xml_att(node, "rx"); char *ry_att = fz_xml_att(node, "ry"); float cx = 0; float cy = 0; float rx = 0; float ry = 0; fz_path *path; svg_parse_common(ctx, doc, node, &local_state); if (cx_att) cx = svg_parse_length(cx_att, local_state.viewbox_w, local_state.fontsize); if (cy_att) cy = svg_parse_length(cy_att, local_state.viewbox_h, local_state.fontsize); if (rx_att) rx = svg_parse_length(rx_att, local_state.viewbox_w, local_state.fontsize); if (ry_att) ry = svg_parse_length(ry_att, local_state.viewbox_h, local_state.fontsize); if (rx <= 0 || ry <= 0) return; path = fz_new_path(ctx); approx_circle(ctx, path, cx, cy, rx, ry); svg_draw_path(ctx, dev, doc, path, &local_state); fz_drop_path(ctx, path); }
static void svg_run_line(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, const svg_state *inherit_state) { svg_state local_state = *inherit_state; char *x1_att = fz_xml_att(node, "x1"); char *y1_att = fz_xml_att(node, "y1"); char *x2_att = fz_xml_att(node, "x2"); char *y2_att = fz_xml_att(node, "y2"); float x1 = 0; float y1 = 0; float x2 = 0; float y2 = 0; svg_parse_common(ctx, doc, node, &local_state); if (x1_att) x1 = svg_parse_length(x1_att, local_state.viewbox_w, local_state.fontsize); if (y1_att) y1 = svg_parse_length(y1_att, local_state.viewbox_h, local_state.fontsize); if (x2_att) x2 = svg_parse_length(x2_att, local_state.viewbox_w, local_state.fontsize); if (y2_att) y2 = svg_parse_length(y2_att, local_state.viewbox_h, local_state.fontsize); if (local_state.stroke_is_set) { fz_path *path = fz_new_path(ctx); fz_moveto(ctx, path, x1, y1); fz_lineto(ctx, path, x2, y2); svg_stroke(ctx, dev, doc, path, &local_state); fz_drop_path(ctx, path); } }
/* svg, symbol, image, foreignObject establish new viewports */ void svg_parse_viewport(fz_context *ctx, svg_document *doc, fz_xml *node, svg_state *state) { //fz_matrix *transform = &state->transform; char *x_att = fz_xml_att(node, "x"); char *y_att = fz_xml_att(node, "y"); char *w_att = fz_xml_att(node, "width"); char *h_att = fz_xml_att(node, "height"); float x = 0; float y = 0; float w = state->viewport_w; float h = state->viewport_h; if (x_att) x = svg_parse_length(x_att, state->viewbox_w, state->fontsize); if (y_att) y = svg_parse_length(y_att, state->viewbox_h, state->fontsize); if (w_att) w = svg_parse_length(w_att, state->viewbox_w, state->fontsize); if (h_att) h = svg_parse_length(h_att, state->viewbox_h, state->fontsize); /* TODO: new transform */ fz_warn(ctx, "push viewport: %g %g %g %g", x, y, w, h); state->viewport_w = w; state->viewport_h = h; }
static void svg_run_use(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *root, const svg_state *inherit_state) { svg_state local_state = *inherit_state; char *xlink_href_att = fz_xml_att(root, "xlink:href"); char *x_att = fz_xml_att(root, "x"); char *y_att = fz_xml_att(root, "y"); float x = 0; float y = 0; svg_parse_common(ctx, doc, root, &local_state); if (x_att) x = svg_parse_length(x_att, local_state.viewbox_w, local_state.fontsize); if (y_att) y = svg_parse_length(y_att, local_state.viewbox_h, local_state.fontsize); fz_pre_translate(&local_state.transform, x, y); if (xlink_href_att && xlink_href_att[0] == '#') { fz_xml *linked = fz_tree_lookup(ctx, doc->idmap, xlink_href_att + 1); if (linked) { if (!strcmp(fz_xml_tag(linked), "symbol")) svg_run_use_symbol(ctx, dev, doc, root, linked, &local_state); else svg_run_element(ctx, dev, doc, linked, &local_state); return; } } fz_warn(ctx, "svg: cannot find linked symbol"); }
static void xps_draw_linear_gradient(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area, struct stop *stops, int count, fz_xml *root, int spread) { float x0, y0, x1, y1; int i, mi, ma; float dx, dy, x, y, k; fz_point p1, p2; fz_matrix inv; fz_rect local_area = *area; char *start_point_att = fz_xml_att(root, "StartPoint"); char *end_point_att = fz_xml_att(root, "EndPoint"); x0 = y0 = 0; x1 = y1 = 1; if (start_point_att) xps_parse_point(ctx, doc, start_point_att, &x0, &y0); if (end_point_att) xps_parse_point(ctx, doc, end_point_att, &x1, &y1); p1.x = x0; p1.y = y0; p2.x = x1; p2.y = y1; fz_transform_rect(&local_area, fz_invert_matrix(&inv, ctm)); x = p2.x - p1.x; y = p2.y - p1.y; k = ((local_area.x0 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y); mi = floorf(k); ma = ceilf(k); k = ((local_area.x1 - p1.x) * x + (local_area.y0 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); k = ((local_area.x0 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); k = ((local_area.x1 - p1.x) * x + (local_area.y1 - p1.y) * y) / (x * x + y * y); mi = fz_mini(mi, floorf(k)); ma = fz_maxi(ma, ceilf(k)); dx = x1 - x0; dy = y1 - y0; if (spread == SPREAD_REPEAT) { for (i = mi; i < ma; i++) xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy); } else if (spread == SPREAD_REFLECT) { if ((mi % 2) != 0) mi--; for (i = mi; i < ma; i += 2) { xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + i * dx, y0 + i * dy, x1 + i * dx, y1 + i * dy); xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 0, x0 + (i + 2) * dx, y0 + (i + 2) * dy, x1 + i * dx, y1 + i * dy); } } else { xps_draw_one_linear_gradient(ctx, doc, ctm, stops, count, 1, x0, y0, x1, y1); } }
static void xps_parse_path_figure(fz_context *doc, fz_path *path, fz_xml *root, int stroking) { fz_xml *node; char *is_closed_att; char *start_point_att; char *is_filled_att; int is_closed = 0; int is_filled = 1; float start_x = 0; float start_y = 0; int skipped_stroke = 0; is_closed_att = fz_xml_att(root, "IsClosed"); start_point_att = fz_xml_att(root, "StartPoint"); is_filled_att = fz_xml_att(root, "IsFilled"); if (is_closed_att) is_closed = !strcmp(is_closed_att, "true"); if (is_filled_att) is_filled = !strcmp(is_filled_att, "true"); if (start_point_att) xps_parse_point(start_point_att, &start_x, &start_y); if (!stroking && !is_filled) /* not filled, when filling */ return; fz_moveto(doc, path, start_x, start_y); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { if (!strcmp(fz_xml_tag(node), "ArcSegment")) xps_parse_arc_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(fz_xml_tag(node), "PolyBezierSegment")) xps_parse_poly_bezier_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(fz_xml_tag(node), "PolyLineSegment")) xps_parse_poly_line_segment(doc, path, node, stroking, &skipped_stroke); if (!strcmp(fz_xml_tag(node), "PolyQuadraticBezierSegment")) xps_parse_poly_quadratic_bezier_segment(doc, path, node, stroking, &skipped_stroke); } if (is_closed) { if (stroking && skipped_stroke) fz_lineto(doc, path, start_x, start_y); /* we've skipped using fz_moveto... */ else fz_closepath(doc, path); /* no skipped segments, safe to closepath properly */ } }
static void xps_parse_metadata_imp(fz_context *ctx, xps_document *doc, fz_xml *item, xps_fixdoc *fixdoc) { while (item) { if (fz_xml_is_tag(item, "Relationship")) { char *target = fz_xml_att(item, "Target"); char *type = fz_xml_att(item, "Type"); if (target && type) { char tgtbuf[1024]; xps_resolve_url(ctx, doc, tgtbuf, doc->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART) || !strcmp(type, REL_START_PART_OXPS)) doc->start_part = fz_strdup(ctx, tgtbuf); if ((!strcmp(type, REL_DOC_STRUCTURE) || !strcmp(type, REL_DOC_STRUCTURE_OXPS)) && fixdoc) fixdoc->outline = fz_strdup(ctx, tgtbuf); if (!fz_xml_att(item, "Id")) fz_warn(ctx, "missing relationship id for %s", target); } } if (fz_xml_is_tag(item, "DocumentReference")) { char *source = fz_xml_att(item, "Source"); if (source) { char srcbuf[1024]; xps_resolve_url(ctx, doc, srcbuf, doc->base_uri, source, sizeof srcbuf); xps_add_fixed_document(ctx, doc, srcbuf); } } if (fz_xml_is_tag(item, "PageContent")) { char *source = fz_xml_att(item, "Source"); char *width_att = fz_xml_att(item, "Width"); char *height_att = fz_xml_att(item, "Height"); int width = width_att ? atoi(width_att) : 0; int height = height_att ? atoi(height_att) : 0; if (source) { char srcbuf[1024]; xps_resolve_url(ctx, doc, srcbuf, doc->base_uri, source, sizeof srcbuf); xps_add_fixed_page(ctx, doc, srcbuf, width, height); } } if (fz_xml_is_tag(item, "LinkTarget")) { char *name = fz_xml_att(item, "Name"); if (name) xps_add_link_target(ctx, doc, name); } xps_parse_metadata_imp(ctx, doc, fz_xml_down(item), fixdoc); item = fz_xml_next(item); } }
static void xps_parse_poly_quadratic_bezier_segment(fz_context *doc, fz_path *path, fz_xml *root, int stroking, int *skipped_stroke) { char *points_att = fz_xml_att(root, "Points"); char *is_stroked_att = fz_xml_att(root, "IsStroked"); float x[2], y[2]; int is_stroked; fz_point pt; char *s; int n; if (!points_att) { fz_warn(doc, "PolyQuadraticBezierSegment element has no points"); return; } is_stroked = 1; if (is_stroked_att && !strcmp(is_stroked_att, "false")) is_stroked = 0; if (!is_stroked) *skipped_stroke = 1; s = points_att; n = 0; while (*s != 0) { while (*s == ' ') s++; s = xps_parse_point(s, &x[n], &y[n]); n ++; if (n == 2) { if (stroking && !is_stroked) { fz_moveto(doc, path, x[1], y[1]); } else { pt = fz_currentpoint(doc, path); fz_curveto(doc, path, (pt.x + 2 * x[0]) / 3, (pt.y + 2 * y[0]) / 3, (x[1] + 2 * x[0]) / 3, (y[1] + 2 * y[0]) / 3, x[1], y[1]); } n = 0; } } }
void xps_parse_visual_brush(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, fz_xml *root) { fz_xml *node; char *visual_uri; char *visual_att; fz_xml *visual_tag = NULL; visual_att = fz_xml_att(root, "Visual"); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { if (fz_xml_is_tag(node, "VisualBrush.Visual")) visual_tag = fz_xml_down(node); } visual_uri = base_uri; xps_resolve_resource_reference(ctx, doc, dict, &visual_att, &visual_tag, &visual_uri); if (visual_tag) { xps_parse_tiling_brush(ctx, doc, ctm, area, visual_uri, dict, root, xps_paint_visual_brush, visual_tag); } }
static fz_outline * epub_parse_ncx_imp(fz_context *ctx, epub_document *doc, fz_xml *node, char *base_uri) { char path[2048]; fz_outline *outline, *head, **tailp; head = NULL; tailp = &head; node = fz_xml_find_down(node, "navPoint"); while (node) { char *text = fz_xml_text(fz_xml_down(fz_xml_find_down(fz_xml_find_down(node, "navLabel"), "text"))); char *content = fz_xml_att(fz_xml_find_down(node, "content"), "src"); if (text && content) { fz_strlcpy(path, base_uri, sizeof path); fz_strlcat(path, "/", sizeof path); fz_strlcat(path, content, sizeof path); fz_urldecode(path); fz_cleanname(path); *tailp = outline = fz_new_outline(ctx); tailp = &(*tailp)->next; outline->title = fz_strdup(ctx, text); outline->uri = fz_strdup(ctx, path); outline->page = -1; outline->down = epub_parse_ncx_imp(ctx, doc, node, base_uri); } node = fz_xml_find_next(node, "navPoint"); } return head; }
static const char * rel_path_from_idref(fz_xml *manifest, const char *idref) { fz_xml *item; if (!idref) return NULL; item = fz_xml_find_down(manifest, "item"); while (item) { const char *id = fz_xml_att(item, "id"); if (id && !strcmp(id, idref)) return fz_xml_att(item, "href"); item = fz_xml_find_next(item, "item"); } return NULL; }
static int match_id_condition(fz_xml *node, const char *p) { const char *s = fz_xml_att(node, "id"); if (s && !strcmp(s, p)) return 1; return 0; }
static fz_css_rule * html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rule *css, fz_xml *root) { fz_xml *node; fz_buffer *buf; char path[2048]; for (node = root; node; node = fz_xml_next(node)) { const char *tag = fz_xml_tag(node); if (tag && !strcmp(tag, "link")) { char *rel = fz_xml_att(node, "rel"); if (rel && !fz_strcasecmp(rel, "stylesheet")) { char *type = fz_xml_att(node, "type"); if ((type && !strcmp(type, "text/css")) || !type) { char *href = fz_xml_att(node, "href"); if (href) { fz_strlcpy(path, base_uri, sizeof path); fz_strlcat(path, "/", sizeof path); fz_strlcat(path, href, sizeof path); fz_cleanname(path); buf = fz_read_archive_entry(ctx, zip, path); fz_write_buffer_byte(ctx, buf, 0); css = fz_parse_css(ctx, css, (char*)buf->data, path); fz_drop_buffer(ctx, buf); } } } } if (tag && !strcmp(tag, "style")) { char *s = concat_text(ctx, node); css = fz_parse_css(ctx, css, s, "<style>"); fz_free(ctx, s); } if (fz_xml_down(node)) css = html_load_css(ctx, zip, base_uri, css, fz_xml_down(node)); } return css; }
void xps_begin_opacity(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, const fz_rect *area, char *base_uri, xps_resource *dict, char *opacity_att, fz_xml *opacity_mask_tag) { fz_device *dev = doc->dev; float opacity; if (!opacity_att && !opacity_mask_tag) return; opacity = 1; if (opacity_att) opacity = fz_atof(opacity_att); if (opacity_mask_tag && !strcmp(fz_xml_tag(opacity_mask_tag), "SolidColorBrush")) { char *scb_opacity_att = fz_xml_att(opacity_mask_tag, "Opacity"); char *scb_color_att = fz_xml_att(opacity_mask_tag, "Color"); if (scb_opacity_att) opacity = opacity * fz_atof(scb_opacity_att); if (scb_color_att) { fz_colorspace *colorspace; float samples[FZ_MAX_COLORS]; xps_parse_color(ctx, doc, base_uri, scb_color_att, &colorspace, samples); opacity = opacity * samples[0]; } opacity_mask_tag = NULL; } if (doc->opacity_top + 1 < nelem(doc->opacity)) { doc->opacity[doc->opacity_top + 1] = doc->opacity[doc->opacity_top] * opacity; doc->opacity_top++; } if (opacity_mask_tag) { fz_begin_mask(ctx, dev, area, 0, NULL, NULL); xps_parse_brush(ctx, doc, ctm, area, base_uri, dict, opacity_mask_tag); fz_end_mask(ctx, dev); } }
static fz_css_rule * html_load_css(fz_context *ctx, fz_archive *zip, const char *base_uri, fz_css_rule *css, fz_xml *root) { fz_xml *html, *head, *node; fz_buffer *buf; char path[2048]; fz_var(buf); html = fz_xml_find(root, "html"); head = fz_xml_find_down(html, "head"); for (node = fz_xml_down(head); node; node = fz_xml_next(node)) { if (fz_xml_is_tag(node, "link")) { char *rel = fz_xml_att(node, "rel"); if (rel && !fz_strcasecmp(rel, "stylesheet")) { char *type = fz_xml_att(node, "type"); if ((type && !strcmp(type, "text/css")) || !type) { char *href = fz_xml_att(node, "href"); if (href) { fz_strlcpy(path, base_uri, sizeof path); fz_strlcat(path, "/", sizeof path); fz_strlcat(path, href, sizeof path); fz_urldecode(path); fz_cleanname(path); buf = NULL; fz_try(ctx) { buf = fz_read_archive_entry(ctx, zip, path); fz_write_buffer_byte(ctx, buf, 0); css = fz_parse_css(ctx, css, (char*)buf->data, path); } fz_always(ctx) fz_drop_buffer(ctx, buf); fz_catch(ctx) fz_warn(ctx, "ignoring stylesheet %s", path); } } }
void svg_parse_document_bounds(fz_context *ctx, svg_document *doc, fz_xml *root) { char *version_att; char *w_att; char *h_att; char *viewbox_att; int version; if (!fz_xml_is_tag(root, "svg")) fz_throw(ctx, FZ_ERROR_GENERIC, "expected svg element (found %s)", fz_xml_tag(root)); version_att = fz_xml_att(root, "version"); w_att = fz_xml_att(root, "width"); h_att = fz_xml_att(root, "height"); viewbox_att = fz_xml_att(root, "viewBox"); version = 10; if (version_att) version = fz_atof(version_att) * 10; if (version > 12) fz_warn(ctx, "svg document version is newer than we support"); /* If no width or height attributes, then guess from the viewbox */ if (w_att == NULL && h_att == NULL && viewbox_att != NULL) { float min_x, min_y, box_w, box_h; sscanf(viewbox_att, "%g %g %g %g", &min_x, &min_y, &box_w, &box_h); doc->width = box_w; doc->height = box_h; } else { doc->width = DEF_WIDTH; if (w_att) doc->width = svg_parse_length(w_att, doc->width, DEF_FONTSIZE); doc->height = DEF_HEIGHT; if (h_att) doc->height = svg_parse_length(h_att, doc->height, DEF_FONTSIZE); } }
fz_xml * xps_lookup_alternate_content(fz_context *ctx, xps_document *doc, fz_xml *node) { for (node = fz_xml_down(node); node; node = fz_xml_next(node)) { if (fz_xml_is_tag(node, "Choice") && fz_xml_att(node, "Requires")) { char list[64]; char *next = list, *item; fz_strlcpy(list, fz_xml_att(node, "Requires"), sizeof(list)); while ((item = fz_strsep(&next, " \t\r\n")) != NULL && (!*item || !strcmp(item, "xps"))); if (!item) return fz_xml_down(node); } else if (fz_xml_is_tag(node, "Fallback")) return fz_xml_down(node); } return NULL; }
static void svg_build_id_map(fz_context *ctx, svg_document *doc, fz_xml *root) { fz_xml *node; char *id_att = fz_xml_att(root, "id"); if (id_att) doc->idmap = fz_tree_insert(ctx, doc->idmap, id_att, root); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) svg_build_id_map(ctx, doc, node); }
static void xps_parse_poly_bezier_segment(fz_context *doc, fz_path *path, fz_xml *root, int stroking, int *skipped_stroke) { char *points_att = fz_xml_att(root, "Points"); char *is_stroked_att = fz_xml_att(root, "IsStroked"); float x[3], y[3]; int is_stroked; char *s; int n; if (!points_att) { fz_warn(doc, "PolyBezierSegment element has no points"); return; } is_stroked = 1; if (is_stroked_att && !strcmp(is_stroked_att, "false")) is_stroked = 0; if (!is_stroked) *skipped_stroke = 1; s = points_att; n = 0; while (*s != 0) { while (*s == ' ') s++; s = xps_parse_point(s, &x[n], &y[n]); n ++; if (n == 3) { if (stroking && !is_stroked) fz_moveto(doc, path, x[2], y[2]); else fz_curveto(doc, path, x[0], y[0], x[1], y[1], x[2], y[2]); n = 0; } } }
void xps_parse_matrix_transform(xps_document *doc, fz_xml *root, fz_matrix *matrix) { char *transform; *matrix = fz_identity; if (!strcmp(fz_xml_tag(root), "MatrixTransform")) { transform = fz_xml_att(root, "Matrix"); if (transform) xps_parse_render_transform(doc, transform, matrix); } }
static void xps_parse_matrix_transform(fz_context *ctx, xps_document *doc, fz_xml *root, fz_matrix *matrix) { char *transform; *matrix = fz_identity; if (fz_xml_is_tag(root, "MatrixTransform")) { transform = fz_xml_att(root, "Matrix"); if (transform) xps_parse_render_transform(ctx, doc, transform, matrix); } }
static void xps_load_links_in_canvas(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, char *base_uri, xps_resource *dict, fz_xml *root, fz_link **link) { xps_resource *new_dict = NULL; fz_matrix local_ctm; fz_xml *node; char *navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri"); char *transform_att = fz_xml_att(root, "RenderTransform"); fz_xml *transform_tag = fz_xml_down(fz_xml_find_down(root, "Canvas.RenderTransform")); fz_xml *resource_tag = fz_xml_down(fz_xml_find_down(root, "Canvas.Resources")); if (resource_tag) { new_dict = xps_parse_resource_dictionary(ctx, doc, base_uri, resource_tag); if (new_dict) { new_dict->parent = dict; dict = new_dict; } } xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL); xps_parse_transform(ctx, doc, transform_att, transform_tag, &local_ctm, ctm); if (navigate_uri_att) fz_warn(ctx, "FixedPage.NavigateUri attribute on Canvas element"); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) xps_load_links_in_element(ctx, doc, &local_ctm, base_uri, dict, node, link); if (new_dict) xps_drop_resource_dictionary(ctx, doc, new_dict); }
xps_resource * xps_parse_resource_dictionary(fz_context *ctx, xps_document *doc, char *base_uri, fz_xml *root) { xps_resource *head; xps_resource *entry; fz_xml *node; char *source; char *key; source = fz_xml_att(root, "Source"); if (source) return xps_parse_remote_resource_dictionary(ctx, doc, base_uri, source); head = NULL; for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { key = fz_xml_att(node, "x:Key"); if (key) { entry = fz_malloc_struct(ctx, xps_resource); entry->name = key; entry->base_uri = NULL; entry->base_xml = NULL; entry->data = node; entry->next = head; entry->parent = NULL; head = entry; } } if (head) head->base_uri = fz_strdup(ctx, base_uri); return head; }
static int match_class_condition(fz_xml *node, const char *p) { const char *s = fz_xml_att(node, "class"); char buf[1024]; if (s) { strcpy(buf, s); s = strtok(buf, " "); while (s) { if (!strcmp(s, p)) return 1; s = strtok(NULL, " "); } } return 0; }
void fz_match_css(fz_context *ctx, fz_css_match *match, fz_css_rule *css, fz_xml *node) { fz_css_rule *rule; fz_css_selector *sel; fz_css_property *prop, *head, *tail; const char *s; for (rule = css; rule; rule = rule->next) { sel = rule->selector; while (sel) { if (match_selector(sel, node)) { for (prop = rule->declaration; prop; prop = prop->next) add_property(match, prop->name, prop->value, selector_specificity(sel, prop->important)); break; } sel = sel->next; } } s = fz_xml_att(node, "style"); if (s) { fz_try(ctx) { head = tail = prop = fz_parse_css_properties(ctx, s); while (prop) { add_property(match, prop->name, prop->value, INLINE_SPECIFICITY); tail = prop; prop = prop->next; } if (tail) tail->next = css->garbage; css->garbage = head; } fz_catch(ctx) { fz_warn(ctx, "ignoring style attribute"); } } sort_properties(match); /* speed up subsequent value_from_raw_property lookups */ }
static fz_path * svg_parse_polygon_imp(fz_context *ctx, svg_document *doc, fz_xml *node, int doclose) { fz_path *path; const char *str = fz_xml_att(node, "points"); float number; float args[2]; int nargs; int isfirst; if (!str) return NULL; isfirst = 1; nargs = 0; path = fz_new_path(ctx); while (*str) { while (svg_is_whitespace_or_comma(*str)) str ++; if (svg_is_digit(*str)) { str = svg_lex_number(&number, str); args[nargs++] = number; } if (nargs == 2) { if (isfirst) { fz_moveto(ctx, path, args[0], args[1]); isfirst = 0; } else { fz_lineto(ctx, path, args[0], args[1]); } nargs = 0; } } return path; }
/* svg, symbol, image, foreignObject plus marker, pattern, view can use viewBox to set the transform */ void svg_parse_viewbox(fz_context *ctx, svg_document *doc, fz_xml *node, svg_state *state) { //fz_matrix *transform = &state->transform; //float port_w = state->viewport_w; //float port_h = state->viewport_h; float min_x, min_y, box_w, box_h; char *viewbox_att = fz_xml_att(node, "viewBox"); if (viewbox_att) { sscanf(viewbox_att, "%g %g %g %g", &min_x, &min_y, &box_w, &box_h); /* scale and translate to fit [x y w h] to [0 0 viewport.w viewport.h] */ fz_warn(ctx, "push viewbox: %g %g %g %g", min_x, min_y, box_w, box_h); } }
static void svg_run_path(fz_context *ctx, fz_device *dev, svg_document *doc, fz_xml *node, const svg_state *inherit_state) { svg_state local_state = *inherit_state; const char *d_att = fz_xml_att(node, "d"); /* unused: char *path_length_att = fz_xml_att(node, "pathLength"); */ svg_parse_common(ctx, doc, node, &local_state); if (d_att) { fz_path *path = svg_parse_path_data(ctx, doc, d_att); svg_draw_path(ctx, dev, doc, path, &local_state); fz_drop_path(ctx, path); } }