static void xps_load_links_in_glyphs(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 *bidi_level_att = fz_xml_att(root, "BidiLevel"); char *font_size_att = fz_xml_att(root, "FontRenderingEmSize"); char *font_uri_att = fz_xml_att(root, "FontUri"); char *origin_x_att = fz_xml_att(root, "OriginX"); char *origin_y_att = fz_xml_att(root, "OriginY"); char *is_sideways_att = fz_xml_att(root, "IsSideways"); char *indices_att = fz_xml_att(root, "Indices"); char *unicode_att = fz_xml_att(root, "UnicodeString"); char *style_att = fz_xml_att(root, "StyleSimulations"); int is_sideways = 0; int bidi_level = 0; fz_matrix local_ctm; fz_font *font; fz_text *text; fz_rect area; 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 (is_sideways_att) is_sideways = !strcmp(is_sideways_att, "true"); if (bidi_level_att) bidi_level = atoi(bidi_level_att); font = xps_lookup_font(ctx, doc, base_uri, font_uri_att, style_att); text = xps_parse_glyphs_imp(ctx, doc, &local_ctm, font, fz_atof(font_size_att), fz_atof(origin_x_att), fz_atof(origin_y_att), is_sideways, bidi_level, indices_att, unicode_att); fz_bound_text(ctx, text, NULL, &local_ctm, &area); fz_drop_text(ctx, text); fz_drop_font(ctx, font); xps_add_link(ctx, doc, &area, base_uri, navigate_uri_att, link); } }
void xps_parse_glyphs(fz_context *ctx, xps_document *doc, const fz_matrix *ctm, char *base_uri, xps_resource *dict, fz_xml *root) { fz_device *dev = doc->dev; fz_xml *node; char *fill_uri; char *opacity_mask_uri; char *bidi_level_att; char *fill_att; char *font_size_att; char *font_uri_att; char *origin_x_att; char *origin_y_att; char *is_sideways_att; char *indices_att; char *unicode_att; char *style_att; char *transform_att; char *clip_att; char *opacity_att; char *opacity_mask_att; char *navigate_uri_att; fz_xml *transform_tag = NULL; fz_xml *clip_tag = NULL; fz_xml *fill_tag = NULL; fz_xml *opacity_mask_tag = NULL; char *fill_opacity_att = NULL; xps_part *part; fz_font *font; char partname[1024]; char fakename[1024]; char *subfont; float font_size = 10; int subfontid = 0; int is_sideways = 0; int bidi_level = 0; fz_text *text; fz_rect area; fz_matrix local_ctm = *ctm; /* * Extract attributes and extended attributes. */ bidi_level_att = fz_xml_att(root, "BidiLevel"); fill_att = fz_xml_att(root, "Fill"); font_size_att = fz_xml_att(root, "FontRenderingEmSize"); font_uri_att = fz_xml_att(root, "FontUri"); origin_x_att = fz_xml_att(root, "OriginX"); origin_y_att = fz_xml_att(root, "OriginY"); is_sideways_att = fz_xml_att(root, "IsSideways"); indices_att = fz_xml_att(root, "Indices"); unicode_att = fz_xml_att(root, "UnicodeString"); style_att = fz_xml_att(root, "StyleSimulations"); transform_att = fz_xml_att(root, "RenderTransform"); clip_att = fz_xml_att(root, "Clip"); opacity_att = fz_xml_att(root, "Opacity"); opacity_mask_att = fz_xml_att(root, "OpacityMask"); navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri"); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { if (fz_xml_is_tag(node, "Glyphs.RenderTransform")) transform_tag = fz_xml_down(node); if (fz_xml_is_tag(node, "Glyphs.OpacityMask")) opacity_mask_tag = fz_xml_down(node); if (fz_xml_is_tag(node, "Glyphs.Clip")) clip_tag = fz_xml_down(node); if (fz_xml_is_tag(node, "Glyphs.Fill")) fill_tag = fz_xml_down(node); } fill_uri = base_uri; opacity_mask_uri = base_uri; xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL); xps_resolve_resource_reference(ctx, doc, dict, &clip_att, &clip_tag, NULL); xps_resolve_resource_reference(ctx, doc, dict, &fill_att, &fill_tag, &fill_uri); xps_resolve_resource_reference(ctx, doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); /* * Check that we have all the necessary information. */ if (!font_size_att || !font_uri_att || !origin_x_att || !origin_y_att) { fz_warn(ctx, "missing attributes in glyphs element"); return; } if (!indices_att && !unicode_att) return; /* nothing to draw */ if (is_sideways_att) is_sideways = !strcmp(is_sideways_att, "true"); if (bidi_level_att) bidi_level = atoi(bidi_level_att); /* * Find and load the font resource */ xps_resolve_url(ctx, doc, partname, base_uri, font_uri_att, sizeof partname); subfont = strrchr(partname, '#'); if (subfont) { subfontid = atoi(subfont + 1); *subfont = 0; } /* Make a new part name for font with style simulation applied */ fz_strlcpy(fakename, partname, sizeof fakename); if (style_att) { if (!strcmp(style_att, "BoldSimulation")) fz_strlcat(fakename, "#Bold", sizeof fakename); else if (!strcmp(style_att, "ItalicSimulation")) fz_strlcat(fakename, "#Italic", sizeof fakename); else if (!strcmp(style_att, "BoldItalicSimulation")) fz_strlcat(fakename, "#BoldItalic", sizeof fakename); } font = xps_lookup_font(ctx, doc, fakename); if (!font) { fz_buffer *buf = NULL; fz_var(buf); fz_try(ctx) { part = xps_read_part(ctx, doc, partname); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "cannot find font resource part '%s'", partname); return; } /* deobfuscate if necessary */ if (strstr(part->name, ".odttf")) xps_deobfuscate_font_resource(ctx, doc, part); if (strstr(part->name, ".ODTTF")) xps_deobfuscate_font_resource(ctx, doc, part); fz_try(ctx) { buf = fz_new_buffer_from_data(ctx, part->data, part->size); /* part->data is now owned by buf */ part->data = NULL; font = fz_new_font_from_buffer(ctx, NULL, buf, subfontid, 1); } fz_always(ctx) { fz_drop_buffer(ctx, buf); xps_drop_part(ctx, doc, part); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "cannot load font resource '%s'", partname); return; } if (style_att) { font->ft_bold = !!strstr(style_att, "Bold"); font->ft_italic = !!strstr(style_att, "Italic"); } xps_select_best_font_encoding(ctx, doc, font); xps_insert_font(ctx, doc, fakename, font); }