pdf_obj * CIDFont_get_resource (CIDFont *font) { ASSERT(font); if (!font->indirect) font->indirect = pdf_ref_obj(font->fontdict); return pdf_link_obj(font->indirect); }
static void pdf_flush_font (pdf_font *font) { char *fontname, *uniqueTag; if (!font) { return; } if (font->resource && font->reference) { if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) { if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { pdf_add_dict(font->resource, pdf_new_name("BaseFont"), pdf_new_name(font->fontname)); if (font->descriptor) { pdf_add_dict(font->descriptor, pdf_new_name("FontName"), pdf_new_name(font->fontname)); } } else { if (!font->fontname) { ERROR("Undefined in fontname... (%s)", font->ident); } fontname = NEW(7+strlen(font->fontname)+1, char); uniqueTag = pdf_font_get_uniqueTag(font); sprintf(fontname, "%6s+%s", uniqueTag, font->fontname); pdf_add_dict(font->resource, pdf_new_name("BaseFont"), pdf_new_name(fontname)); if (font->descriptor) { pdf_add_dict(font->descriptor, pdf_new_name("FontName"), pdf_new_name(fontname)); } RELEASE(fontname); } if (font->descriptor) { pdf_add_dict(font->resource, pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor)); } } } if (font->resource) pdf_release_obj(font->resource); if (font->descriptor) pdf_release_obj(font->descriptor); if (font->reference) pdf_release_obj(font->reference); font->reference = NULL; font->resource = NULL; font->descriptor = NULL; return; }
pdf_obj * Type0Font_get_resource (Type0Font *font) { ASSERT(font); /* * This looks somewhat strange. */ if (!font->indirect) { pdf_obj *array; array = pdf_new_array(); pdf_add_array(array, CIDFont_get_resource(font->descendant)); pdf_add_dict(font->fontdict, pdf_new_name("DescendantFonts"), array); font->indirect = pdf_ref_obj(font->fontdict); } return pdf_link_obj(font->indirect); }
pdf_obj * pdf_get_font_reference (int font_id) { pdf_font *font; CHECK_ID(font_id); font = GET_FONT(font_id); if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) { Type0Font *t0font; t0font = Type0Font_cache_get(font->font_id); return Type0Font_get_resource(t0font); } else { if (!font->reference) { font->reference = pdf_ref_obj(pdf_font_get_resource(font)); } } return pdf_link_obj(font->reference); }
static void html_make_link_dict (char *name) { pdf_obj *color; if (!link_dict) { link_dict = pdf_new_dict(); pdf_add_dict(link_dict, pdf_new_name("Type"), pdf_new_name ("Annot")); pdf_add_dict(link_dict, pdf_new_name("Subtype"), pdf_new_name ("Link")); color = pdf_new_array (); pdf_add_array (color, pdf_new_number (0)); pdf_add_array (color, pdf_new_number (1)); pdf_add_array (color, pdf_new_number (1)); pdf_add_dict(link_dict, pdf_new_name("C"), color); if (name && *name == '#' && !(base_value)) { pdf_add_dict (link_dict, pdf_new_name("Dest"), pdf_new_string(name+1,strlen(name+1))); } else if (name) { /* Assume its a URL */ char *url; int len; pdf_obj *action; len = strlen(name)+1; if (base_value) len+=strlen(base_value); url = NEW (len, char); if (base_value) strcpy (url, base_value); else url[0] = 0; strcat (url, name); action = pdf_new_dict(); pdf_add_dict (action, pdf_new_name ("Type"), pdf_new_name ("Action")); pdf_add_dict (action, pdf_new_name ("S"), pdf_new_name ("URI")); pdf_add_dict (action, pdf_new_name ("URI"), pdf_new_string (url, len)); pdf_add_dict (link_dict, pdf_new_name ("A"), pdf_ref_obj (action)); pdf_release_obj (action); RELEASE (url); } pdf_doc_begin_annot (link_dict); } else {
long pdf_defineresource (const char *category, const char *resname, pdf_obj *object, int flags) { int res_id; struct res_cache *rc; int cat_id; pdf_res *res = NULL; ASSERT(category && object); cat_id = get_category(category); if (cat_id < 0) { ERROR("Unknown resource category: %s", category); return -1; } rc = &resources[cat_id]; if (resname) { for (res_id = 0; res_id < rc->count; res_id++) { res = &rc->resources[res_id]; if (!strcmp(resname, res->ident)) { WARN("Resource %s (category: %s) already defined...", resname, category); pdf_flush_resource(res); res->flags = flags; if (flags & PDF_RES_FLUSH_IMMEDIATE) { res->reference = pdf_ref_obj(object); pdf_release_obj(object); } else { res->object = object; } return (long) ((cat_id << 16)|(res_id)); } } } else { res_id = rc->count; } if (res_id == rc->count) { if (rc->count >= rc->capacity) { rc->capacity += CACHE_ALLOC_SIZE; rc->resources = RENEW(rc->resources, rc->capacity, pdf_res); } res = &rc->resources[res_id]; pdf_init_resource(res); if (resname && resname[0] != '\0') { res->ident = NEW(strlen(resname) + 1, char); strcpy(res->ident, resname); } res->category = cat_id; res->flags = flags; if (flags & PDF_RES_FLUSH_IMMEDIATE) { res->reference = pdf_ref_obj(object); pdf_release_obj(object); } else { res->object = object; } rc->count++; }
int pdf_font_load_pkfont (pdf_font *font) { pdf_obj *fontdict; char *usedchars; char *ident; unsigned dpi; FILE *fp; double point_size, pix2charu; int opcode, code, firstchar, lastchar, prev; pdf_obj *charprocs, *procset, *encoding, *tmp_array; double widths[256]; pdf_rect bbox; char charavail[256]; #if ENABLE_GLYPHENC int encoding_id; char **enc_vec; #endif /* ENABLE_GLYPHENC */ int error = 0; if (!pdf_font_is_in_use(font)) { return 0; } ident = pdf_font_get_ident(font); point_size = pdf_font_get_param(font, PDF_FONT_PARAM_POINT_SIZE); usedchars = pdf_font_get_usedchars(font); #if ENABLE_GLYPHENC encoding_id = pdf_font_get_encoding(font); if (encoding_id < 0) enc_vec = NULL; else { enc_vec = pdf_encoding_get_encoding(encoding_id); } #endif /* ENABLE_GLYPHENC */ ASSERT(ident && usedchars && point_size > 0.0); dpi = truedpi(ident, point_size, base_dpi); { char *fontfile = pdf_font_get_fontfile (font); if (fontfile) fp = MFOPEN(fontfile, FOPEN_RBIN_MODE); else fp = dpx_open_pk_font_at(ident, dpi); } if (!fp) { ERROR("Could not find/open PK font file: %s (at %udpi)", ident, dpi); } memset(charavail, 0, 256); charprocs = pdf_new_dict(); /* Include bitmap as 72dpi image: * There seems to be problems in "scaled" bitmap glyph * rendering in several viewers. */ pix2charu = 72. * 1000. / ((double) base_dpi) / point_size; bbox.llx = bbox.lly = HUGE_VAL; bbox.urx = bbox.ury = -HUGE_VAL; while ((opcode = fgetc(fp)) >= 0 && opcode != PK_POST) { if (opcode < 240) { struct pk_header_ pkh; error = read_pk_char_header(&pkh, opcode, fp); if (error) ERROR("Error in reading PK character header."); else if (charavail[pkh.chrcode & 0xff]) WARN("More than two bitmap image for single glyph?: font=\"%s\" code=0x%02x", ident, pkh.chrcode); if (!usedchars[pkh.chrcode & 0xff]) do_skip(fp, pkh.pkt_len); else { char *charname; pdf_obj *charproc; unsigned char *pkt_ptr; size_t bytesread; double charwidth; /* Charwidth in PDF units */ charwidth = ROUND(1000.0 * pkh.wd / (((double) (1<<20))*pix2charu), 0.1); widths[pkh.chrcode & 0xff] = charwidth; /* Update font BBox info */ bbox.llx = MIN(bbox.llx, -pkh.bm_hoff); bbox.lly = MIN(bbox.lly, pkh.bm_voff - pkh.bm_ht); bbox.urx = MAX(bbox.urx, pkh.bm_wd - pkh.bm_hoff); bbox.ury = MAX(bbox.ury, pkh.bm_voff); pkt_ptr = NEW(pkh.pkt_len, unsigned char); if ((bytesread = fread(pkt_ptr, 1, pkh.pkt_len, fp))!= pkh.pkt_len) { ERROR("Only %ld bytes PK packet read. (expected %ld bytes)", bytesread, pkh.pkt_len); } charproc = create_pk_CharProc_stream(&pkh, charwidth, pkt_ptr, bytesread); RELEASE(pkt_ptr); if (!charproc) ERROR("Unpacking PK character data failed."); #if ENABLE_GLYPHENC if (encoding_id >= 0 && enc_vec) { charname = (char *) enc_vec[pkh.chrcode & 0xff]; if (!charname) { WARN("\".notdef\" glyph used in font (code=0x%02x): %s", pkh.chrcode, ident); charname = work_buffer; pk_char2name(charname, pkh.chrcode); } } else #endif /* ENABLE_GLYPHENC */ { charname = work_buffer; pk_char2name(charname, pkh.chrcode); } pdf_add_dict(charprocs, pdf_new_name(charname), pdf_ref_obj(charproc)); /* _FIXME_ */ pdf_release_obj(charproc); } charavail[pkh.chrcode & 0xff] = 1; } else { /* A command byte */ switch (opcode) { case PK_NO_OP: break; case PK_XXX1: do_skip(fp, get_unsigned_byte(fp)); break; case PK_XXX2: do_skip(fp, get_unsigned_pair(fp)); break; case PK_XXX3: do_skip(fp, get_unsigned_triple(fp)); break; case PK_XXX4: do_skip(fp, get_unsigned_quad(fp)); break; case PK_YYY: do_skip(fp, 4); break; case PK_PRE: do_preamble(fp); break; } } }
int png_include_image (pdf_ximage *ximage, FILE *png_file) { pdf_obj *stream; pdf_obj *stream_dict; pdf_obj *colorspace, *mask, *intent; png_bytep stream_data_ptr; int trans_type; ximage_info info; /* Libpng stuff */ png_structp png_ptr; png_infop png_info_ptr; png_byte bpc, color_type; png_uint_32 width, height, rowbytes; pdf_ximage_init_image_info(&info); stream = NULL; stream_dict = NULL; colorspace = mask = intent = NULL; rewind (png_file); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn); if (png_ptr == NULL || (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) { WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); return -1; } #if PNG_LIBPNG_VER >= 10603 /* ignore possibly incorrect CMF bytes */ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON); #endif /* Inititializing file IO. */ png_init_io (png_ptr, png_file); /* Read PNG info-header and get some info. */ png_read_info(png_ptr, png_info_ptr); color_type = png_get_color_type (png_ptr, png_info_ptr); width = png_get_image_width (png_ptr, png_info_ptr); height = png_get_image_height(png_ptr, png_info_ptr); bpc = png_get_bit_depth (png_ptr, png_info_ptr); /* Ask libpng to convert down to 8-bpc. */ if (bpc > 8) { if (pdf_get_version() < 5) { WARN("%s: 16-bpc PNG requires PDF version 1.5.", PNG_DEBUG_STR); png_set_strip_16(png_ptr); bpc = 8; } } /* Ask libpng to gamma-correct. * It is wrong to assume screen gamma value 2.2 but... * We do gamma correction here only when uncalibrated color space is used. */ if (!png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP) && !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) && !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM) && png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) { double G = 1.0; png_get_gAMA (png_ptr, png_info_ptr, &G); png_set_gamma(png_ptr, 2.2, G); } trans_type = check_transparency(png_ptr, png_info_ptr); /* check_transparency() does not do updata_info() */ png_read_update_info(png_ptr, png_info_ptr); rowbytes = png_get_rowbytes(png_ptr, png_info_ptr); /* Values listed below will not be modified in the remaining process. */ info.width = width; info.height = height; info.bits_per_component = bpc; if (compat_mode) info.xdensity = info.ydensity = 72.0 / 100.0; else { png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr); png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr); if (xppm > 0) info.xdensity = 72.0 / 0.0254 / xppm; if (yppm > 0) info.ydensity = 72.0 / 0.0254 / yppm; } stream = pdf_new_stream (STREAM_COMPRESS); stream_dict = pdf_stream_dict(stream); stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte); read_image_data(png_ptr, stream_data_ptr, height, rowbytes); /* Non-NULL intent means there is valid sRGB chunk. */ intent = get_rendering_intent(png_ptr, png_info_ptr); if (intent) pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: colorspace = create_cspace_Indexed(png_ptr, png_info_ptr); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: /* Color-key masking */ mask = create_ckey_mask(png_ptr, png_info_ptr); break; case PDF_TRANS_TYPE_ALPHA: /* Soft mask */ mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height); break; default: /* Nothing to be done here. * No tRNS chunk or image already composited with background color. */ break; } info.num_components = 1; break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); else if (intent) { colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); } else { colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr); } if (!colorspace) colorspace = pdf_new_name("DeviceRGB"); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: mask = create_ckey_mask(png_ptr, png_info_ptr); break; /* rowbytes changes 4 to 3 at here */ case PDF_TRANS_TYPE_ALPHA: mask = strip_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, &rowbytes, width, height); break; default: mask = NULL; } info.num_components = 3; break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); else if (intent) { colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); } else { colorspace = create_cspace_CalGray(png_ptr, png_info_ptr); } if (!colorspace) colorspace = pdf_new_name("DeviceGray"); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: mask = create_ckey_mask(png_ptr, png_info_ptr); break; case PDF_TRANS_TYPE_ALPHA: mask = strip_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, &rowbytes, width, height); break; default: mask = NULL; } info.num_components = 1; break; default: WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type); } pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); pdf_add_stream(stream, stream_data_ptr, rowbytes*height); RELEASE(stream_data_ptr); if (mask) { if (trans_type == PDF_TRANS_TYPE_BINARY) pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask); else if (trans_type == PDF_TRANS_TYPE_ALPHA) { if (info.bits_per_component >= 8 && info.width > 64) { pdf_stream_set_predictor(mask, 2, info.width, info.bits_per_component, 1); } pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask)); pdf_release_obj(mask); } else { WARN("%s: Unknown transparency type...???", PNG_DEBUG_STR); pdf_release_obj(mask); } } /* Finally read XMP Metadata * See, XMP Specification Part 3, Storage in Files * http://www.adobe.com/jp/devnet/xmp.html * * We require libpng version >= 1.6.14 since prior versions * of libpng had a bug that incorrectly treat the compression * flag of iTxt chunks. */ #if PNG_LIBPNG_VER >= 10614 if (pdf_get_version() >= 4) { png_textp text_ptr; pdf_obj *XMP_stream, *XMP_stream_dict; int i, num_text; int have_XMP = 0; num_text = png_get_text(png_ptr, png_info_ptr, &text_ptr, NULL); for (i = 0; i < num_text; i++) { if (!memcmp(text_ptr[i].key, "XML:com.adobe.xmp", 17)) { /* XMP found */ if (text_ptr[i].compression != PNG_ITXT_COMPRESSION_NONE || text_ptr[i].itxt_length == 0) WARN("%s: Invalid value(s) in iTXt chunk for XMP Metadata.", PNG_DEBUG_STR); else if (have_XMP) WARN("%s: Multiple XMP Metadata. Don't know how to treat it.", PNG_DEBUG_STR); else { /* We compress XMP metadata for included images here. * It is not recommended to compress XMP metadata for PDF documents but * we compress XMP metadata for included images here to avoid confusing * application programs that only want PDF document global XMP metadata * and scan for that. */ XMP_stream = pdf_new_stream(STREAM_COMPRESS); XMP_stream_dict = pdf_stream_dict(XMP_stream); pdf_add_dict(XMP_stream_dict, pdf_new_name("Type"), pdf_new_name("Metadata")); pdf_add_dict(XMP_stream_dict, pdf_new_name("Subtype"), pdf_new_name("XML")); pdf_add_stream(XMP_stream, text_ptr[i].text, text_ptr[i].itxt_length); pdf_add_dict(stream_dict, pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream)); pdf_release_obj(XMP_stream); have_XMP = 1; } } } } #endif /* PNG_LIBPNG_VER */ png_read_end(png_ptr, NULL); /* Cleanup */ if (png_info_ptr) png_destroy_info_struct(png_ptr, &png_info_ptr); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); if (color_type != PNG_COLOR_TYPE_PALETTE && info.bits_per_component >= 8 && info.height > 64) { pdf_stream_set_predictor(stream, 15, info.width, info.bits_per_component, info.num_components); } pdf_ximage_set_image(ximage, &info, stream); return 0; }
pdf_obj *pdf_include_page(FILE *image_file, struct xform_info *p, char *res_name) { pdf_obj *trailer = NULL, *catalog = NULL, *page_tree = NULL; pdf_obj *kids_ref, *kids; pdf_obj *media_box = NULL, *crop_box = NULL, *resources = NULL, *contents = NULL, *contents_ref = NULL; pdf_obj *tmp1; #ifdef MEM_DEBUG MEM_START #endif if (!(trailer = pdf_open (image_file))) { fprintf (stderr, "\nCorrupt PDF file?\n"); } /* Now just lookup catalog location */ /* Deref catalog */ if (trailer && (catalog = pdf_deref_obj(pdf_lookup_dict (trailer,"Root"))) == NULL) { fprintf (stderr, "\nCatalog isn't where I expect it.\n"); } if (trailer) pdf_release_obj (trailer); /* Lookup page tree in catalog */ if (catalog) { page_tree = pdf_deref_obj (pdf_lookup_dict (catalog, "Pages")); /* Should be finished with catalog */ pdf_release_obj (catalog); } /* Media box and resources can be inherited so start looking for them here */ if (page_tree) { if ((tmp1 = pdf_lookup_dict (page_tree, "CropBox"))) crop_box = pdf_deref_obj (tmp1); if ((tmp1 = pdf_lookup_dict (page_tree, "MediaBox"))) media_box = pdf_deref_obj (tmp1); resources = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources")); if (resources == NULL) { resources = pdf_new_dict(); } while ((kids_ref = pdf_lookup_dict (page_tree, "Kids")) != NULL) { kids = pdf_deref_obj (kids_ref); pdf_release_obj (page_tree); page_tree = pdf_deref_obj (pdf_get_array(kids, 0)); pdf_release_obj (kids); /* Replace MediaBox if it's here */ tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "MediaBox")); if (tmp1 && media_box) pdf_release_obj (media_box); if (tmp1) media_box = tmp1; /* Do same for CropBox */ tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "CropBox")); if (tmp1 && crop_box) pdf_release_obj (crop_box); if (tmp1) crop_box = tmp1; /* Add resources if they're here */ tmp1 = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources")); if (tmp1) { pdf_merge_dict (tmp1, resources); pdf_release_obj (resources); resources = tmp1; } } /* At this point, page_tree contains the first page. media_box, crop_box, and resources should also be set. */ /* If there's a crop_box, replace media_box with crop_box. The rest of this routine assumes crop_box has been released */ if (crop_box) { pdf_release_obj (media_box); media_box = crop_box; crop_box = NULL; } /* This gets bit confusing. In the following code, media_box is the box the image is cropped to. The bounding box is the box the image is scaled to */ /* If user did not supply bounding box, use media_box (which may really be cropbox) as bounding box */ /* Set the crop box parameters in the xform_info structure */ p->c_llx = pdf_number_value (pdf_get_array (media_box, 0)); p->c_lly = pdf_number_value (pdf_get_array (media_box, 1)); p->c_urx = pdf_number_value (pdf_get_array (media_box, 2)); p->c_ury = pdf_number_value (pdf_get_array (media_box, 3)); /* Adjust scaling and clipping information as necessary */ pdf_scale_image (p); /* Set the media box to whatever pdf_scale_image() decided for the crop box (which may be unchanged) */ pdf_release_obj (media_box); media_box = pdf_new_array (); pdf_add_array (media_box, pdf_new_number (p->c_llx)); pdf_add_array (media_box, pdf_new_number (p->c_lly)); pdf_add_array (media_box, pdf_new_number (p->c_urx)); pdf_add_array (media_box, pdf_new_number (p->c_ury)); if ((contents = pdf_deref_obj(pdf_lookup_dict(page_tree,"Contents")))==NULL) { fprintf (stderr, "\nNo Contents found\n"); return NULL; } pdf_release_obj (page_tree); } /* Arrays of contents must be handled very differently (not implemented) */ if (contents && contents -> type != PDF_ARRAY) { doc_make_form_xobj (contents, media_box, p->user_bbox? p->u_llx: 0.0, p->user_bbox? p->u_lly: 0.0, 1.0, 1.0, resources, res_name); } else { fprintf (stderr, "\nIgnoring stream with with multiple segments\n"); contents = NULL; } if (contents) { contents_ref = pdf_ref_obj (contents); pdf_release_obj (contents); } pdf_close (); #ifdef MEM_DEBUG MEM_END #endif return (contents_ref); }
/* * The following routine returns copies, not the original object. */ pdf_obj * spc_lookup_reference (const char *key) { pdf_obj *value = NULL; pdf_coord cp; int k; ASSERT(named_objects); if (!key) return NULL; for (k = 0; _rkeys[k] && strcmp(key, _rkeys[k]); k++); switch (k) { /* xpos and ypos must be position in device space here. */ case K_OBJ__XPOS: cp.x = dvi_dev_xpos(); cp.y = 0.0; pdf_dev_transform(&cp, NULL); value = pdf_new_number(ROUND(cp.x, .01)); break; case K_OBJ__YPOS: cp.x = 0.0; cp.y = dvi_dev_ypos(); pdf_dev_transform(&cp, NULL); value = pdf_new_number(ROUND(cp.y, .01)); break; case K_OBJ__THISPAGE: value = pdf_doc_this_page_ref(); break; case K_OBJ__PREVPAGE: value = pdf_doc_prev_page_ref(); break; case K_OBJ__NEXTPAGE: value = pdf_doc_next_page_ref(); break; case K_OBJ__PAGES: value = pdf_ref_obj(pdf_doc_page_tree()); break; case K_OBJ__NAMES: value = pdf_ref_obj(pdf_doc_names()); break; case K_OBJ__RESOURCES: value = pdf_ref_obj(pdf_doc_current_page_resources()); break; case K_OBJ__CATALOG: value = pdf_ref_obj(pdf_doc_catalog()); break; case K_OBJ__DOCINFO: value = pdf_ref_obj(pdf_doc_docinfo()); break; default: if (ispageref(key)) value = pdf_doc_ref_page(atoi(key + 4)); else { value = pdf_names_lookup_reference(named_objects, key, strlen(key)); } break; } if (!value) { ERROR("Object reference %s not exist.", key); } return value; }