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 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 fz_css_condition *fz_new_css_condition(fz_context *ctx, int type, const char *key, const char *val) { fz_css_condition *cond = fz_malloc_struct(ctx, fz_css_condition); cond->type = type; cond->key = key ? fz_strdup(ctx, key) : NULL; cond->val = val ? fz_strdup(ctx, val) : NULL; cond->next = NULL; return cond; }
static xps_outline * xps_new_outline(char *title, char *target) { xps_outline *outline = fz_malloc(sizeof(xps_outline)); outline->title = fz_strdup(title); outline->target = fz_strdup(target); outline->next = NULL; outline->child = NULL; return outline; }
static fz_outline * xps_parse_document_outline(xps_context *ctx, xml_element *root) { xml_element *node; fz_outline *head = NULL, *entry, *tail; int last_level = 1, this_level; for (node = xml_down(root); node; node = xml_next(node)) { if (!strcmp(xml_tag(node), "OutlineEntry")) { char *level = xml_att(node, "OutlineLevel"); char *target = xml_att(node, "OutlineTarget"); char *description = xml_att(node, "Description"); /* SumatraPDF: allow target-less outline entries */ if (!description) continue; entry = fz_malloc(ctx->ctx, sizeof *entry); entry->title = fz_strdup(ctx->ctx, description); entry->page = -1; /* SumatraPDF: extended outline actions */ entry->data = target ? fz_strdup(ctx->ctx, target) : NULL; if (target && !xps_is_external_uri(target)) entry->page = xps_find_link_target(ctx, target); entry->free_data = fz_free; entry->down = NULL; entry->next = NULL; this_level = level ? atoi(level) : 1; entry->is_open = this_level == 1; /* SumatraPDF: support expansion states */ if (!head) { head = entry; } else { tail = xps_find_last_outline_at_level(head, 1, this_level); if (this_level > last_level) tail->down = entry; else tail->next = entry; } last_level = this_level; } } return head; }
static void xps_add_fixed_page(xps_context *ctx, char *name, int width, int height) { xps_page *page; /* Check for duplicates first */ for (page = ctx->first_page; page; page = page->next) if (!strcmp(page->name, name)) return; page = fz_malloc(sizeof(xps_page)); page->name = fz_strdup(name); page->width = width; page->height = height; page->root = NULL; page->next = NULL; if (!ctx->first_page) { ctx->first_page = page; ctx->last_page = page; } else { ctx->last_page->next = page; ctx->last_page = page; } }
static void xps_add_fixed_document(xps_context *ctx, char *name) { xps_document *fixdoc; /* Check for duplicates first */ for (fixdoc = ctx->first_fixdoc; fixdoc; fixdoc = fixdoc->next) if (!strcmp(fixdoc->name, name)) return; fixdoc = fz_malloc(sizeof(xps_document)); fixdoc->name = fz_strdup(name); fixdoc->next = NULL; if (!ctx->first_fixdoc) { ctx->first_fixdoc = fixdoc; ctx->last_fixdoc = fixdoc; } else { ctx->last_fixdoc->next = fixdoc; ctx->last_fixdoc = fixdoc; } }
static float pdf_extract_font_size(pdf_xref *xref, char *appearance, char **font_name) { fz_context *ctx = xref->ctx; fz_stream *stream = fz_open_memory(ctx, appearance, strlen(appearance)); float font_size = 0; int tok, len; *font_name = NULL; do { fz_error error = pdf_lex(&tok, stream, xref->scratch, sizeof(xref->scratch), &len); if (error || tok == PDF_TOK_EOF) { fz_free(ctx, *font_name); *font_name = NULL; break; } if (tok == PDF_TOK_NAME) { fz_free(ctx, *font_name); *font_name = fz_strdup(ctx, xref->scratch); } else if (tok == PDF_TOK_REAL || tok == PDF_TOK_INT) { font_size = fz_atof(xref->scratch); } } while (tok != PDF_TOK_KEYWORD || strcmp(xref->scratch, "Tf") != 0); fz_close(stream); return font_size; }
static epub_chapter * epub_parse_chapter(fz_context *ctx, epub_document *doc, const char *path) { fz_archive *zip = doc->zip; fz_buffer *buf = NULL; epub_chapter *ch; char base_uri[2048]; fz_dirname(base_uri, path, sizeof base_uri); ch = fz_malloc_struct(ctx, epub_chapter); ch->path = NULL; ch->html = NULL; ch->next = NULL; fz_var(buf); fz_try(ctx) { buf = fz_read_archive_entry(ctx, zip, path); ch->path = fz_strdup(ctx, path); ch->html = fz_parse_html(ctx, doc->set, zip, base_uri, buf, fz_user_css(ctx)); } fz_always(ctx) fz_drop_buffer(ctx, buf); fz_catch(ctx) { fz_drop_html(ctx, ch->html); fz_free(ctx, ch->path); fz_free(ctx, ch); fz_rethrow(ctx); } return ch; }
fz_document_writer * fz_new_pixmap_writer(fz_context *ctx, const char *path, const char *options, const char *default_path, int n, void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename)) { fz_pixmap_writer *wri = fz_new_derived_document_writer(ctx, fz_pixmap_writer, pixmap_begin_page, pixmap_end_page, NULL, pixmap_drop_writer); fz_try(ctx) { fz_parse_draw_options(ctx, &wri->options, options); wri->path = fz_strdup(ctx, path ? path : default_path); wri->save = save; switch (n) { case 1: wri->options.colorspace = fz_device_gray(ctx); break; case 3: wri->options.colorspace = fz_device_rgb(ctx); break; case 4: wri->options.colorspace = fz_device_cmyk(ctx); break; } } fz_catch(ctx) { fz_free(ctx, wri); fz_rethrow(ctx); } return (fz_document_writer*)wri; }
static void xps_add_fixed_document(fz_context *ctx, xps_document *doc, char *name) { xps_fixdoc *fixdoc; /* Check for duplicates first */ for (fixdoc = doc->first_fixdoc; fixdoc; fixdoc = fixdoc->next) if (!strcmp(fixdoc->name, name)) return; fixdoc = fz_malloc_struct(ctx, xps_fixdoc); fixdoc->name = fz_strdup(ctx, name); fixdoc->outline = NULL; fixdoc->next = NULL; if (!doc->first_fixdoc) { doc->first_fixdoc = fixdoc; doc->last_fixdoc = fixdoc; } else { doc->last_fixdoc->next = fixdoc; doc->last_fixdoc = fixdoc; } }
static void xps_add_fixed_page(fz_context *ctx, xps_document *doc, char *name, int width, int height) { xps_fixpage *page; /* Check for duplicates first */ for (page = doc->first_page; page; page = page->next) if (!strcmp(page->name, name)) return; page = fz_malloc_struct(ctx, xps_fixpage); page->name = fz_strdup(ctx, name); page->number = doc->page_count++; page->width = width; page->height = height; page->next = NULL; if (!doc->first_page) { doc->first_page = page; doc->last_page = page; } else { doc->last_page->next = page; doc->last_page = page; } }
void xps_extract_anchor_info(xps_context *ctx, xml_element *node, fz_rect rect) { char *value; if (ctx->link_root && (value = xml_att(node, "FixedPage.NavigateUri"))) { xps_anchor *link = fz_malloc(ctx->ctx, sizeof(xps_anchor)); link->target = fz_strdup(ctx->ctx, value); link->rect = rect; // insert the links in bottom-to-top order (first one is to be preferred) link->next = ctx->link_root->next; ctx->link_root->next = link; } if ((value = xml_att(node, "Name"))) { xps_target *target; char *valueId = fz_malloc(ctx->ctx, strlen(value) + 2); sprintf(valueId, "#%s", value); target = xps_find_link_target_obj(ctx, valueId); if (target) target->rect = rect; fz_free(ctx->ctx, valueId); } }
fz_error fz_newfontfromfile(fz_font **fontp, char *path, int index) { fz_error error; fz_font *font; int fterr; error = fz_initfreetype(); if (error) return fz_rethrow(error, "cannot init freetype library"); font = fz_newfont(); fterr = FT_New_Face(fz_ftlib, path, index, (FT_Face*)&font->ftface); if (fterr) { fz_free(font); return fz_throw("freetype: cannot load font: %s", ft_errorstring(fterr)); } /* SumatraPDF */ font->_data = fz_strdup(path); font->_data_len = 0; *fontp = font; return fz_okay; }
int main(int argc, char **argv) { MSG msg; char buf[1024]; char *filename; fz_cpudetect(); fz_accelerate(); pdfapp_init(&gapp); associate(argv[0]); winopen(); if (argc == 2) filename = fz_strdup(argv[1]); else { if (!winfilename(buf, sizeof buf)) exit(0); filename = buf; } pdfapp_open(&gapp, filename); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } pdfapp_close(&gapp); return 0; }
void fz_set_user_css(fz_context *ctx, const char *user_css) { fz_lock(ctx, FZ_LOCK_ALLOC); fz_free(ctx, ctx->style->user_css); ctx->style->user_css = fz_strdup(ctx, user_css); fz_unlock(ctx, FZ_LOCK_ALLOC); }
static char * find_metadata(fz_context *ctx, fz_xml *metadata, char *key) { char *text = fz_xml_text(fz_xml_down(fz_xml_find_down(metadata, key))); if (text) return fz_strdup(ctx, text); return NULL; }
static fz_css_value *fz_new_css_value(fz_context *ctx, int type, const char *data) { fz_css_value *val = fz_malloc_struct(ctx, fz_css_value); val->type = type; val->data = fz_strdup(ctx, data); val->args = NULL; val->next = NULL; return val; }
static fz_css_property *fz_new_css_property(fz_context *ctx, const char *name, fz_css_value *value, int spec) { fz_css_property *prop = fz_malloc_struct(ctx, fz_css_property); prop->name = fz_strdup(ctx, name); prop->value = value; prop->spec = spec; prop->next = NULL; return prop; }
static void xps_insert_font(fz_context *ctx, xps_document *doc, char *name, fz_font *font) { xps_font_cache *cache = fz_malloc_struct(ctx, xps_font_cache); cache->name = fz_strdup(ctx, name); cache->font = fz_keep_font(ctx, font); cache->next = doc->font_table; doc->font_table = cache; }
static fz_tree *fz_tree_new_node(fz_context *ctx, const char *key, void *value) { fz_tree *node = fz_malloc_struct(ctx, fz_tree); node->key = fz_strdup(ctx, key); node->value = value; node->left = node->right = &sentinel; node->level = 1; return node; }
static void xps_add_link_target(fz_context *ctx, xps_document *doc, char *name) { xps_fixpage *page = doc->last_page; xps_target *target = fz_malloc_struct(ctx, xps_target); target->name = fz_strdup(ctx, name); target->page = page->number; target->next = doc->target; doc->target = target; }
static fz_css_selector *fz_new_css_selector(fz_context *ctx, const char *name) { fz_css_selector *sel = fz_malloc_struct(ctx, fz_css_selector); sel->name = name ? fz_strdup(ctx, name) : NULL; sel->combine = 0; sel->cond = NULL; sel->left = NULL; sel->right = NULL; sel->next = NULL; return sel; }
static xps_link * xps_new_link(char *target, fz_rect rect, int is_dest) { xps_link *link = fz_malloc(sizeof(xps_link)); link->target = fz_strdup(target); link->rect = rect; link->is_dest = is_dest; link->next = NULL; return link; }
static xps_named_dest * xps_new_named_dest(char *target, int page) { xps_named_dest *dest = fz_malloc(sizeof(xps_named_dest)); dest->target = fz_strdup(target); dest->page = page; dest->rect = fz_empty_rect; // to be updated dest->next = NULL; return dest; }
static char *parse_attrib_value(struct lexbuf *buf) { char *s; if (buf->lookahead == CSS_KEYWORD || buf->lookahead == CSS_STRING) { s = fz_strdup(buf->ctx, buf->string); next(buf); return s; } fz_css_error(buf, "expected attribute value"); }
xps_part * xps_new_part(xps_context *ctx, char *name, int size) { xps_part *part; part = fz_malloc(ctx->ctx, sizeof(xps_part)); part->name = fz_strdup(ctx->ctx, name); part->size = size; part->data = fz_malloc(ctx->ctx, size + 1); part->data[size] = 0; /* null-terminate for xml parser */ return part; }
static void xps_parse_metadata_imp(xps_context *ctx, xml_element *item) { while (item) { xps_parse_metadata_imp(ctx, xml_down(item)); if (!strcmp(xml_tag(item), "Relationship")) { char *target = xml_att(item, "Target"); char *type = xml_att(item, "Type"); if (target && type) { char tgtbuf[1024]; xps_absolute_path(tgtbuf, ctx->base_uri, target, sizeof tgtbuf); if (!strcmp(type, REL_START_PART)) ctx->start_part = fz_strdup(tgtbuf); } } if (!strcmp(xml_tag(item), "DocumentReference")) { char *source = xml_att(item, "Source"); if (source) { char srcbuf[1024]; xps_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_document(ctx, srcbuf); } } if (!strcmp(xml_tag(item), "PageContent")) { char *source = xml_att(item, "Source"); char *width_att = xml_att(item, "Width"); char *height_att = 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_absolute_path(srcbuf, ctx->base_uri, source, sizeof srcbuf); xps_add_fixed_page(ctx, srcbuf, width, height); } } item = xml_next(item); } }
void fz_add_separation(fz_context *ctx, fz_separations *sep, uint32_t rgb, uint32_t cmyk, char *name) { int n; if (!ctx || !sep) return; n = sep->num_separations; if (n == FZ_MAX_SEPARATIONS) fz_throw(ctx, FZ_ERROR_GENERIC, "Too many separations"); sep->name[n] = fz_strdup(ctx, name); sep->equiv_rgb[n] = rgb; sep->equiv_cmyk[n] = cmyk; sep->num_separations++; }
int xps_parse_resource_dictionary(xps_context *ctx, xps_resource **dictp, char *base_uri, xml_element *root) { xps_resource *head; xps_resource *entry; xml_element *node; char *source; char *key; int code; source = xml_att(root, "Source"); if (source) { code = xps_parse_remote_resource_dictionary(ctx, dictp, base_uri, source); if (code) return fz_rethrow(code, "cannot parse remote resource dictionary"); return fz_okay; } head = NULL; for (node = xml_down(root); node; node = xml_next(node)) { key = xml_att(node, "x:Key"); if (key) { entry = fz_malloc(sizeof(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(base_uri); } *dictp = head; return fz_okay; }