From 85a4af76fcdaa84a774e591e5b9b892ced83c6e5 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Fri, 18 Apr 2008 09:08:15 +0000 Subject: merged xdvipdfmx patches to support xetex update git-svn-id: svn://tug.org/texlive/branches/branch2007@7491 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/xdvipdfmx/configure | 2 +- Build/source/texk/xdvipdfmx/configure.in | 2 +- Build/source/texk/xdvipdfmx/src/bmpimage.c | 4 +- Build/source/texk/xdvipdfmx/src/cff_dict.c | 107 +--- Build/source/texk/xdvipdfmx/src/cff_dict.h | 3 +- Build/source/texk/xdvipdfmx/src/cidtype0.c | 27 +- Build/source/texk/xdvipdfmx/src/cidtype2.c | 4 +- Build/source/texk/xdvipdfmx/src/dpxfile.c | 6 +- Build/source/texk/xdvipdfmx/src/dvi.c | 163 ++++-- Build/source/texk/xdvipdfmx/src/dvi.h | 5 + Build/source/texk/xdvipdfmx/src/dvipdfmx.c | 143 +++-- Build/source/texk/xdvipdfmx/src/epdf.c | 760 ++++++++++++++++++++------- Build/source/texk/xdvipdfmx/src/epdf.h | 4 +- Build/source/texk/xdvipdfmx/src/fontmap.c | 37 +- Build/source/texk/xdvipdfmx/src/fontmap.h | 2 +- Build/source/texk/xdvipdfmx/src/jpegimage.c | 170 +++++- Build/source/texk/xdvipdfmx/src/mpost.c | 24 +- Build/source/texk/xdvipdfmx/src/pdfcolor.c | 210 ++------ Build/source/texk/xdvipdfmx/src/pdfcolor.h | 16 +- Build/source/texk/xdvipdfmx/src/pdfdev.c | 214 +++++++- Build/source/texk/xdvipdfmx/src/pdfdev.h | 9 +- Build/source/texk/xdvipdfmx/src/pdfdoc.c | 39 +- Build/source/texk/xdvipdfmx/src/pdfdoc.h | 5 +- Build/source/texk/xdvipdfmx/src/pdfdraw.c | 435 ++++++++------- Build/source/texk/xdvipdfmx/src/pdfdraw.h | 7 + Build/source/texk/xdvipdfmx/src/pdfencrypt.c | 32 +- Build/source/texk/xdvipdfmx/src/pdfencrypt.h | 9 +- Build/source/texk/xdvipdfmx/src/pdfobj.c | 537 +++++++++++++------ Build/source/texk/xdvipdfmx/src/pdfobj.h | 14 +- Build/source/texk/xdvipdfmx/src/pdfparse.c | 7 +- Build/source/texk/xdvipdfmx/src/pdfximage.c | 271 +++++++--- Build/source/texk/xdvipdfmx/src/pdfximage.h | 16 +- Build/source/texk/xdvipdfmx/src/pngimage.c | 15 +- Build/source/texk/xdvipdfmx/src/pst_obj.c | 6 +- Build/source/texk/xdvipdfmx/src/spc_color.c | 28 +- Build/source/texk/xdvipdfmx/src/spc_dvips.c | 578 +++++++++++++++++++- Build/source/texk/xdvipdfmx/src/spc_html.c | 4 +- Build/source/texk/xdvipdfmx/src/spc_misc.c | 2 +- Build/source/texk/xdvipdfmx/src/spc_pdfm.c | 83 +-- Build/source/texk/xdvipdfmx/src/spc_util.c | 77 ++- Build/source/texk/xdvipdfmx/src/spc_util.h | 4 +- Build/source/texk/xdvipdfmx/src/spc_xtx.c | 148 +++++- Build/source/texk/xdvipdfmx/src/spc_xtx.h | 1 + Build/source/texk/xdvipdfmx/src/specials.h | 2 +- Build/source/texk/xdvipdfmx/src/truetype.c | 44 +- Build/source/texk/xdvipdfmx/src/tt_aux.c | 27 +- Build/source/texk/xdvipdfmx/src/tt_aux.h | 4 +- Build/source/texk/xdvipdfmx/src/tt_cmap.c | 47 +- Build/source/texk/xdvipdfmx/src/tt_glyf.c | 22 +- Build/source/texk/xdvipdfmx/src/tt_post.c | 9 +- Build/source/texk/xdvipdfmx/src/tt_table.c | 92 ++-- Build/source/texk/xdvipdfmx/src/tt_table.h | 20 +- Build/source/texk/xdvipdfmx/src/type1.c | 18 +- Build/source/texk/xdvipdfmx/src/type1c.c | 2 +- Build/source/texk/xdvipdfmx/src/vf.c | 5 +- 55 files changed, 3178 insertions(+), 1344 deletions(-) diff --git a/Build/source/texk/xdvipdfmx/configure b/Build/source/texk/xdvipdfmx/configure index 9d0c7938c0d..c05ec5e0aff 100755 --- a/Build/source/texk/xdvipdfmx/configure +++ b/Build/source/texk/xdvipdfmx/configure @@ -1828,7 +1828,7 @@ fi # Define the identity of the package. PACKAGE=xdvipdfmx - VERSION=0.4 + VERSION=0.6 cat >>confdefs.h <<_ACEOF diff --git a/Build/source/texk/xdvipdfmx/configure.in b/Build/source/texk/xdvipdfmx/configure.in index 8ed5e6adfd7..25c088d7612 100644 --- a/Build/source/texk/xdvipdfmx/configure.in +++ b/Build/source/texk/xdvipdfmx/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(src/dvipdfmx.c) -AM_INIT_AUTOMAKE(xdvipdfmx, 0.4) +AM_INIT_AUTOMAKE(xdvipdfmx, 0.6) AM_CONFIG_HEADER(config.h) AM_MAINTAINER_MODE diff --git a/Build/source/texk/xdvipdfmx/src/bmpimage.c b/Build/source/texk/xdvipdfmx/src/bmpimage.c index 3897275ca06..813c74d5cca 100644 --- a/Build/source/texk/xdvipdfmx/src/bmpimage.c +++ b/Build/source/texk/xdvipdfmx/src/bmpimage.c @@ -145,8 +145,8 @@ bmp_include_image (pdf_ximage *ximage, FILE *fp) /* ignore biSizeImage */ p += 4; biXPelsPerMeter = ULONG_LE(p); p += 4; biYPelsPerMeter = ULONG_LE(p); p += 4; - info.xdpi = biXPelsPerMeter * 0.0254; /* convert pixels per meter to DPI */ - info.ydpi = biYPelsPerMeter * 0.0254; + info.xdensity = 72.0 / (biXPelsPerMeter * 0.0254); + info.ydensity = 72.0 / (biYPelsPerMeter * 0.0254); if (info.height < 0) { info.height = -info.height; flip = 0; diff --git a/Build/source/texk/xdvipdfmx/src/cff_dict.c b/Build/source/texk/xdvipdfmx/src/cff_dict.c index 875210ca090..37a27ef90f9 100644 --- a/Build/source/texk/xdvipdfmx/src/cff_dict.c +++ b/Build/source/texk/xdvipdfmx/src/cff_dict.c @@ -1,5 +1,5 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/cff_dict.c,v 1.13 2004/08/26 16:02:26 hirata Exp $ - +/* $Header: /home/cvsroot/dvipdfmx/src/cff_dict.c,v 1.15 2007/07/05 05:45:06 chofchof Exp $ + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, @@ -301,9 +301,6 @@ static void add_dict (cff_dict *dict, if (dict_operator[id].opname == NULL || argtype < 0) { *status = CFF_ERROR_PARSE_ERROR; return; - } else if (stack_top < 1) { - *status = CFF_ERROR_STACK_UNDERFLOW; - return; } if (dict->count >= dict->max) { @@ -317,20 +314,30 @@ static void add_dict (cff_dict *dict, argtype == CFF_TYPE_BOOLEAN || argtype == CFF_TYPE_SID || argtype == CFF_TYPE_OFFSET) { + /* check for underflow here, as exactly one operand is expected */ + if (stack_top < 1) { + *status = CFF_ERROR_STACK_UNDERFLOW; + return; + } stack_top--; (dict->entries)[dict->count].count = 1; (dict->entries)[dict->count].values = NEW(1, double); (dict->entries)[dict->count].values[0] = arg_stack[stack_top]; + dict->count += 1; } else { - (dict->entries)[dict->count].count = stack_top; - (dict->entries)[dict->count].values = NEW(stack_top, double); - while (stack_top > 0) { - stack_top--; - (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top]; + /* just ignore operator if there were no operands provided; + don't treat this as underflow (e.g. StemSnapV in TemporaLGCUni-Italic.otf) */ + if (stack_top > 0) { + (dict->entries)[dict->count].count = stack_top; + (dict->entries)[dict->count].values = NEW(stack_top, double); + while (stack_top > 0) { + stack_top--; + (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top]; + } + dict->count += 1; } } - dict->count += 1; *data += 1; return; @@ -430,7 +437,7 @@ static long pack_real (card8 *dest, long destlen, double value) { long e; int i = 0, pos = 2; -#define CFF_REAL_MAX_LEN 17 + char buffer[32]; if (destlen < 2) ERROR("%s: Buffer overflow.", CFF_DEBUG_STR); @@ -448,28 +455,19 @@ static long pack_real (card8 *dest, long destlen, double value) pos++; } - e = 0; - if (value >= 10.0) { - while (value >= 10.0) { - value /= 10.0; - e++; - } - } else if (value < 1.0) { - while (value < 1.0) { - value *= 10.0; - e--; - } - } + /* To avoid the problem with Mac OS X 10.4 Quartz, + * change the presion of the real numbers + * on June 27, 2007 for musix20.pfb */ + sprintf(buffer, "%.13g", value); - sprintf(work_buffer, "%1.14g", value); - for (i=0;i= '0' && work_buffer[i] <= '9') { - ch = work_buffer[i] - '0'; + } else if (buffer[i] >= '0' && buffer[i] <= '9') { + ch = buffer[i] - '0'; + } else if (buffer[i] == 'e') { + ch = (buffer[++i] == '-' ? 0x0c : 0x0b); } else { ERROR("%s: Invalid character.", CFF_DEBUG_STR); } @@ -485,53 +483,6 @@ static long pack_real (card8 *dest, long destlen, double value) pos++; } - if (e > 0) { - if (pos % 2) { - dest[pos/2] += 0x0b; - } else { - if (destlen < pos/2 + 1) - ERROR("%s: Buffer overflow.", CFF_DEBUG_STR); - dest[pos/2] = 0xb0; - } - pos++; - } else if (e < 0) { - if (pos % 2) { - dest[pos/2] += 0x0c; - } else { - if (destlen < pos/2 + 1) - ERROR("%s: Buffer overflow.", CFF_DEBUG_STR); - dest[pos/2] = 0xc0; - } - e *= -1; - pos++; - } - - if (e != 0) { - sprintf(work_buffer, "%ld", e); - for (i=0;i= '0' && work_buffer[i] <= '9') { - ch = work_buffer[i] - '0'; - } else { - ERROR("%s: Invalid character.", CFF_DEBUG_STR); - } - - if (destlen < pos/2 + 1) - ERROR("%s: Buffer overflow.", CFF_DEBUG_STR); - - if (pos % 2) { - dest[pos/2] += ch; - } else { - dest[pos/2] = (ch << 4); - } - pos++; - } - } - if (pos % 2) { dest[pos/2] += 0x0f; pos++; diff --git a/Build/source/texk/xdvipdfmx/src/cff_dict.h b/Build/source/texk/xdvipdfmx/src/cff_dict.h index 806fc4be50d..c74e1172e61 100644 --- a/Build/source/texk/xdvipdfmx/src/cff_dict.h +++ b/Build/source/texk/xdvipdfmx/src/cff_dict.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/cff_dict.h,v 1.6 2004/02/15 12:59:42 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/cff_dict.h,v 1.7 2007/06/30 01:18:13 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -26,7 +26,6 @@ #include "cff_types.h" #include "cff.h" -#define CFF_CIDCOUNT_DEFAULT 8720 #define CFF_NOMINALWIDTHX_DEFAULT 0.0 #define CFF_DEFAULTWIDTHX_DEFAULT 0.0 diff --git a/Build/source/texk/xdvipdfmx/src/cidtype0.c b/Build/source/texk/xdvipdfmx/src/cidtype0.c index ea471fae14c..6a79fab45e2 100644 --- a/Build/source/texk/xdvipdfmx/src/cidtype0.c +++ b/Build/source/texk/xdvipdfmx/src/cidtype0.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/cidtype0.c,v 1.34 2005/07/17 09:53:37 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/cidtype0.c,v 1.36 2007/06/30 01:18:13 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -182,7 +182,7 @@ add_CIDVMetrics (sfnt *sfont, pdf_obj *fontdict, vhea = tt_read_vhea_table(sfont); if (vhea && sfnt_find_table_pos(sfont, "vmtx") > 0) { sfnt_locate_table(sfont, "vmtx"); - vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics); + vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings); } /* * OpenType font must have OS/2 table. @@ -312,7 +312,7 @@ add_CIDMetrics (sfnt *sfont, pdf_obj *fontdict, hhea = tt_read_hhea_table(sfont); sfnt_locate_table(sfont, "hmtx"); - hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); add_CIDHMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); if (need_vmetrics) @@ -472,8 +472,8 @@ CIDFont_type0_dofont (CIDFont *font) long size, offset = 0; card8 *data; card16 num_glyphs, gid; - long cid; - card16 cid_count, cs_count, last_cid; + long cid, cid_count; + card16 cs_count, last_cid; int fd, prev_fd, parent_id; char *used_chars; unsigned char *CIDToGIDMap = NULL; @@ -530,9 +530,9 @@ CIDFont_type0_dofont (CIDFont *font) ERROR("Not a CIDFont."); if (cff_dict_known(cffont->topdict, "CIDCount")) { - cid_count = (card16) cff_dict_get(cffont->topdict, "CIDCount", 0); + cid_count = (long) cff_dict_get(cffont->topdict, "CIDCount", 0); } else { - cid_count = CFF_CIDCOUNT_DEFAULT; + cid_count = CID_MAX + 1; } cff_read_charsets(cffont); @@ -542,11 +542,6 @@ CIDFont_type0_dofont (CIDFont *font) cid = 0; last_cid = 0; num_glyphs = 0; for (cid = 0; cid <= CID_MAX; cid++) { if (is_used_char2(used_chars, cid)) { - if (cid >= cid_count) { - WARN("Glyph for CID %u missing in font \"%s\".", (CID) cid, font->ident); - used_chars[cid/8] &= ~(1 << (7 - (cid % 8))); - continue; - } gid = cff_charsets_lookup(cffont, cid); if (cid != 0 && gid == 0) { WARN("Glyph for CID %u missing in font \"%s\".", (CID) cid, font->ident); @@ -832,8 +827,8 @@ CIDFont_type0_open (CIDFont *font, const char *name, /* getting font info. from TrueType tables */ if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), 0)) == NULL) - ERROR("Could not obtain neccesary font info."); + = tt_get_fontdesc(sfont, &(opt->embed), 0, name)) == NULL) + ERROR("Could not obtain necessary font info."); if (opt->embed) { memmove(fontname + 7, fontname, strlen(fontname) + 1); @@ -1244,8 +1239,8 @@ CIDFont_type0_t1copen (CIDFont *font, const char *name, /* getting font info. from TrueType tables */ if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), 0)) == NULL) - ERROR("Could not obtain neccesary font info."); + = tt_get_fontdesc(sfont, &(opt->embed), 0, name)) == NULL) + ERROR("Could not obtain necessary font info."); if (opt->embed) { memmove(fontname + 7, fontname, strlen(fontname) + 1); diff --git a/Build/source/texk/xdvipdfmx/src/cidtype2.c b/Build/source/texk/xdvipdfmx/src/cidtype2.c index c9045e4b2d5..21eea1eaa86 100644 --- a/Build/source/texk/xdvipdfmx/src/cidtype2.c +++ b/Build/source/texk/xdvipdfmx/src/cidtype2.c @@ -1049,9 +1049,9 @@ CIDFont_type2_open (CIDFont *font, const char *name, pdf_new_name("Subtype"), pdf_new_name("CIDFontType2")); - font->descriptor = tt_get_fontdesc(sfont, &(opt->embed), 0); + font->descriptor = tt_get_fontdesc(sfont, &(opt->embed), 0, name); if (!font->descriptor) { - ERROR("Could not obtain neccesary font info."); + ERROR("Could not obtain necessary font info."); } if (opt->embed) { diff --git a/Build/source/texk/xdvipdfmx/src/dpxfile.c b/Build/source/texk/xdvipdfmx/src/dpxfile.c index 3a9920eaf72..ffb60233b98 100644 --- a/Build/source/texk/xdvipdfmx/src/dpxfile.c +++ b/Build/source/texk/xdvipdfmx/src/dpxfile.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/dpxfile.c,v 1.14 2005/12/18 14:56:47 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/dpxfile.c,v 1.15 2007/03/17 04:48:41 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -520,9 +520,9 @@ dpx_find_enc_file (const char *filename) } #else # if defined(__TDS_VERSION__) && __TDS_VERSION__ >= 0x200406L - fqpn = kpse_find_file(filename, kpse_enc_format, 0); + fqpn = kpse_find_file(q, kpse_enc_format, 0); # else - fqpn = kpse_find_file(filename, kpse_tex_ps_header_format, 0); + fqpn = kpse_find_file(q, kpse_tex_ps_header_format, 0); # endif #endif /* MIKTEX */ diff --git a/Build/source/texk/xdvipdfmx/src/dvi.c b/Build/source/texk/xdvipdfmx/src/dvi.c index cda84f8cda3..d56bbf8bbfc 100644 --- a/Build/source/texk/xdvipdfmx/src/dvi.c +++ b/Build/source/texk/xdvipdfmx/src/dvi.c @@ -61,6 +61,7 @@ #ifdef XETEX #include "pdfcolor.h" #include "pdfximage.h" +#include "pdfdev.h" #include "ft2build.h" #include FT_FREETYPE_H #include FT_TRUETYPE_TABLES_H @@ -98,6 +99,11 @@ static struct dvi_header static double dev_origin_x = 72.0, dev_origin_y = 770.0; +double get_origin (int x) +{ + return x ? dev_origin_x : dev_origin_y; +} + #define PHYSICAL 1 #define VIRTUAL 2 #define SUBFONT 3 @@ -122,6 +128,9 @@ static struct loaded_font FT_Face ft_face; unsigned short *glyph_widths; int layout_dir; + float extend; + float slant; + float embolden; #endif } *loaded_fonts = NULL; static int num_loaded_fonts = 0, max_loaded_fonts = 0; @@ -147,6 +156,9 @@ static struct font_def char *fam_name, *sty_name; /* only used for native fonts in XeTeX */ unsigned long rgba_color; /* only used for native fonts in XeTeX */ int layout_dir; /* 1 = vertical, 0 = horizontal */ + int extend; + int slant; + int embolden; #endif } *def_fonts = NULL; @@ -157,6 +169,9 @@ static struct font_def #define XDV_FLAG_COLORED 0x0200 #define XDV_FLAG_FEATURES 0x0400 #define XDV_FLAG_VARIATIONS 0x0800 +#define XDV_FLAG_EXTEND 0x1000 +#define XDV_FLAG_SLANT 0x2000 +#define XDV_FLAG_EMBOLDEN 0x4000 #endif static int num_def_fonts = 0, max_def_fonts = 0; @@ -600,6 +615,9 @@ read_font_record (SIGNED_QUAD tex_id) def_fonts[num_def_fonts].sty_name = NULL; def_fonts[num_def_fonts].rgba_color = 0xffffffff; def_fonts[num_def_fonts].layout_dir = 0; + def_fonts[num_def_fonts].extend = 0x00010000; /* 1.0 */ + def_fonts[num_def_fonts].slant = 0; + def_fonts[num_def_fonts].embolden = 0; #endif num_def_fonts++; @@ -663,6 +681,18 @@ read_native_font_record (SIGNED_QUAD tex_id) (void)get_unsigned_quad(dvi_file); /* skip axis and value for each variation setting */ WARN("Variation axes are not supported; ignoring variation settings for font %s.\n", font_name); } + if (flags & XDV_FLAG_EXTEND) + def_fonts[num_def_fonts].extend = get_signed_quad(dvi_file); + else + def_fonts[num_def_fonts].extend = 0x00010000; + if (flags & XDV_FLAG_SLANT) + def_fonts[num_def_fonts].slant = get_signed_quad(dvi_file); + else + def_fonts[num_def_fonts].slant = 0; + if (flags & XDV_FLAG_EMBOLDEN) + def_fonts[num_def_fonts].embolden = get_signed_quad(dvi_file); + else + def_fonts[num_def_fonts].embolden = 0; num_def_fonts++; } else { ERROR("Unknown native_font flags."); @@ -828,6 +858,12 @@ dvi_link_annot (int flag) link_annot = flag; } +int +dvi_is_tracking_boxes(void) +{ + return (compute_boxes && link_annot && marked_depth >= tagged_depth); +} + void dvi_do_special (const void *buffer, UNSIGNED_QUAD size) { @@ -1003,12 +1039,12 @@ dvi_locate_font (const char *tfm_name, spt_t ptsize) #ifdef XETEX static int dvi_locate_native_font (const char *ps_name, const char *fam_name, - const char *sty_name, spt_t ptsize, int layout_dir) + const char *sty_name, spt_t ptsize, int layout_dir, int extend, int slant, int embolden) { int cur_id = -1; fontmap_rec *mrec; int i; - char *fontmap_key = malloc(strlen(ps_name) + 3); + char *fontmap_key = malloc(strlen(ps_name) + 40); // CHECK this is enough if (verbose) MESG("<%s(%s:%s)@%.2fpt", ps_name, fam_name, sty_name, ptsize * dvi2pts); @@ -1017,10 +1053,10 @@ dvi_locate_native_font (const char *ps_name, const char *fam_name, cur_id = num_loaded_fonts++; - sprintf(fontmap_key, "%s/%c", ps_name, layout_dir == 0 ? 'H' : 'V'); + sprintf(fontmap_key, "%s/%c/%d/%d/%d", ps_name, layout_dir == 0 ? 'H' : 'V', extend, slant, embolden); mrec = pdf_lookup_fontmap_record(fontmap_key); if (mrec == NULL) { - if (pdf_load_native_font(ps_name, fam_name, sty_name, layout_dir) == -1) { + if (pdf_load_native_font(ps_name, fam_name, sty_name, layout_dir, extend, slant, embolden) == -1) { ERROR("Cannot proceed without the \"native\" font: %s (%s %s)...", ps_name, fam_name, sty_name); } @@ -1043,6 +1079,9 @@ dvi_locate_native_font (const char *ps_name, const char *fam_name, } loaded_fonts[cur_id].glyph_widths = mrec->opt.glyph_widths; loaded_fonts[cur_id].layout_dir = layout_dir; + loaded_fonts[cur_id].extend = mrec->opt.extend; + loaded_fonts[cur_id].slant = mrec->opt.slant; + loaded_fonts[cur_id].embolden = mrec->opt.bold; if (verbose) MESG(">"); @@ -1678,7 +1717,10 @@ do_fnt (SIGNED_QUAD tex_id) def_fonts[i].fam_name, def_fonts[i].sty_name, def_fonts[i].point_size, - def_fonts[i].layout_dir); + def_fonts[i].layout_dir, + def_fonts[i].extend, + def_fonts[i].slant, + def_fonts[i].embolden); } else { font_id = dvi_locate_font(def_fonts[i].font_name, def_fonts[i].point_size); @@ -1734,6 +1776,7 @@ static void do_xxx (UNSIGNED_QUAD size) { UNSIGNED_QUAD i; +#if 0 Ubyte *buffer; /* FIXME - no need for new buffer here */ buffer = NEW(size+1, Ubyte); @@ -1742,6 +1785,10 @@ do_xxx (UNSIGNED_QUAD size) } dvi_do_special(buffer, size); RELEASE(buffer); +#else + dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size); + dvi_page_buf_index += size; +#endif } static void @@ -1864,6 +1911,9 @@ do_native_font_def (int scanning) } } +/* globals initialized by fontmap.c when it opens freetype */ +extern FT_Int ft_major, ft_minor, ft_patch; + static void do_glyph_array (int yLocsPresent) { @@ -1889,20 +1939,23 @@ do_glyph_array (int yLocsPresent) if (font->rgba_color != 0xffffffff) { pdf_color color; - pdf_color_push(); +// pdf_color_push(); pdf_color_rgbcolor(&color, (double)((unsigned char)(font->rgba_color >> 24) & 0xff) / 255, (double)((unsigned char)(font->rgba_color >> 16) & 0xff) / 255, (double)((unsigned char)(font->rgba_color >> 8) & 0xff) / 255); - pdf_dev_setcolor(&color, 0); /* stroke color */ - pdf_dev_setcolor(&color, 1); /* fill color */ + pdf_color_push(&color, &color); +// pdf_dev_setcolor(&color, 0); /* stroke color */ +// pdf_dev_setcolor(&color, 1); /* fill color */ } for (i = 0; i < slen; i++) { glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */ if (glyph_id < font->ft_face->num_glyphs) { if (font->glyph_widths[glyph_id] == 0xffff) { - if (FT_IS_SFNT(font->ft_face)) { - /* CFF driver of freetype does not set vertical metrics correctly, + if (FT_IS_SFNT(font->ft_face) + && ((ft_major < 2) || ((ft_major == 2) && (ft_minor < 2)))) { + /* prior to version 2.2.0, + CFF driver of freetype does not set vertical metrics correctly, so we'll read the metrics directly */ TT_HoriHeader *dir_hea; /* vhea structure is identical */ dir_hea = FT_Get_Sfnt_Table(font->ft_face, (font->layout_dir == 0) @@ -1919,13 +1972,14 @@ do_glyph_array (int yLocsPresent) font->glyph_widths[glyph_id] = 0; } else { - FT_Load_Glyph(font->ft_face, glyph_id, FT_LOAD_NO_SCALE); + FT_Load_Glyph(font->ft_face, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); font->glyph_widths[glyph_id] = (font->layout_dir == 0) ? font->ft_face->glyph->metrics.horiAdvance : font->ft_face->glyph->metrics.vertAdvance; } } glyph_width = (double)font->size * (double)font->glyph_widths[glyph_id] / (double)font->ft_face->units_per_EM; + glyph_width = glyph_width * font->extend; if (compute_boxes && link_annot && marked_depth >= tagged_depth) { pdf_rect rect; height = (double)font->size * (double)font->ft_face->ascender / (double)font->ft_face->units_per_EM; @@ -1994,9 +2048,7 @@ do_pic_file() transform is a 3x2 affine transform matrix expressed in fixed-point values */ - if (page_no > 0) - --page_no; /* convert 1-based page number to 0-based index */ - xobj_id = pdf_ximage_findresource(path, page_no, pdf_box); + xobj_id = pdf_ximage_findresource(path, page_no/*, pdf_box*/); if (xobj_id >= 0) { /* FIXME: this seems to work for 72dpi JPEGs, but isn't right for others; need to take the actual image resolution into account in pdf_dev_put_image, @@ -2393,26 +2445,39 @@ read_length (double *vp, double mag, char **pp, char *endptr) v = atof(q); RELEASE(q); + skip_white(&p, endptr); q = parse_c_ident(&p, endptr); if (q) { - if (strlen(q) > strlen("true") && + char *qq = q; /* remember this for RELEASE, because q may be advanced */ + if (strlen(q) >= strlen("true") && !memcmp(q, "true", strlen("true"))) { u /= mag != 0.0 ? mag : 1.0; /* inverse magnify */ q += strlen("true"); } - for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++); - switch (k) { - case K_UNIT__PT: u *= 72.0 / 72.27; break; - case K_UNIT__IN: u *= 72.0; break; - case K_UNIT__CM: u *= 72.0 / 2.54 ; break; - case K_UNIT__MM: u *= 72.0 / 25.4 ; break; - case K_UNIT__BP: u *= 1.0 ; break; - default: - WARN("Unknown unit of measure: %s", q); + if (strlen(q) == 0) { /* "true" was a separate word from the units */ + RELEASE(qq); + skip_white(&p, endptr); + qq = q = parse_c_ident(&p, endptr); + } + if (q) { + for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++); + switch (k) { + case K_UNIT__PT: u *= 72.0 / 72.27; break; + case K_UNIT__IN: u *= 72.0; break; + case K_UNIT__CM: u *= 72.0 / 2.54 ; break; + case K_UNIT__MM: u *= 72.0 / 25.4 ; break; + case K_UNIT__BP: u *= 1.0 ; break; + default: + WARN("Unknown unit of measure: %s", q); + error = -1; + break; + } + RELEASE(qq); + } + else { + WARN("Missing unit of measure after \"true\""); error = -1; - break; } - RELEASE(q); } *vp = v * u; *pp = p; @@ -2425,7 +2490,10 @@ scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, const ch { char *q, *p = (char *) buf; char *endptr; - int ns_pdf = 0, error = 0; + int ns_pdf = 0, ns_xtx = 0, error = 0; + double tmp; + extern double paper_width, paper_height; + extern char landscape_mode; endptr = p + size; @@ -2441,6 +2509,15 @@ scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, const ch q = parse_c_ident(&p, endptr); ns_pdf = 1; } } + else if (q && !strcmp(q, "x")) { + skip_white(&p, endptr); + if (p < endptr && *p == ':') { + p++; + skip_white(&p, endptr); + RELEASE(q); + q = parse_c_ident(&p, endptr); ns_xtx = 1; + } + } skip_white(&p, endptr); if (q) { @@ -2454,21 +2531,26 @@ scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, const ch else { skip_white(&p, endptr); if (!strcmp(kp, "width")) { - error = read_length(wd, dvi_tell_mag(), &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); if (!error) - *wd *= dvi_tell_mag(); + *wd = tmp * dvi_tell_mag(); } else if (!strcmp(kp, "height")) { - error = read_length(ht, dvi_tell_mag(), &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); if (!error) - *ht *= dvi_tell_mag(); + *ht = tmp * dvi_tell_mag(); } else if (!strcmp(kp, "xoffset")) { - error = read_length(xo, dvi_tell_mag(), &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); if (!error) - *xo *= dvi_tell_mag(); + *xo = tmp * dvi_tell_mag(); } else if (!strcmp(kp, "yoffset")) { - error = read_length(yo, dvi_tell_mag(), &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); if (!error) - *yo *= dvi_tell_mag(); + *yo = tmp * dvi_tell_mag(); + } else if (!strcmp(kp, "default")) { + *wd = paper_width; + *ht = paper_height; + *lm = landscape_mode; + *xo = *yo = 72.0; } RELEASE(kp); } @@ -2482,19 +2564,26 @@ scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, const ch qchr = *p; p++; skip_white(&p, endptr); } - error = read_length(wd, 1.0, &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); if (!error) { + *wd = tmp * dvi_tell_mag(); skip_white(&p, endptr); if (p < endptr && *p == ',') { p++; skip_white(&p, endptr); } - error = read_length(ht, 1.0, &p, endptr); + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); + if (!error) + *ht = tmp * dvi_tell_mag(); skip_white(&p, endptr); } if (!error && qchr) { /* Check if properly quoted */ if (p >= endptr || *p != qchr) error = -1; } + if (error == 0) { + paper_width = *wd; + paper_height = *ht; + } } RELEASE(q); } diff --git a/Build/source/texk/xdvipdfmx/src/dvi.h b/Build/source/texk/xdvipdfmx/src/dvi.h index b25661eaf37..60f9ad7c8f5 100644 --- a/Build/source/texk/xdvipdfmx/src/dvi.h +++ b/Build/source/texk/xdvipdfmx/src/dvi.h @@ -30,6 +30,8 @@ /* spt_t */ #include "pdfdev.h" +extern double get_origin (int x); + extern void dvi_set_verbose (void); /* returns scale (dvi2pts) */ @@ -90,4 +92,7 @@ extern void dvi_compute_boxes (int flag); extern void dvi_do_special (const void *buffer, UNSIGNED_QUAD size); +/* allow other modules (pdfdev) to ask whether we're collecting box areas */ +int dvi_is_tracking_boxes(void); + #endif /* _DVI_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/dvipdfmx.c b/Build/source/texk/xdvipdfmx/src/dvipdfmx.c index 30e5a07d144..2eeb6e10972 100644 --- a/Build/source/texk/xdvipdfmx/src/dvipdfmx.c +++ b/Build/source/texk/xdvipdfmx/src/dvipdfmx.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/dvipdfmx.c,v 1.47 2006/12/11 13:23:26 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/dvipdfmx.c,v 1.52 2007/05/18 05:19:00 chofchof Exp $ This is xdvipdfmx, an extended version of... @@ -70,6 +70,9 @@ static long opt_flags = 0; #define OPT_TPIC_TRANSPARENT_FILL (1 << 1) #define OPT_CIDFONT_FIXEDPITCH (1 << 2) #define OPT_FONTMAP_FIRST_MATCH (1 << 3) +#define OPT_NO_OBJSTM (1 << 4) + +static int do_objstm; static char ignore_colors = 0; static double annot_grow = 0.0; @@ -89,11 +92,12 @@ static unsigned key_bits = 40; static unsigned permission = 0x003C; /* Page device */ -static double paper_width = 595.0; -static double paper_height = 842.0; +double paper_width = 595.0; /* not static, we allow dvi.c to access them */ +double paper_height = 842.0; +char landscape_mode = 0; + static double x_offset = 72.0; static double y_offset = 72.0; -static char landscape_mode = 0; int always_embed = 0; /* always embed fonts, regardless of licensing flags */ @@ -130,12 +134,12 @@ set_default_pdf_filename(void) } static void -usage (void) +usage (int exit_code) { fprintf (stdout, "\nThis is %s-%s by Jonathan Kew and Jin-Hwan Cho,\n", PACKAGE, VERSION); fprintf (stdout, "an extended version of DVIPDFMx, which in turn was\n"); fprintf (stdout, "an extended version of dvipdfm-0.13.2c developed by Mark A. Wicks.\n"); - fprintf (stdout, "\nCopyright (c) 2006 SIL International and Jin-Hwan Cho.\n"); + fprintf (stdout, "\nCopyright (c) 2006-2008 SIL International and Jin-Hwan Cho.\n"); fprintf (stdout, "\nThis is free software; you can redistribute it and/or modify\n"); fprintf (stdout, "it under the terms of the GNU General Public License as published by\n"); fprintf (stdout, "the Free Software Foundation; either version 2 of the License, or\n"); @@ -143,44 +147,54 @@ usage (void) fprintf (stdout, "\nUsage: xdvipdfmx [options] xdvfile\n"); fprintf (stdout, "-c \t\tIgnore color specials (for B&W printing)\n"); fprintf (stdout, "-d number\tSet PDF decimal digits (0-5) [2]\n"); - fprintf (stdout, "-l \t\tLandscape mode\n"); #if 0 /* Not supported */ fprintf (stdout, "-e \t\tDisable partial font embedding [default is enabled]\n"); #endif fprintf (stdout, "-f filename\tSet font map file name [t1fonts.map]\n"); + fprintf (stdout, "-g dimension\tAnnotation \"grow\" amount [0.0in]\n"); + fprintf (stdout, "-h \t\tShow this help message\n"); + fprintf (stdout, "-l \t\tLandscape mode\n"); fprintf (stdout, "-m number\tSet additional magnification\n"); fprintf (stdout, "-o filename\tSet output file name [dvifile.pdf]\n"); fprintf (stdout, "-p papersize\tSet papersize [a4]\n"); + fprintf (stdout, "-q \t\tBe quiet\n"); fprintf (stdout, "-r resolution\tSet resolution (in DPI) for raster fonts [600]\n"); fprintf (stdout, "-s pages\tSelect page ranges (-)\n"); +#ifndef NO_THUMBNAIL fprintf (stdout, "-t \t\tEmbed thumbnail images\n"); +#endif /* !NO_THUMBNAIL */ fprintf (stdout, "-x dimension\tSet horizontal offset [1.0in]\n"); fprintf (stdout, "-y dimension\tSet vertical offset [1.0in]\n"); fprintf (stdout, "-z number \tSet zlib compression level (0-9) [9]\n"); - fprintf (stdout, "-v \tBe verbose\n"); - fprintf (stdout, "-vv \tBe more verbose\n"); + fprintf (stdout, "-v \t\tBe verbose\n"); + fprintf (stdout, "-vv\t\tBe more verbose\n"); fprintf (stdout, "-C number\tSpecify miscellaneous option flags [0]:\n"); fprintf (stdout, "\t\t 0x0001 reserved\n"); fprintf (stdout, "\t\t 0x0002 Use semi-transparent filling for tpic shading command,\n"); - fprintf (stdout, "\t\t instead of opaque gray color. (requires PDF 1.4)\n"); + fprintf (stdout, "\t\t\t instead of opaque gray color. (requires PDF 1.4)\n"); fprintf (stdout, "\t\t 0x0004 Treat all CIDFont as fixed-pitch font.\n"); fprintf (stdout, "\t\t 0x0008 Do not replace duplicate fontmap entries.\n"); + fprintf (stdout, "\t\t 0x0010 Do not create object streams.\n"); fprintf (stdout, "\t\tPositive values are always ORed with previously given flags.\n"); fprintf (stdout, "\t\tAnd negative values replace old values.\n"); - fprintf (stdout, "-E \tAlways try to embed fonts, regardless of licensing flags.\n"); + fprintf (stdout, "-D template\tPS->PDF conversion command line template [none]\n"); + fprintf (stdout, "-E \t\tAlways try to embed fonts, regardless of licensing flags.\n"); + fprintf (stdout, "-K number\tEncryption key bits [40]\n"); + fprintf (stdout, "-M \t\tExperimental mps-to-pdf mode\n"); fprintf (stdout, "-O number\tSet maximum depth of open bookmark items [0]\n"); fprintf (stdout, "-P number\tSet permission flags for PDF encryption [0x003C]\n"); - fprintf (stdout, "-S \tEnable PDF encryption\n"); - fprintf (stdout, "-T \tEmbed thumbnail images. Remove images files when finished.\n"); - fprintf (stdout, "-M \tExperimental mps-to-pdf mode\n"); - fprintf (stdout, "-V number\tSet PDF minor version [3]\n"); + fprintf (stdout, "-S \t\tEnable PDF encryption\n"); +#ifndef NO_THUMBNAIL + fprintf (stdout, "-T \t\tEmbed thumbnail images. Remove images files when finished.\n"); +#endif /* !NO_THUMBNAIL */ + fprintf (stdout, "-V number\tSet PDF minor version [4]\n"); fprintf (stdout, "\nAll dimensions entered on the command line are \"true\" TeX dimensions.\n"); fprintf (stdout, "Argument of \"-s\" lists physical page ranges separated by commas, e.g., \"-s 1-3,5-6\"\n"); fprintf (stdout, "Papersize is specified by paper format (e.g., \"a4\") or by w,h (e.g., \"20cm,30cm\").\n"); - exit(1); + exit(exit_code); } @@ -209,25 +223,38 @@ read_length (double *vp, char **pp, char *endptr) v = atof(q); RELEASE(q); + skip_white(&p, endptr); q = parse_c_ident(&p, endptr); if (q) { - if (strlen(q) > strlen("true") && + char *qq = q; + if (strlen(q) >= strlen("true") && !memcmp(q, "true", strlen("true"))) { q += strlen("true"); /* just skip "true" */ } - for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++); - switch (k) { - case K_UNIT__PT: u *= 72.0 / 72.27; break; - case K_UNIT__IN: u *= 72.0; break; - case K_UNIT__CM: u *= 72.0 / 2.54 ; break; - case K_UNIT__MM: u *= 72.0 / 25.4 ; break; - case K_UNIT__BP: u *= 1.0 ; break; - default: - WARN("Unknown unit of measure: %s", q); + if (strlen(q) == 0) { + RELEASE(qq); + skip_white(&p, endptr); + qq = q = parse_c_ident(&p, endptr); + } + if (q) { + for (k = 0; _ukeys[k] && strcmp(_ukeys[k], q); k++); + switch (k) { + case K_UNIT__PT: u *= 72.0 / 72.27; break; + case K_UNIT__IN: u *= 72.0; break; + case K_UNIT__CM: u *= 72.0 / 2.54 ; break; + case K_UNIT__MM: u *= 72.0 / 25.4 ; break; + case K_UNIT__BP: u *= 1.0 ; break; + default: + WARN("Unknown unit of measure: %s", q); + error = -1; + break; + } + RELEASE(qq); + } + else { + WARN("Missing unit of measure after \"true\""); error = -1; - break; } - RELEASE(q); } *vp = v * u; *pp = p; @@ -322,7 +349,7 @@ select_pages (const char *pagespec) /* It doesn't work as expected (due to dvi filename). */ #define CHECK_ARG(n,m) if (argc < (n) + 1) {\ fprintf (stderr, "\nMissing %s after \"-%c\".\n", (m), *flag);\ - usage();\ + usage(1);\ } static void @@ -429,9 +456,9 @@ do_args (int argc, char *argv[]) ver_minor = atoi(argv[1]); POP_ARG(); } - if (ver_minor < 3 || ver_minor > 5) { - WARN("PDF version 1.%d not supported. (1.3 used instead)", ver_minor); - ver_minor = 3; + if (ver_minor < 3 || ver_minor > 6) { + WARN("PDF version 1.%d not supported. (1.4 used instead)", ver_minor); + ver_minor = 4; } pdf_set_version((unsigned) ver_minor); } @@ -505,9 +532,12 @@ do_args (int argc, char *argv[]) case 'E': always_embed = 1; break; + case 'h': + usage(0); + break; default: fprintf (stderr, "Unknown option in \"%s\"", flag); - usage(); + usage(1); break; } } @@ -525,12 +555,13 @@ do_args (int argc, char *argv[]) pdf_enc_set_verbose(); pdf_obj_set_verbose(); dpx_file_set_verbose(); + tt_aux_set_verbose(); } } if (argc > 1) { fprintf(stderr, "Multiple dvi filenames?"); - usage(); + usage(1); } else if (argc > 0) { /* * The only legitimate way to have argc == 0 here is @@ -572,8 +603,10 @@ read_config_file (const char *config) if (!(fp = MFOPEN (fullname, FOPEN_R_MODE))) { WARN("Could not open config file \"%s\".", fullname); + RELEASE(fullname); return; } + RELEASE(fullname); while ((start = mfgets (work_buffer, WORK_BUFFER_SIZE, fp)) != NULL) { char *argv[2]; int argc; @@ -641,6 +674,7 @@ do_dvi_pages (void) { long page_no, page_count, i, step; double page_width, page_height; + double init_paper_width, init_paper_height; pdf_rect mediabox; spc_exec_at_begin_document(); @@ -655,8 +689,8 @@ do_dvi_pages (void) num_page_ranges = 1; } - page_width = paper_width; - page_height = paper_height; + init_paper_width = page_width = paper_width; + init_paper_height = page_height = paper_height; page_count = 0; mediabox.llx = 0.0; @@ -664,7 +698,6 @@ do_dvi_pages (void) mediabox.urx = paper_width; mediabox.ury = paper_height; - pdf_doc_set_creator (dvi_comment()); pdf_doc_set_mediabox(0, &mediabox); /* Root node */ for (i = 0; i < num_page_ranges && dvi_npages() > 0; i++) { @@ -679,6 +712,7 @@ do_dvi_pages (void) char lm; /* Users want to change page size even after page is started! */ + page_width = paper_width; page_height = paper_height; w = page_width; h = page_height; lm = landscape_mode; xo = x_offset; yo = y_offset; dvi_scan_paper_size(page_no, &w, &h, &xo, &yo, &lm); @@ -694,8 +728,8 @@ do_dvi_pages (void) x_offset = xo; y_offset = yo; } - if (page_width != paper_width || - page_height != paper_height) { + if (page_width != init_paper_width || + page_height != init_paper_height) { mediabox.llx = 0.0; mediabox.lly = 0.0; mediabox.urx = page_width; @@ -781,12 +815,6 @@ main (int argc, char *argv[]) { double dvi2pts; - if (argc < 2) { - fprintf(stderr, "No dvi filename specified."); - usage(); - return 1; - } - #ifdef MIKTEX miktex_initialize(); #else @@ -818,26 +846,24 @@ main (int argc, char *argv[]) pdf_font_set_dpi(font_dpi); if (dvi_filename == NULL) { - if (pdf_filename == NULL) { - WARN("No dvi or pdf filename specified."); - usage(); - return 1; - } - else { + if (verbose) + MESG("No dvi filename specified, reading standard input.\n"); + if (pdf_filename == NULL) if (verbose) - MESG("No dvi filename specified, reading standard input."); - } + MESG("No pdf filename specified, writing to standard output.\n"); } - if (pdf_filename == NULL) + if (pdf_filename == NULL && dvi_filename != NULL) set_default_pdf_filename(); if (do_encryption) { pdf_enc_set_passwd(key_bits, permission, dvi_filename, pdf_filename); - if (key_bits > 40) + if (key_bits > 40 && pdf_get_version() < 4) pdf_set_version(4); } + do_objstm = !(opt_flags & OPT_NO_OBJSTM); + if (mp_mode) { x_offset = 0.0; y_offset = 0.0; @@ -848,19 +874,22 @@ main (int argc, char *argv[]) if (dvi2pts == 0.0) ERROR("dvi_init() failed!"); + pdf_doc_set_creator(dvi_comment()); + dvi_scan_paper_size(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode); if (landscape_mode) { SWAP(paper_width, paper_height); } } - MESG("%s -> %s\n", dvi_filename == NULL ? "stdin" : dvi_filename, pdf_filename); + MESG("%s -> %s\n", dvi_filename == NULL ? "stdin" : dvi_filename, + pdf_filename == NULL ? "stdout" : pdf_filename); /* Set default paper size here so that all page's can inherite it. * annot_grow: Margin of annotation. * bookmark_open: Miximal depth of open bookmarks. */ - pdf_open_document(pdf_filename, + pdf_open_document(pdf_filename, do_encryption, do_objstm, paper_width, paper_height, annot_grow, bookmark_open); /* Ignore_colors placed here since diff --git a/Build/source/texk/xdvipdfmx/src/epdf.c b/Build/source/texk/xdvipdfmx/src/epdf.c index c041bb1e7b5..d01421d7635 100644 --- a/Build/source/texk/xdvipdfmx/src/epdf.c +++ b/Build/source/texk/xdvipdfmx/src/epdf.c @@ -1,28 +1,27 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/epdf.c,v 1.14 2004/09/12 11:57:49 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/epdf.c,v 1.18 2008/02/13 20:22:21 matthias Exp $ - This is dvipdfm, a DVI to PDF translator. - Copyright (C) 1998, 1999 by Mark A. Wicks + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team + + Copyright (C) 1998, 1999 by Mark A. Wicks This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - The author may be contacted via the e-mail address - - mwicks@kettering.edu + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ - /* * Concatinating content streams are only supported for streams that only uses * single FlateDecode filter, i.e., @@ -49,6 +48,8 @@ #include "pdfdev.h" #include "pdfximage.h" +#include "pdfdraw.h" +#include "pdfparse.h" #include "epdf.h" @@ -60,44 +61,55 @@ static void print_bbox_info (pdf_obj *rect, const char *type, pdf_obj *crop_box static int rect_equal (pdf_obj *rect1, pdf_obj *rect2); /* - * From PDF Reference 4th ed. + * From PDFReference15_v6.pdf (p.119 and p.834) * - * MediaBox rectangle (Required; inheritable) + * MediaBox rectangle (Required; inheritable) * - * A rectangle, expressed in default user space units, defining the boundaries of the - * physical medium on which the page is intended to be displayed or printed. + * The media box defines the boundaries of the physical medium on which the + * page is to be printed. It may include any extended area surrounding the + * finished page for bleed, printing marks, or other such purposes. It may + * also include areas close to the edges of the medium that cannot be marked + * because of physical limitations of the output device. Content falling + * outside this boundary can safely be discarded without affecting the + * meaning of the PDF file. * - * CropBox rectangle (Optional; inheritable) + * CropBox rectangle (Optional; inheritable) * - * A rectangle, expressed in default user space units, defining the visible region of - * default user space. When the page is displayed or printed, its contents are to be - * clipped (cropped) to this rectangle and then imposed on the output medium in some - * implementation-defined manner. - * Default value: the value of MediaBox. + * The crop box defines the region to which the contents of the page are to be + * clipped (cropped) when displayed or printed. Unlike the other boxes, the + * crop box has no defined meaning in terms of physical page geometry or + * intended use; it merely imposes clipping on the page contents. However, + * in the absence of additional information (such as imposition instructions + * specified in a JDF or PJTF job ticket), the crop box will determine how + * the page’s contents are to be positioned on the output medium. The default + * value is the page’s media box. * - * BleedBox rectangle (Optional; PDF 1.3) + * BleedBox rectangle (Optional; PDF 1.3) * - * A rectangle, expressed in default user space units, defining the region to which the - * contents of the page should be clipped when output in a production environment. - * Default value: the value of CropBox. + * The bleed box (PDF 1.3) defines the region to which the contents of the + * page should be clipped when output in a production environment. This may + * include any extra “bleed area” needed to accommodate the physical + * limitations of cutting, folding, and trimming equipment. The actual printed + * page may include printing marks that fall outside the bleed box. + * The default value is the page’s crop box. * - * TrimBox rectangle (Optional; PDF 1.3) + * TrimBox rectangle (Optional; PDF 1.3) * - * A rectangle, expressed in default user space units, defining the intended dimensions - * of the finished page after trimming. - * Default value: the value of CropBox. + * The trim box (PDF 1.3) defines the intended dimensions of the finished page + * after trimming. It may be smaller than the media box, to allow for + * production-related content such as printing instructions, cut marks, or + * color bars. The default value is the page’s crop box. * - * ArtBox rectangle (Optional; PDF 1.3) + * ArtBox rectangle (Optional; PDF 1.3) * - * A rectangle, expressed in default user space units, defining the extent of the page's - * meaningful content (including potential white space) as intended by the page's creator - * Default value: the value of CropBox. + * The art box (PDF 1.3) defines the extent of the page’s meaningful content + * (including potential white space) as intended by the page’s creator. + * The default value is the page’s crop box. * - * Rotate integer (Optional; inheritable) + * Rotate integer (Optional; inheritable) * - * The number of degrees by which the page should be rotated clockwise when displayed or - * printed. The value must be a multiple of 90. - * Default value: 0. + * The number of degrees by which the page should be rotated clockwise when + * displayed or printed. The value must be a multiple of 90. Default value: 0. */ static int @@ -132,16 +144,12 @@ print_bbox_info (pdf_obj *rect, const char *type, pdf_obj *crop_box) pdf_number_value(pdf_get_array(crop_box, 3))); } -int -pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_box) +static pdf_obj* +pdf_get_page_obj (FILE *image_file, long page_no, pdf_obj **ret_bbox, pdf_obj **ret_resources) { - xform_info info; - pdf_obj *contents, *contents_ref, *contents_dict; - pdf_obj *page_tree; - pdf_obj *bbox, *resources, *rotate, *matrix; - int page_count; + pdf_obj *page_tree, *resources = NULL, *rotate = NULL, *bbox = NULL; + long page_count, page_idx; - pdf_ximage_init_form_info(&info); /* * Get Page Tree. */ @@ -153,22 +161,22 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ trailer = pdf_open(image_file); if (!trailer) { WARN("Trailer not found! Corrupt PDF file?"); - pdf_close(); - return -1; + return NULL; } if (pdf_lookup_dict(trailer, "Encrypt")) { WARN("This PDF document is encrypted."); pdf_release_obj(trailer); - pdf_close(); - return -1; + return NULL; } catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); - if (!catalog) { - WARN("Catalog isn't where I expect it."); - pdf_close(); - return -1; + if (!PDF_OBJ_DICTTYPE(catalog)) { + WARN("Can't read document catalog."); + pdf_release_obj(trailer); + if (catalog) + pdf_release_obj(catalog); + return NULL; } pdf_release_obj(trailer); @@ -179,8 +187,7 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ if (tmp && pdf_boolean_value(tmp)) { WARN("Tagged PDF not supported."); pdf_release_obj(catalog); - pdf_close(); - return -1; + return NULL; } } @@ -189,70 +196,63 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ } if (!page_tree) { WARN("Page tree not found."); - pdf_close(); - return -1; + return NULL; } - page_count = (int)pdf_number_value(pdf_lookup_dict(page_tree, "Count")); - if (page_index >= page_count) - page_index = page_count - 1; - else if (page_index < 0) { - page_index = page_count + page_index; - if (page_index < 0) - page_index = 0; + /* + * Negative page numbers are counted from the back. + */ + { + long count = pdf_number_value(pdf_lookup_dict(page_tree, "Count")); + page_idx = page_no + (page_no >= 0 ? -1 : count); + if (page_idx < 0 || page_idx >= count) { + WARN("Page %ld does not exist.", page_no); + page_idx = page_idx < 0 ? 0 : count - 1; + } + page_no = page_idx + 1; } /* - * Seek required page. Get Media/Crop Box. + * Seek correct page. Get Media/Crop Box. * Media box and resources can be inherited. */ { pdf_obj *kids_ref, *kids; - pdf_obj *crop_box; + pdf_obj *crop_box = NULL; pdf_obj *tmp; - tmp = pdf_lookup_dict(page_tree, "MediaBox"); - bbox = tmp ? pdf_deref_obj(tmp) : NULL; - tmp = pdf_lookup_dict(page_tree, "CropBox"); - crop_box = tmp ? pdf_deref_obj(tmp) : NULL; - tmp = pdf_lookup_dict(page_tree, "Rotate"); - rotate = tmp ? pdf_deref_obj(tmp) : NULL; - tmp = pdf_lookup_dict(page_tree, "Resources"); resources = tmp ? pdf_deref_obj(tmp) : pdf_new_dict(); - while ((kids_ref = pdf_lookup_dict(page_tree, "Kids")) != NULL) { - /* page_tree is a Pages object: figure out which of its Kids we need */ - int kid_index; - kids = pdf_deref_obj(kids_ref); - for (kid_index = 0; ; ++kid_index) { - pdf_release_obj(page_tree); - page_tree = pdf_deref_obj(pdf_get_array(kids, kid_index)); - /* page_tree might be a Page or another Pages node */ - tmp = pdf_lookup_dict(page_tree, "Count"); - if (tmp) { - /* it's a subtree: check if the required page is within this tree */ - page_count = (int)pdf_number_value(tmp); - if (page_index < page_count) - break; - else - page_index -= page_count; - } - else { - /* it's a page: break if it's the one we want */ - if (page_index == 0) - break; - else - --page_index; - } - } - pdf_release_obj(kids); - + while (1) { + long kids_length, i; + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) { if (bbox) pdf_release_obj(bbox); bbox = tmp; } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox")))) { + if (!rect_equal(tmp, bbox)) { + if (bbox) + pdf_release_obj(bbox); + bbox = tmp; + } + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox")))) { + if (!rect_equal(tmp, bbox)) { + if (bbox) + pdf_release_obj(bbox); + bbox = tmp; + } + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox")))) { + if (!rect_equal(tmp, bbox)) { + if (bbox) + pdf_release_obj(bbox); + bbox = tmp; + } + } if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { if (crop_box) pdf_release_obj(crop_box); @@ -271,116 +271,192 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ pdf_release_obj(resources); resources = tmp; } + + kids_ref = pdf_lookup_dict(page_tree, "Kids"); + if (!kids_ref) + break; + kids = pdf_deref_obj(kids_ref); + kids_length = pdf_array_length(kids); + + for (i = 0; i < kids_length; i++) { + long count; + + pdf_release_obj(page_tree); + page_tree = pdf_deref_obj(pdf_get_array(kids, i)); + + tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); + if (tmp) { + /* Pages object */ + count = pdf_number_value(tmp); + pdf_release_obj(tmp); + } else + /* Page object */ + count = 1; + + if (page_idx < count) + break; + + page_idx -= count; + } + + pdf_release_obj(kids); + + if (i == kids_length) { + WARN("Page %ld not found! Broken PDF file?", page_no); + if (bbox) + pdf_release_obj(bbox); + if (crop_box) + pdf_release_obj(crop_box); + if (rotate) + pdf_release_obj(rotate); + pdf_release_obj(resources); + pdf_release_obj(page_tree); + return NULL; + } } if (crop_box) { pdf_release_obj(bbox); bbox = crop_box; } } + if (!bbox) { WARN("No BoundingBox information available."); pdf_release_obj(page_tree); pdf_release_obj(resources); if (rotate) pdf_release_obj(rotate); - pdf_close(); - return -1; + return NULL; + } + + if (rotate) { + if (pdf_number_value(rotate) != 0.0) + WARN("<< /Rotate %d >> found. (Not supported yet)", (int)pdf_number_value(rotate)); + pdf_release_obj(rotate); + rotate = NULL; } - /* - * BleedBox, TrimBox, and ArtBox are not inheritable. - */ - { - pdf_obj *tmp; + if (ret_bbox != NULL) + *ret_bbox = bbox; + if (ret_resources != NULL) + *ret_resources = resources; - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox")))) { - if (!rect_equal(tmp, bbox)) { - print_bbox_info(tmp, "TrimBox", bbox); - if (bbox) - pdf_release_obj(bbox); - bbox = tmp; - } - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox")))) { - if (!rect_equal(tmp, bbox)) { - print_bbox_info(tmp, "BleedBox", bbox); - if (bbox) - pdf_release_obj(bbox); - bbox = tmp; + return page_tree; +} + +static pdf_obj* +pdf_get_page_content (pdf_obj* page) +{ + pdf_obj *contents, *content_new; + + contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents")); + if (!contents) + return NULL; + + if (pdf_obj_typeof(contents) == PDF_NULL) { + /* empty page */ + pdf_release_obj(contents); + /* TODO: better don't include anything if the page is empty */ + contents = pdf_new_stream(0); + } else if (PDF_OBJ_ARRAYTYPE(contents)) { + /* + * Concatenate all content streams. + */ + pdf_obj *content_seg, *content_new; + int idx = 0; + content_new = pdf_new_stream(STREAM_COMPRESS); + for (;;) { + content_seg = pdf_deref_obj(pdf_get_array(contents, idx)); + if (!content_seg) + break; + else if (PDF_OBJ_NULLTYPE(content_seg)) { + /* Silently ignore. */ + } else if (!PDF_OBJ_STREAMTYPE(content_seg)) { + WARN("Page content not a stream object. Broken PDF file?"); + pdf_release_obj(content_seg); + pdf_release_obj(content_new); + pdf_release_obj(contents); + return NULL; + } else if (concat_stream(content_new, content_seg) < 0) { + WARN("Could not handle content stream with multiple segments."); + pdf_release_obj(content_seg); + pdf_release_obj(content_new); + pdf_release_obj(contents); + return NULL; } + pdf_release_obj(content_seg); + idx++; } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox")))) { - if (!rect_equal(tmp, bbox)) { - print_bbox_info(tmp, "ArtBox", bbox); - if (bbox) - pdf_release_obj(bbox); - bbox = tmp; - } + pdf_release_obj(contents); + contents = content_new; + } else { + if (!PDF_OBJ_STREAMTYPE(contents)) { + WARN("Page content not a stream object. Broken PDF file?"); + pdf_release_obj(contents); + return NULL; } - if (rotate) { - if (pdf_number_value(rotate) != 0.0) - WARN("<< /Rotate %d >> found. (Not supported yet)", (int)pdf_number_value(rotate)); - pdf_release_obj(rotate); - rotate = NULL; + /* Flate the contents if necessary. */ + content_new = pdf_new_stream(STREAM_COMPRESS); + if (concat_stream(content_new, contents) < 0) { + WARN("Could not handle a content stream."); + pdf_release_obj(contents); + pdf_release_obj(content_new); + return NULL; } - - info.bbox.llx = pdf_number_value(pdf_get_array(bbox, 0)); - info.bbox.lly = pdf_number_value(pdf_get_array(bbox, 1)); - info.bbox.urx = pdf_number_value(pdf_get_array(bbox, 2)); - info.bbox.ury = pdf_number_value(pdf_get_array(bbox, 3)); + pdf_release_obj(contents); + contents = content_new; } + return contents; +} + +int +pdf_include_page (pdf_ximage *ximage, FILE *image_file) +{ + xform_info info; + pdf_obj *contents, *contents_dict; + pdf_obj *page_tree; + pdf_obj *matrix; + pdf_obj *bbox = NULL, *resources = NULL; + long page_no, page_idx; + + pdf_ximage_init_form_info(&info); + /* - * Handle page content stream. - * page_tree is now set to the first page. + * Get Page Tree. */ - contents_ref = contents = NULL; - { - contents = pdf_deref_obj(pdf_lookup_dict(page_tree, "Contents")); - pdf_release_obj(page_tree); - if (!contents) { - pdf_release_obj(bbox); - pdf_close(); - return -1; - } + page_no = pdf_ximage_get_page(ximage); + if (page_no == 0) + page_no = 1; - /* - * Concatinate all content streams. - */ - if (PDF_OBJ_ARRAYTYPE(contents)) { - pdf_obj *content_seg, *content_new; - int idx = 0; - content_new = pdf_new_stream(STREAM_COMPRESS); - for (;;) { - content_seg = pdf_deref_obj(pdf_get_array(contents, idx)); - if (!content_seg) - break; - else if (PDF_OBJ_NULLTYPE(content_seg)) { - /* Silently ignore. */ - } else if (!PDF_OBJ_STREAMTYPE(content_seg)) { - WARN("Page content not a stream object. Broken PDF file?"); - pdf_release_obj(content_new); - pdf_release_obj(bbox); - pdf_close(); - return -1; - } else if (concat_stream(content_new, content_seg) < 0) { - WARN("Could not handle content stream with multiple segment."); - pdf_release_obj(content_new); - pdf_release_obj(bbox); - pdf_close(); - return -1; - } - pdf_release_obj(content_seg); - idx++; - } - pdf_release_obj(contents); - contents = content_new; - } - if (!contents) { - pdf_release_obj(bbox); - pdf_close(); - return -1; - } + page_tree = pdf_get_page_obj(image_file, page_no, &bbox, &resources); + if (page_tree == NULL) { + pdf_close(); + return -1; + } + + if (bbox != NULL) { + pdf_obj *tmp; + + tmp = pdf_deref_obj(pdf_get_array(bbox, 0)); + info.bbox.llx = pdf_number_value(tmp); + pdf_release_obj(tmp); + tmp = pdf_deref_obj(pdf_get_array(bbox, 1)); + info.bbox.lly = pdf_number_value(tmp); + pdf_release_obj(tmp); + tmp = pdf_deref_obj(pdf_get_array(bbox, 2)); + info.bbox.urx = pdf_number_value(tmp); + pdf_release_obj(tmp); + tmp = pdf_deref_obj(pdf_get_array(bbox, 3)); + info.bbox.ury = pdf_number_value(tmp); + pdf_release_obj(tmp); + } + + contents = pdf_get_page_content(page_tree); + pdf_release_obj(page_tree); + if (contents == NULL) { + pdf_close(); + return -1; } { @@ -389,6 +465,9 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ tmp = pdf_import_object(resources); pdf_release_obj(resources); resources = tmp; + tmp = pdf_import_object(bbox); + pdf_release_obj(bbox); + bbox = tmp; } pdf_close(); @@ -423,6 +502,315 @@ pdf_include_page (pdf_ximage *ximage, FILE *image_file, int page_index, int pdf_ return 0; } +typedef enum { + OP_SETCOLOR = 1, + OP_CLOSEandCLIP = 2, + OP_CLIP = 3, + OP_CONCATMATRIX = 4, + OP_SETCOLORSPACE = 5, + OP_RECTANGLE = 6, + OP_CURVETO = 7, + OP_CLOSEPATH = 8, + OP_LINETO = 9, + OP_MOVETO = 10, + OP_NOOP = 11, + OP_GSAVE = 12, + OP_GRESTORE = 13, + OP_CURVETO1 = 14, + OP_CURVETO2 = 15, + OP_UNKNOWN = 16 +} pdf_opcode; + +static struct operator +{ + const char *token; + int opcode; +} pdf_operators[] = { + {"SCN", OP_SETCOLOR}, + {"b*", OP_CLOSEandCLIP}, + {"B*", OP_CLIP}, + {"cm", OP_CONCATMATRIX}, + {"CS", OP_SETCOLORSPACE}, + {"f*", 0}, + {"gs", -1}, + {"re", OP_RECTANGLE}, + {"rg", -3}, + {"RG", -3}, + {"sc", OP_SETCOLOR}, + {"SC", OP_SETCOLOR}, + {"W*", OP_CLIP}, + {"b", OP_CLOSEandCLIP}, + {"B", OP_CLIP}, + {"c", OP_CURVETO}, + {"d", -2}, + {"f", 0}, + {"F", 0}, + {"g", -1}, + {"G", -1}, + {"h", OP_CLOSEPATH}, + {"i", -1}, + {"j", -1}, + {"J", -1}, + {"k", -4}, + {"K", -4}, + {"l", OP_LINETO}, + {"m", OP_MOVETO}, + {"M", -1}, + {"n", OP_NOOP}, + {"q", OP_GSAVE}, + {"Q", OP_GRESTORE}, + {"s", OP_CLOSEandCLIP}, + {"S", OP_CLIP}, + {"v", OP_CURVETO1}, + {"w", -1}, + {"W", OP_CLIP}, + {"y", OP_CURVETO2} +}; + + +int +pdf_copy_clip (FILE *image_file, int pageNo, double x_user, double y_user) +{ + pdf_obj *page_tree, *contents; + int depth = 0, top = -1; + char *clip_path, *temp, *end_path; + pdf_tmatrix M; + double stack[6]; + pdf_coord p0, p1, p2; + pdf_rect bbox; + + pdf_dev_currentmatrix(&M); + pdf_invertmatrix(&M); + M.e += x_user; M.f += y_user; + page_tree = pdf_get_page_obj (image_file, pageNo, NULL, NULL); + if (!page_tree) { + pdf_close(); + return -1; + } + + contents = pdf_get_page_content(page_tree); + pdf_release_obj(page_tree); + if (!contents) { + pdf_close(); + return -1; + } + + pdf_doc_add_page_content(" ", 1); + + clip_path = malloc(pdf_stream_length(contents) + 1); + strncpy(clip_path, (char*)pdf_stream_dataptr(contents), pdf_stream_length(contents)); + end_path = clip_path + pdf_stream_length(contents); + depth = 0; + + for (; clip_path < end_path; clip_path++) { + int color_dimen; + char *token; + skip_white(&clip_path, end_path); + if (clip_path == end_path) + break; + if (depth > 1) { + if (*clip_path == 'q') + depth++; + if (*clip_path == 'Q') + depth--; + parse_ident(&clip_path, end_path); + continue; + } else if (*clip_path == '-' + || *clip_path == '+' + || *clip_path == '.' + || isdigit(*clip_path)) { + stack[++top] = strtod(clip_path, &temp); + clip_path = temp; + } else if (*clip_path == '[') { + /* Ignore, but put a dummy value on the stack (in case of d operator) */ + parse_pdf_array(&clip_path, end_path); + stack[++top] = 0; + } else if (*clip_path == '/') { + if (strncmp("/DeviceGray", clip_path, 11) == 0 + || strncmp("/Indexed", clip_path, 8) == 0 + || strncmp("/CalGray", clip_path, 8) == 0) { + color_dimen = 1; + continue; + } + else if (strncmp("/DeviceRGB", clip_path, 10) == 0 + || strncmp("/CalRGB", clip_path, 7) == 0 + || strncmp("/Lab", clip_path, 4) == 0) { + color_dimen = 3; + continue; + } + else if (strncmp("/DeviceCMYK", clip_path, 11) == 0) { + color_dimen = 4; + continue; + } + else { + clip_path++; + parse_ident(&clip_path, end_path); + skip_white(&clip_path, end_path); + token = parse_ident(&clip_path, end_path); + if (strcmp(token, "gs") == 0) { + continue; + } + return -1; + } + } else { + int j; + pdf_tmatrix T; + pdf_coord p0, p1, p2, p3; + + token = parse_ident(&clip_path, end_path); + for (j = 0; j < sizeof(pdf_operators) / sizeof(pdf_operators[0]); j++) + if (strcmp(token, pdf_operators[j].token) == 0) + break; + if (j == sizeof(pdf_operators) / sizeof(pdf_operators[0])) { + return -1; + } + switch (pdf_operators[j].opcode) { + case 0: + case -1: + case -2: + case -3: + case -4: + /* Just pop the stack and do nothing. */ + top += pdf_operators[j].opcode; + if (top < -1) + return -1; + break; + case OP_SETCOLOR: + top -= color_dimen; + if (top < -1) + return -1; + break; + case OP_CLOSEandCLIP: + pdf_dev_closepath(); + case OP_CLIP: +#if 0 + pdf_dev_clip(); +#else + pdf_dev_flushpath('W', PDF_FILL_RULE_NONZERO); +#endif + break; + case OP_CONCATMATRIX: + if (top < 5) + return -1; + T.f = stack[top--]; + T.e = stack[top--]; + T.d = stack[top--]; + T.c = stack[top--]; + T.b = stack[top--]; + T.a = stack[top--]; + pdf_concatmatrix(&M, &T); + break; + case OP_SETCOLORSPACE: + /* Do nothing. */ + break; + case OP_RECTANGLE: + if (top < 3) + return -1; + p1.y = stack[top--]; + p1.x = stack[top--]; + p0.y = stack[top--]; + p0.x = stack[top--]; + if (M.b == 0 && M.c == 0) { + pdf_tmatrix M0; + M0.a = M.a; M0.b = M.b; M0.c = M.c; M0.d = M.d; + M0.e = 0; M0.f = 0; + pdf_dev_transform(&p0, &M); + pdf_dev_transform(&p1, &M0); + pdf_dev_rectadd(p0.x, p0.y, p1.x, p1.y); + } else { + p2.x = p0.x + p1.x; p2.y = p0.y + p1.y; + p3.x = p0.x; p3.y = p0.y + p1.y; + p1.x += p0.x; p1.y = p0.y; + pdf_dev_transform(&p0, &M); + pdf_dev_transform(&p1, &M); + pdf_dev_transform(&p2, &M); + pdf_dev_transform(&p3, &M); + pdf_dev_moveto(p0.x, p0.y); + pdf_dev_lineto(p1.x, p1.y); + pdf_dev_lineto(p2.x, p2.y); + pdf_dev_lineto(p3.x, p3.y); + pdf_dev_closepath(); + } + break; + case OP_CURVETO: + if (top < 5) + return -1; + p0.y = stack[top--]; + p0.x = stack[top--]; + pdf_dev_transform(&p0, &M); + p1.y = stack[top--]; + p1.x = stack[top--]; + pdf_dev_transform(&p1, &M); + p2.y = stack[top--]; + p2.x = stack[top--]; + pdf_dev_transform(&p2, &M); + pdf_dev_curveto(p2.x, p2.y, p1.x, p1.y, p0.x, p0.y); + break; + case OP_CLOSEPATH: + pdf_dev_closepath(); + break; + case OP_LINETO: + if (top < 1) + return -1; + p0.y = stack[top--]; + p0.x = stack[top--]; + pdf_dev_transform(&p0, &M); + pdf_dev_lineto(p0.x, p0.y); + break; + case OP_MOVETO: + if (top < 1) + return -1; + p0.y = stack[top--]; + p0.x = stack[top--]; + pdf_dev_transform(&p0, &M); + pdf_dev_moveto(p0.x, p0.y); + break; + case OP_NOOP: + pdf_doc_add_page_content(" n", 2); + break; + case OP_GSAVE: + depth++; + break; + case OP_GRESTORE: + depth--; + break; + case OP_CURVETO1: + if (top < 3) + return -1; + p0.y = stack[top--]; + p0.x = stack[top--]; + pdf_dev_transform(&p0, &M); + p1.y = stack[top--]; + p1.x = stack[top--]; + pdf_dev_transform(&p1, &M); + pdf_dev_vcurveto(p1.x, p1.y, p0.x, p0.y); + break; + case OP_CURVETO2: + if (top < 3) + return -1; + p0.y = stack[top--]; + p0.x = stack[top--]; + pdf_dev_transform(&p0, &M); + p1.y = stack[top--]; + p1.x = stack[top--]; + pdf_dev_transform(&p1, &M); + pdf_dev_ycurveto(p1.x, p1.y, p0.x, p0.y); + break; + default: + return -1; + } + } + } + clip_path = end_path; + clip_path -= pdf_stream_length(contents); + free(clip_path); + + pdf_release_obj(contents); + pdf_close(); + + return 0; +} + #define WBUF_SIZE 4096 #if HAVE_ZLIB static int diff --git a/Build/source/texk/xdvipdfmx/src/epdf.h b/Build/source/texk/xdvipdfmx/src/epdf.h index d99f3a63856..234eaed5136 100644 --- a/Build/source/texk/xdvipdfmx/src/epdf.h +++ b/Build/source/texk/xdvipdfmx/src/epdf.h @@ -34,6 +34,8 @@ #define pdfbox_trim 4 #define pdfbox_art 5 -extern int pdf_include_page (pdf_ximage *ximage, FILE *file, int page_index, int pdf_box); +extern int pdf_copy_clip (FILE *image_file, int page_index, double x_user, double y_user); +//extern int pdf_include_page (pdf_ximage *ximage, FILE *file, int page_index, int pdf_box); +extern int pdf_include_page (pdf_ximage *ximage, FILE *file); #endif /* _EPDF_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/fontmap.c b/Build/source/texk/xdvipdfmx/src/fontmap.c index 58b47aa8fde..7bbf8bb2b8a 100644 --- a/Build/source/texk/xdvipdfmx/src/fontmap.c +++ b/Build/source/texk/xdvipdfmx/src/fontmap.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/fontmap.c,v 1.33 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/fontmap.c,v 1.35 2007/01/21 15:17:53 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -980,7 +980,8 @@ pdf_load_fontmap_file (const char *filename, int mode) #ifdef XETEX static int -pdf_insert_native_fontmap_record (const char *name, const char *path, int index, FT_Face face, int layout_dir) +pdf_insert_native_fontmap_record (const char *name, const char *path, int index, FT_Face face, + int layout_dir, int extend, int slant, int embolden) { char *fontmap_key; fontmap_rec *mrec; @@ -988,8 +989,8 @@ pdf_insert_native_fontmap_record (const char *name, const char *path, int index, ASSERT(name); ASSERT(path || face); - fontmap_key = malloc(strlen(name) + 3); - sprintf(fontmap_key, "%s/%c", name, layout_dir == 0 ? 'H' : 'V'); + fontmap_key = malloc(strlen(name) + 40); // CHECK + sprintf(fontmap_key, "%s/%c/%d/%d/%d", name, layout_dir == 0 ? 'H' : 'V', extend, slant, embolden); if (verbose) MESG("opt.flags |= FONTMAP_OPT_VERT; fill_in_defaults(mrec, fontmap_key); + + mrec->opt.extend = extend / 65536.0; + mrec->opt.slant = slant / 65536.0; + mrec->opt.bold = embolden / 65536.0; + pdf_insert_fontmap_record(mrec->map_name, mrec); pdf_clear_fontmap_record(mrec); RELEASE(mrec); @@ -1020,7 +1026,7 @@ pdf_insert_native_fontmap_record (const char *name, const char *path, int index, static FT_Library ftLib; static int -pdf_load_native_font_from_path(const char *ps_name, int layout_dir) +pdf_load_native_font_from_path(const char *ps_name, int layout_dir, int extend, int slant, int embolden) { const char *p; char *filename = NEW(strlen(ps_name), char); @@ -1059,15 +1065,20 @@ pdf_load_native_font_from_path(const char *ps_name, int layout_dir) } if (error == 0) - return pdf_insert_native_fontmap_record(ps_name, filename, index, face, layout_dir); + return pdf_insert_native_fontmap_record(ps_name, filename, index, face, + layout_dir, extend, slant, embolden); else return error; } +FT_Int ft_major; /* global so that dvi.c can check the version */ +FT_Int ft_minor; +FT_Int ft_patch; + int pdf_load_native_font (const char *ps_name, const char *fam_name, const char *sty_name, - int layout_dir) + int layout_dir, int extend, int slant, int embolden) { static int sInitialized = 0; int error = -1; @@ -1079,11 +1090,12 @@ pdf_load_native_font (const char *ps_name, WARN("FreeType initialization failed."); return error; } + FT_Library_Version(ftLib, &ft_major, &ft_minor, &ft_patch); sInitialized = 1; } if (ps_name[0] == '[') { - error = pdf_load_native_font_from_path(ps_name, layout_dir); + error = pdf_load_native_font_from_path(ps_name, layout_dir, extend, slant, embolden); } else { ATSFontRef fontRef; @@ -1105,7 +1117,8 @@ pdf_load_native_font (const char *ps_name, FT_Face face; ftErr = FT_New_Face_From_FSSpec(ftLib, &pathSpec, index, &face); if (ftErr == 0) { - error = pdf_insert_native_fontmap_record(ps_name, NULL, 0, face, layout_dir); + error = pdf_insert_native_fontmap_record(ps_name, NULL, 0, face, + layout_dir, extend, slant, embolden); } } } @@ -1132,11 +1145,12 @@ pdf_load_native_font (const char *ps_name, WARN("FreeType initialization failed."); return error; } + FT_Library_Version(ftLib, &ft_major, &ft_minor, &ft_patch); sInitialized = 1; } if (ps_name[0] == '[') { - error = pdf_load_native_font_from_path(ps_name, layout_dir); + error = pdf_load_native_font_from_path(ps_name, layout_dir, extend, slant, embolden); } else { os = FcObjectSetBuild(FC_FILE, FC_INDEX, FC_FAMILY, FC_STYLE, NULL); @@ -1159,7 +1173,8 @@ pdf_load_native_font (const char *ps_name, FT_New_Face(ftLib, (char*)path, index, &face); name = (char *)FT_Get_Postscript_Name(face); if (!strcmp(name, ps_name)) { - error = pdf_insert_native_fontmap_record(ps_name, (char*)path, index, face, layout_dir); + error = pdf_insert_native_fontmap_record(ps_name, (char*)path, index, face, + layout_dir, extend, slant, embolden); /* don't dispose of the FT_Face, as we'll be using it to retrieve font data */ break; } diff --git a/Build/source/texk/xdvipdfmx/src/fontmap.h b/Build/source/texk/xdvipdfmx/src/fontmap.h index 4069cf69e52..b2ce2645397 100644 --- a/Build/source/texk/xdvipdfmx/src/fontmap.h +++ b/Build/source/texk/xdvipdfmx/src/fontmap.h @@ -101,7 +101,7 @@ extern fontmap_rec *pdf_lookup_fontmap_record (const char *kp); #ifdef XETEX extern int pdf_load_native_font (const char *ps_name, const char *fam_name, const char *sty_name, - int layout_dir); + int layout_dir, int extend, int slant, int embolden); #endif #endif /* _FONTMAP_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/jpegimage.c b/Build/source/texk/xdvipdfmx/src/jpegimage.c index a5f1986815c..6aea61213a3 100644 --- a/Build/source/texk/xdvipdfmx/src/jpegimage.c +++ b/Build/source/texk/xdvipdfmx/src/jpegimage.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/jpegimage.c,v 1.8 2004/09/05 13:30:05 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/jpegimage.c,v 1.9 2007/05/18 05:19:01 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -113,6 +113,7 @@ typedef enum { JM_EXP = 0xdf, JM_APP0 = 0xe0, + JM_APP1 = 0xe1, JM_APP2 = 0xe2, JM_APP14 = 0xee, JM_APP15 = 0xef, @@ -334,8 +335,33 @@ jpeg_include_image (pdf_ximage *ximage, FILE *fp) info.bits_per_component = j_info.bits_per_component; info.num_components = j_info.num_components; - info.xdpi = j_info.xdpi; - info.ydpi = j_info.ydpi; +#define IS_JFIF(j) ((j).flags & HAVE_APPn_JFIF) + if (IS_JFIF(j_info)) { + int i; + for (i = 0; i < j_info.num_appn; i++) { + if (j_info.appn[i].marker == JM_APP0 && j_info.appn[i].app_sig == JS_APPn_JFIF) + break; + } + if (i < j_info.num_appn) { + struct JPEG_APPn_JFIF *app_data = (struct JPEG_APPn_JFIF *)j_info.appn[i].app_data; + switch (app_data->units) { + case 1: /* pixels per inch */ + info.xdensity = 72.0 / app_data->Xdensity; + info.ydensity = 72.0 / app_data->Ydensity; + break; + case 2: /* pixels per centimeter */ + info.xdensity = 72.0 / 2.54 / app_data->Xdensity; + info.ydensity = 72.0 / 2.54 / app_data->Ydensity; + break; + default: + break; + } + } + } + else { /* resolution data from EXIF is handled here */ + info.xdensity = 72.0 / j_info.xdpi; + info.ydensity = 72.0 / j_info.ydpi; + } pdf_ximage_set_image(ximage, &info, stream); JPEG_info_clear(&j_info); @@ -504,6 +530,133 @@ read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp, unsigned short length) return 7; } +static unsigned long +read_exif_bytes(unsigned char **p, int n, int b) +{ + unsigned long rval = 0; + unsigned char *pp = *p; + if (b) { + switch (n) { + case 4: + rval += *pp++; rval <<= 8; + rval += *pp++; rval <<= 8; + case 2: + rval += *pp++; rval <<= 8; + rval += *pp; + break; + } + } + else { + pp += n; + switch (n) { + case 4: + rval += *--pp; rval <<= 8; + rval += *--pp; rval <<= 8; + case 2: + rval += *--pp; rval <<= 8; + rval += *--pp; + break; + } + } + *p += n; + return rval; +} + +static unsigned short +read_APP1_Exif (struct JPEG_info *j_info, FILE *fp, unsigned short length) +{ + /* this doesn't save the data, just reads the tags we need */ + /* based on info from http://www.exif.org/Exif2-2.PDF */ + unsigned char *buffer = NEW(length, unsigned char); + unsigned char *p, *rp; + unsigned char *tiff_header; + char bigendian; + int i; + double rational_value; + int num_fields, tag, type, count, value, num, den; + double xres = 72.0; + double yres = 72.0; + double res_unit = 1.0; + fread(buffer, length, 1, fp); + p = buffer; + while ((p < buffer + length) && (*p == 0)) + ++p; + tiff_header = p; + if ((*p == 'M') && (*(p+1) == 'M')) + bigendian = 1; + else if ((*p == 'I') && (*(p+1) == 'I')) + bigendian = 0; + else + goto err; + p += 2; + i = read_exif_bytes(&p, 2, bigendian); + if (i != 42) + goto err; + i = read_exif_bytes(&p, 4, bigendian); + p = tiff_header + i; + num_fields = read_exif_bytes(&p, 2, bigendian); + while (num_fields-- > 0) { + tag = read_exif_bytes(&p, 2, bigendian); + type = read_exif_bytes(&p, 2, bigendian); + count = read_exif_bytes(&p, 4, bigendian); + switch (type) { + case 1: /* byte */ + value = *p++; + p += 3; + break; + case 3: /* short */ + value = read_exif_bytes(&p, 2, bigendian); + p += 2; + break; + case 4: /* long */ + case 9: /* slong */ + value = read_exif_bytes(&p, 4, bigendian); + break; + case 5: /* rational */ + case 10: /* srational */ + value = read_exif_bytes(&p, 4, bigendian); + rp = tiff_header + value; + num = read_exif_bytes(&rp, 4, bigendian); + den = read_exif_bytes(&rp, 4, bigendian); + break; + case 7: /* undefined */ + value = *p++; + p += 3; + break; + case 2: /* ascii */ + default: + p += 4; + break; + } + switch (tag) { + case 282: /* x res */ + if (den != 0) + xres = num / den; + break; + case 283: /* y res */ + if (den != 0) + yres = num / den; + break; + case 296: /* res unit */ + switch (value) { + case 2: + res_unit = 1.0; + break; + case 3: + res_unit = 2.54; + break; + } + } + } + + j_info->xdpi = xres * res_unit; + j_info->ydpi = yres * res_unit; + +err: + RELEASE(buffer); + return length; +} + static unsigned short read_APP0_JFIF (struct JPEG_info *j_info, FILE *fp, unsigned short length) { @@ -701,6 +854,17 @@ JPEG_scan_file (struct JPEG_info *j_info, FILE *fp) } seek_relative(fp, length); break; + case JM_APP1: + if (length > 5) { + if (fread(app_sig, sizeof(char), 5, fp) != 5) + return -1; + length -= 5; + if (!memcmp(app_sig, "Exif\000", 5)) { + length -= read_APP1_Exif(j_info, fp, length); + } + } + seek_relative(fp, length); + break; case JM_APP2: if (length >= 14) { if (fread(app_sig, sizeof(char), 12, fp) != 12) diff --git a/Build/source/texk/xdvipdfmx/src/mpost.c b/Build/source/texk/xdvipdfmx/src/mpost.c index 6875d5d573e..3a36080effb 100644 --- a/Build/source/texk/xdvipdfmx/src/mpost.c +++ b/Build/source/texk/xdvipdfmx/src/mpost.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/mpost.c,v 1.36 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/mpost.c,v 1.38 2007/11/22 16:57:08 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -260,7 +260,8 @@ skip_prolog (char **start, char *end) save = *start; while (*start < end) { - skip_white(start, end); + if (**start != '%') + skip_white(start, end); if (*start >= end) break; if (!strncmp(*start, "%%EndProlog", 11)) { @@ -1189,8 +1190,7 @@ do_operator (const char *token, double x_user, double y_user) pdf_color_cmykcolor(&color, values[0], values[1], values[2], values[3]); - pdf_dev_setcolor(&color, 0); - pdf_dev_setcolor(&color, 1); + pdf_dev_set_color(&color); } break; case SETGRAY: @@ -1198,8 +1198,7 @@ do_operator (const char *token, double x_user, double y_user) error = pop_get_numbers(values, 1); if (!error) { pdf_color_graycolor(&color, values[0]); - pdf_dev_setcolor(&color, 0); - pdf_dev_setcolor(&color, 1); + pdf_dev_set_color(&color); } break; case SETRGBCOLOR: @@ -1207,8 +1206,7 @@ do_operator (const char *token, double x_user, double y_user) if (!error) { pdf_color_rgbcolor(&color, values[0], values[1], values[2]); - pdf_dev_setcolor(&color, 0); - pdf_dev_setcolor(&color, 1); + pdf_dev_set_color(&color); } break; @@ -1462,7 +1460,7 @@ mps_exec_inline (char **p, char *endptr, autorotate = pdf_dev_get_param(PDF_DEV_PARAM_AUTOROTATE); pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, 0); - pdf_color_push(); /* ... */ + //pdf_color_push(); /* ... */ /* Comment in dvipdfm: * Remember that x_user and y_user are off by 0.02 % @@ -1470,7 +1468,7 @@ mps_exec_inline (char **p, char *endptr, pdf_dev_moveto(x_user, y_user); error = mp_parse_body(p, endptr, x_user, y_user); - pdf_color_pop(); /* ... */ + //pdf_color_pop(); /* ... */ pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, autorotate); pdf_dev_set_dirmode(dirmode); @@ -1535,7 +1533,7 @@ mps_include_page (const char *ident, FILE *fp) dirmode = pdf_dev_get_dirmode(); autorotate = pdf_dev_get_param(PDF_DEV_PARAM_AUTOROTATE); pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, 0); - pdf_color_push(); + //pdf_color_push(); form_id = pdf_doc_begin_grabbing(ident, 0.0, 0.0, &(info.bbox)); @@ -1562,7 +1560,7 @@ mps_include_page (const char *ident, FILE *fp) pdf_doc_end_grabbing(); - pdf_color_pop(); + //pdf_color_pop(); pdf_dev_set_param(PDF_DEV_PARAM_AUTOROTATE, autorotate); pdf_dev_set_dirmode(dirmode); diff --git a/Build/source/texk/xdvipdfmx/src/pdfcolor.c b/Build/source/texk/xdvipdfmx/src/pdfcolor.c index 8d9341302c1..ab908079ec3 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfcolor.c +++ b/Build/source/texk/xdvipdfmx/src/pdfcolor.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfcolor.c,v 1.13 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfcolor.c,v 1.14 2007/11/22 11:45:39 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -212,115 +212,28 @@ compare_color (const pdf_color *color1, const pdf_color *color2) } #endif -static int -valid_color_values (pdf_color *validated, const pdf_color *color) +int +pdf_color_is_valid (pdf_color *color) { - int i, num_components = 0; + int i, num_components; num_components = color->num_components; if (num_components != 1 && num_components != 3 && num_components != 4) { ERROR("Only RGB/CMYK/Gray currently supported."); - return -1; + return 0; } for (i = 0; i < num_components; i++) { if (color->values[i] < 0.0 || color->values[i] > 1.0) { WARN("Invalid color value: %g", color->values[i]); - return -1; - } else { - validated->values[i] = color->values[i]; - } - } - validated->num_components = color->num_components; - - return 0; -} - -int -pdf_dev_currentcolor (pdf_color *color, int is_fill) -{ - ASSERT(color); - - if (is_fill) { - memcpy(color, ¤t_fill, sizeof(pdf_color)); - } else { - memcpy(color, ¤t_stroke, sizeof(pdf_color)); - } - - return 0; -} - -int -pdf_dev_setcolor (const pdf_color *color, int is_fill) -{ - int len = 0, colormode; - int i; - char format_buffer[128]; - pdf_color validated; - - if (!color) { - WARN("No color specified."); - return -1; - } - - colormode = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - if (!colormode) { - WARN("setcolor ignored. (Ignore color option set)"); - return 0; - } - - if (valid_color_values(&validated, color) < 0) { - return -1; - } - -#if 0 - /* There are much problems in this :( */ - if (is_fill) { - if (!compare_color(&validated, ¤t_fill)) { - return 0; - } - } else { - if (!compare_color(&validated, ¤t_stroke)) { return 0; } } -#endif - - graphics_mode(); - - for (i = 0; i < validated.num_components; i++) { - len = sprintf(format_buffer, " %g", ROUND(validated.values[i], 0.01)); - pdf_doc_add_page_content(format_buffer, len); - } - - switch (validated.num_components) { - case 3: - pdf_doc_add_page_content((is_fill ? " rg" : " RG"), 3); - break; - case 4: - pdf_doc_add_page_content((is_fill ? " k" : " K" ), 2); - break; - case 1: - pdf_doc_add_page_content((is_fill ? " g" : " G" ), 2); - break; - default: - ERROR("Only RGB/CMYK/Gray currently supported."); - return -1; - break; - } - - if (is_fill) { - memcpy(¤t_fill, &validated, sizeof(pdf_color)); - } else { - memcpy(¤t_stroke, &validated, sizeof(pdf_color)); - } - - return 0; + return 1; } - /* Dvipdfm special */ pdf_color default_color = { 1, @@ -330,116 +243,77 @@ pdf_color default_color = { void pdf_color_set_default (const pdf_color *color) { - ASSERT(color); - - memcpy(&default_color, color, sizeof(pdf_color)); + pdf_color_copycolor(&default_color, color); } - -/* - * Having color stack here is wrong. - * dvi.c or XXX_special should treat this. - */ #define DEV_COLOR_STACK_MAX 128 static struct { - int next; + int current; pdf_color stroke[DEV_COLOR_STACK_MAX]; pdf_color fill[DEV_COLOR_STACK_MAX]; } color_stack = { 0, }; -/* BUG (20060330): color change does not effect on the next page. - * The problem is due to the part of grestore because it restores - * the color values in the state of gsave which are not correct - * if the color values are changed inside of a page. - */ void -pdf_dev_preserve_color (void) +pdf_color_clear_stack (void) { - if (color_stack.next > 0) { - current_stroke = color_stack.stroke[color_stack.next]; - current_fill = color_stack.fill[color_stack.next]; + if (color_stack.current > 0) { + WARN("You've mistakenly made a global color change within nested colors."); } + color_stack.current = 0; + pdf_color_copycolor(&color_stack.stroke[color_stack.current], &default_color); + pdf_color_copycolor(&color_stack.fill[color_stack.current], &default_color); + return; } void -pdf_dev_reset_color (void) +pdf_color_push (pdf_color *sc, pdf_color *fc) { - int colormode; - pdf_color fillcolor, strokecolor; - - /* Shouldn't give a warning */ - colormode = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - if (!colormode) { - return; - } - - if (color_stack.next > 0) { - strokecolor = current_stroke; - fillcolor = current_fill; + if (color_stack.current >= DEV_COLOR_STACK_MAX-1) { + WARN("Color stack overflow. Just ignore."); } else { - strokecolor = default_color; - fillcolor = default_color; + color_stack.current++; + pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); + pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); + pdf_dev_reset_color(); } - - pdf_dev_setcolor(&strokecolor, 0); - pdf_dev_setcolor(&fillcolor, 1); - return; } - void -pdf_color_clear (void) +pdf_color_pop (void) { - color_stack.next = 0; + if (color_stack.current <= 0) { + WARN("Color stack underflow. Just ignore."); + } else { + color_stack.current--; + pdf_dev_reset_color(); + } + return; } void -pdf_color_push (void) +pdf_color_get_current (pdf_color **sc, pdf_color **fc) { - int current; - - current = color_stack.next; - if (current >= DEV_COLOR_STACK_MAX) { - WARN("Exceeded depth of color stack."); - return; - } - - memcpy(&color_stack.stroke[current], - ¤t_stroke, sizeof(pdf_color)); - memcpy(&color_stack.fill[current], - ¤t_fill , sizeof(pdf_color)); - - color_stack.next++; - + *sc = &color_stack.stroke[color_stack.current]; + *fc = &color_stack.fill[color_stack.current]; return; } +/* BUG (20060330): color change does not effect on the next page. + * The problem is due to the part of grestore because it restores + * the color values in the state of gsave which are not correct + * if the color values are changed inside of a page. + */ void -pdf_color_pop (void) +pdf_dev_preserve_color (void) { - int current; - - current = --(color_stack.next); - - if (current < 0) { - WARN("End color with no corresponding begin color."); - /* - * In the case of mismatched push and pop, color_stack.next must set - * to be the default value, 0. Otherwise causes segmentation fault - * in the next push command. - */ - pdf_color_clear(); - return; + if (color_stack.current > 0) { + current_stroke = color_stack.stroke[color_stack.current]; + current_fill = color_stack.fill[color_stack.current]; } - - pdf_dev_setcolor(&color_stack.stroke[current], 0); - pdf_dev_setcolor(&color_stack.fill[current] , 1); - - return; } /***************************** COLOR SPACE *****************************/ diff --git a/Build/source/texk/xdvipdfmx/src/pdfcolor.h b/Build/source/texk/xdvipdfmx/src/pdfcolor.h index 48e930be1a3..769d7e52a5c 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfcolor.h +++ b/Build/source/texk/xdvipdfmx/src/pdfcolor.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfcolor.h,v 1.7 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfcolor.h,v 1.8 2007/11/22 11:45:39 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -51,10 +51,6 @@ typedef struct extern void pdf_color_set_verbose (void); -extern int pdf_dev_setcolor (const pdf_color *color, int is_fill); - -extern int pdf_dev_currentcolor (pdf_color *color, int is_fill); - extern int pdf_color_rgbcolor (pdf_color *color, double r, double g, double b); extern int pdf_color_cmykcolor (pdf_color *color, @@ -63,6 +59,7 @@ extern int pdf_color_graycolor (pdf_color *color, double g); extern void pdf_color_copycolor (pdf_color *color1, const pdf_color *color2); extern int pdf_color_is_white (pdf_color *color); +extern int pdf_color_is_valid (pdf_color *color); /* Not check size */ extern pdf_obj *iccp_get_rendering_intent (const void *profile, long proflen); @@ -88,12 +85,15 @@ extern int pdf_colorspace_load_ICCBased (const char *ident, * See remark in spc_color.c. */ extern void pdf_color_set_default (const pdf_color *color); -extern void pdf_color_push (void); +extern void pdf_color_push (pdf_color *sc, pdf_color *fc); extern void pdf_color_pop (void); -extern void pdf_color_clear (void); + +/* Color stack + */ +extern void pdf_color_clear_stack (void); +extern void pdf_color_get_current (pdf_color **sc, pdf_color **fc); /* Reinstall color */ extern void pdf_dev_preserve_color(void); -extern void pdf_dev_reset_color (void); #endif /* _PDF_COLOR_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/pdfdev.c b/Build/source/texk/xdvipdfmx/src/pdfdev.c index e960965d4c4..1d930d6c1cd 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdev.c +++ b/Build/source/texk/xdvipdfmx/src/pdfdev.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfdev.c,v 1.61 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfdev.c,v 1.64 2007/11/27 02:44:29 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -824,7 +824,7 @@ dev_set_font (int font_id) if (font->bold <= 0.0) len = sprintf(format_buffer, " 0 Tr"); else - len = sprintf(format_buffer, " 2 Tr %.2f w", font->bold); /* _FIXME_ */ + len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ pdf_doc_add_page_content(format_buffer, len); } text_state.bold_param = font->bold; @@ -1131,11 +1131,8 @@ pdf_dev_set_string (spt_t xpos, spt_t ypos, * Same issues as earlier. Use floating point for simplicity. * This routine needs to be fast, so we don't call sprintf() or strcpy(). */ -#if 0 - text_state.offset -= + text_state.offset -= (spt_t) (kern * font->extend * (font->sptsize / 1000.0)); -#endif - text_state.offset -= delh; format_buffer[len++] = text_state.is_mb ? '>' : ')'; if (font->wmode) len += p_itoa(-kern, format_buffer + len); @@ -1191,7 +1188,7 @@ pdf_init_device (double dvi2pts, int precision, int black_and_white) dev_param.colormode = (black_and_white ? 0 : 1); graphics_mode(); - pdf_color_clear(); + pdf_color_clear_stack(); pdf_dev_init_gstates(); num_dev_fonts = 0; @@ -1219,7 +1216,7 @@ pdf_close_device (void) num_dev_fonts = 0; max_dev_fonts = 0; - pdf_dev_clean_gstates(); + pdf_dev_clear_gstates(); } /* @@ -1247,6 +1244,148 @@ pdf_dev_reset_fonts (void) text_state.is_mb = 0; } +void +pdf_dev_reset_color(void) +{ + pdf_color *sc, *fc; + + if (pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { + pdf_color_get_current(&sc, &fc); + pdf_dev_set_strokingcolor(sc); + pdf_dev_set_nonstrokingcolor(fc); + } + return; +} + +static int +color_to_string (pdf_color *color, char *buffer) +{ + int i, len = 0; + + for (i = 0; i < color->num_components; i++) { + len += sprintf(format_buffer+len, " %g", ROUND(color->values[i], 0.001)); + } + return len; +} + +void +pdf_dev_set_color (pdf_color *color) +{ + int len; + + if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { + WARN("Ignore color option was set. Just ignore."); + return; + } else if (!(color && pdf_color_is_valid(color))) { + WARN("No valid color is specified. Just ignore."); + return; + } + + graphics_mode(); + len = color_to_string(color, format_buffer); + format_buffer[len++] = ' '; + switch (color->num_components) { + case 3: + format_buffer[len++] = 'R'; + format_buffer[len++] = 'G'; + break; + case 4: + format_buffer[len++] = 'K'; + break; + case 1: + format_buffer[len++] = 'G'; + break; + default: /* already verified the given color */ + break; + } + strncpy(format_buffer+len, format_buffer, len); + len = len << 1; + switch (color->num_components) { + case 3: + format_buffer[len-2] = 'r'; + format_buffer[len-1] = 'g'; + break; + case 4: + format_buffer[len-1] = 'k'; + break; + case 1: + format_buffer[len-1] = 'g'; + break; + default: /* already verified the given color */ + break; + } + pdf_doc_add_page_content(format_buffer, len); + return; +} + +void +pdf_dev_set_strokingcolor (pdf_color *color) +{ + int len; + + if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { + WARN("Ignore color option was set. Just ignore."); + return; + } else if (!(color && pdf_color_is_valid(color))) { + WARN("No valid color is specified. Just ignore."); + return; + } + + graphics_mode(); + len = color_to_string(color, format_buffer); + format_buffer[len++] = ' '; + switch (color->num_components) { + case 3: + format_buffer[len++] = 'R'; + format_buffer[len++] = 'G'; + break; + case 4: + format_buffer[len++] = 'K'; + break; + case 1: + format_buffer[len++] = 'G'; + break; + default: /* already verified the given color */ + break; + } + pdf_doc_add_page_content(format_buffer, len); + return; +} + +void +pdf_dev_set_nonstrokingcolor (pdf_color *color) +{ + int len; + + if (!pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE)) { + WARN("Ignore color option was set. Just ignore."); + return; + } else if (!(color && pdf_color_is_valid(color))) { + WARN("No valid color is specified. Just ignore."); + return; + } + + graphics_mode(); + len = color_to_string(color, format_buffer); + format_buffer[len++] = ' '; + switch (color->num_components) { + case 3: + format_buffer[len++] = 'r'; + format_buffer[len++] = 'g'; + break; + case 4: + format_buffer[len++] = 'k'; + break; + case 1: + format_buffer[len++] = 'g'; + break; + default: /* already verified the given color */ + break; + } + pdf_doc_add_page_content(format_buffer, len); + return; +} + /* Not working */ void pdf_dev_set_origin (double phys_x, double phys_y) @@ -1262,9 +1401,6 @@ pdf_dev_set_origin (double phys_x, double phys_y) pdf_dev_concat(&M1); } -static pdf_color saved_sc, saved_fc; -static int have_saved_color = 0; - void pdf_dev_bop (const pdf_tmatrix *M) { @@ -1276,28 +1412,15 @@ pdf_dev_bop (const pdf_tmatrix *M) pdf_dev_concat(M); pdf_dev_reset_fonts(); - pdf_dev_preserve_color(); /* preserve the last color in the previous page */ pdf_dev_reset_color(); - - if (have_saved_color) { - pdf_dev_setcolor(&saved_sc, 0); - pdf_dev_setcolor(&saved_fc, 1); - } } void pdf_dev_eop (void) { int depth; - - graphics_mode(); - /* preserve the current color for start of next page, so \special{color...} - doesn't cease to have any effect at a page break; - note that printing pages out of order will break the assumptions here */ - pdf_dev_currentcolor(&saved_sc, 0); - pdf_dev_currentcolor(&saved_fc, 1); - have_saved_color = 1; + graphics_mode(); depth = pdf_dev_current_depth(); if (depth != 1) { @@ -1782,6 +1905,47 @@ pdf_dev_put_image (int id, res_name, pdf_ximage_get_reference(id)); + if (dvi_is_tracking_boxes()) { + pdf_tmatrix P; + int i; + pdf_rect rect; + pdf_coord corner[4]; + + pdf_dev_set_rect(&rect, 65536 * ref_x, 65536 * ref_y, + 65536 * (r.urx - r.llx), 65536 * (r.ury - r.lly), 0); + + corner[0].x = rect.llx; corner[0].y = rect.lly; + corner[1].x = rect.llx; corner[1].y = rect.ury; + corner[2].x = rect.urx; corner[2].y = rect.ury; + corner[3].x = rect.urx; corner[3].y = rect.lly; + + pdf_copymatrix(&P, &(p->matrix)); + for (i = 0; i < 4; ++i) { + corner[i].x -= rect.llx; + corner[i].y -= rect.lly; + pdf_dev_transform(&(corner[i]), &P); + corner[i].x += rect.llx; + corner[i].y += rect.lly; + } + + rect.llx = corner[0].x; + rect.lly = corner[0].y; + rect.urx = corner[0].x; + rect.ury = corner[0].y; + for (i = 0; i < 4; ++i) { + if (corner[i].x < rect.llx) + rect.llx = corner[i].x; + if (corner[i].x > rect.urx) + rect.urx = corner[i].x; + if (corner[i].y < rect.lly) + rect.lly = corner[i].y; + if (corner[i].y > rect.ury) + rect.ury = corner[i].y; + } + + pdf_doc_expand_box(&rect); + } + return 0; } diff --git a/Build/source/texk/xdvipdfmx/src/pdfdev.h b/Build/source/texk/xdvipdfmx/src/pdfdev.h index f29481266b5..5e5b7a9adfe 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdev.h +++ b/Build/source/texk/xdvipdfmx/src/pdfdev.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfdev.h,v 1.19 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfdev.h,v 1.20 2007/11/22 11:45:39 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -27,6 +27,7 @@ #include "numbers.h" #include "pdfobj.h" +#include "pdfcolor.h" typedef signed long spt_t; @@ -202,7 +203,11 @@ extern void pdf_dev_set_param (int param_type, int value); * XFrom (content grabbing) and Metapost support want them. */ extern void pdf_dev_reset_fonts (void); -extern void pdf_dev_reset_color (void); /* defined in pdfcolor.c */ +extern void pdf_dev_reset_color (void); + +extern void pdf_dev_set_color (pdf_color *color); +extern void pdf_dev_set_strokingcolor (pdf_color *color); +extern void pdf_dev_set_nonstrokingcolor (pdf_color *color); /* Initialization of transformation matrix with M and others. * They are called within pdf_doc_begin_page() and pdf_doc_end_page(). diff --git a/Build/source/texk/xdvipdfmx/src/pdfdoc.c b/Build/source/texk/xdvipdfmx/src/pdfdoc.c index 87c4edf3ec6..aeda5c1d8ef 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdoc.c +++ b/Build/source/texk/xdvipdfmx/src/pdfdoc.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfdoc.c,v 1.44 2006/12/20 08:10:13 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfdoc.c,v 1.50 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -144,9 +144,9 @@ read_thumbnail (const char *thumb_filename) MFCLOSE(fp); if (found_in_cwd) { - xobj_id = pdf_ximage_findresource(thumb_filename, 0, 0); + xobj_id = pdf_ximage_findresource(thumb_filename, 0/*, 0*/); } else { - xobj_id = pdf_ximage_findresource(guess_filename, 0, 0); + xobj_id = pdf_ximage_findresource(guess_filename, 0/*, 0*/); } if (xobj_id < 0) { @@ -511,7 +511,7 @@ asn_date (char *date_string) # ifdef HAVE_TM_GMTOFF # define timezone (-bd_time->tm_gmtoff) # else -# define timezone (-compute_timezone_offset()) +# define timezone (-compute_timezone_offset()) # endif /* not HAVE_TM_GMTOFF */ #endif /* not HAVE_TIMEZONE */ time_t current_time; @@ -1037,6 +1037,7 @@ flush_bookmarks (pdf_olitem *node, pdf_new_name("Last"), pdf_link_obj(prev_ref)); + pdf_release_obj(prev_ref); pdf_release_obj(node->dict); node->dict = NULL; @@ -1334,10 +1335,10 @@ pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, pdf_obj *annot_dict) #endif rect_array = pdf_new_array(); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->llx - annot_grow, 0.01))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->lly - annot_grow, 0.01))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->urx + annot_grow, 0.01))); - pdf_add_array(rect_array, pdf_new_number(ROUND(rect->ury + annot_grow, 0.01))); + pdf_add_array(rect_array, pdf_new_number(ROUND(rect->llx - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(rect->lly - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(rect->urx + annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(rect->ury + annot_grow, 0.001))); pdf_add_dict (annot_dict, pdf_new_name("Rect"), rect_array); pdf_add_array(page->annots, pdf_ref_obj(annot_dict)); @@ -1961,10 +1962,10 @@ doc_fill_page_background (pdf_doc *p) currentpage->contents = currentpage->background; pdf_dev_gsave(); - pdf_color_push(); - pdf_dev_setcolor(&bgcolor, 1); /* is_fill */ + //pdf_color_push(); + pdf_dev_set_nonstrokingcolor(&bgcolor); pdf_dev_rectfill(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); - pdf_color_pop(); + //pdf_color_pop(); pdf_dev_grestore(); currentpage->contents = saved_content; @@ -2023,12 +2024,13 @@ static char *doccreator = NULL; /* Ugh */ void pdf_open_document (const char *filename, + int do_encryption, int do_objstm, double media_width, double media_height, double annot_grow_amount, int bookmark_open_depth) { pdf_doc *p = &pdoc; - pdf_out_init(filename); + pdf_out_init(filename, do_encryption); pdf_doc_init_catalog(p); @@ -2054,7 +2056,14 @@ pdf_open_document (const char *filename, pdf_doc_init_names (p); pdf_doc_init_page_tree(p, media_width, media_height); - create_encrypt(); + if (do_encryption) { + pdf_obj *encrypt = pdf_encrypt_obj(); + pdf_set_encrypt(encrypt, pdf_enc_id_array()); + pdf_release_obj(encrypt); + } + + if (do_objstm) + pdf_objstm_init(); #ifndef NO_THUMBNAIL /* Create a default name for thumbnail image files */ @@ -2118,6 +2127,8 @@ pdf_close_document (void) } #endif /* !NO_THUMBNAIL */ + pdf_objstm_close(); + return; } diff --git a/Build/source/texk/xdvipdfmx/src/pdfdoc.h b/Build/source/texk/xdvipdfmx/src/pdfdoc.h index 0d160e18a7f..2fd805c6077 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdoc.h +++ b/Build/source/texk/xdvipdfmx/src/pdfdoc.h @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfdoc.h,v 1.19 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfdoc.h,v 1.21 2007/11/14 03:36:01 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -33,6 +33,7 @@ extern void pdf_doc_set_verbose (void); extern void pdf_open_document (const char *filename, + int do_encryption, int do_objstm, double media_width, double media_height, double annot_grow_amount, int bookmark_open_depth); extern void pdf_close_document (void); diff --git a/Build/source/texk/xdvipdfmx/src/pdfdraw.c b/Build/source/texk/xdvipdfmx/src/pdfdraw.c index 444d177d9b0..618aae75686 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdraw.c +++ b/Build/source/texk/xdvipdfmx/src/pdfdraw.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfdraw.c,v 1.13 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfdraw.c,v 1.14 2007/11/22 17:10:12 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -207,6 +207,7 @@ pdf_invertmatrix (pdf_tmatrix *M) W.c = -(M->c) / det; W.d = (M->a) / det; W.e = (M->c) * (M->f) - (M->d) * (M->e); W.f = (M->b) * (M->e) - (M->a) * (M->f); + W.e /= det; W.f /= det; } pdf_copymatrix(M, &W); @@ -267,7 +268,7 @@ static char fmt_buf[1024]; /* FIXME */ #define FORMAT_BUFF_LEN(p) 1024 static void -pdf_path__initpath (pdf_path *p) +init_a_path (pdf_path *p) { ASSERT(p); @@ -301,7 +302,7 @@ pdf_path__growpath (pdf_path *p, int max_pe) } static void -pdf_path__cleanpath (pdf_path *p) +clear_a_path (pdf_path *p) { ASSERT(p); @@ -710,7 +711,7 @@ pdf_path__isarect (pdf_path *pa, (c) == 'f' || (c) == 'F' || \ (c) == 's' || (c) == 'S' || \ (c) == 'b' || (c) == 'B' || \ - (c) == 'W' \ + (c) == 'W' || (c) == ' ' \ ) static /* __inline__ */ int @@ -752,7 +753,7 @@ pdf_dev__rectshape (pdf_dev *P, ASSERT(r && PT_OP_VALID(opchr)); - isclip = (opchr == 'W') ? 1 : 0; + isclip = (opchr == 'W' || opchr == ' ') ? 1 : 0; /* disallow matrix for clipping. * q ... clip Q does nothing and @@ -789,17 +790,21 @@ pdf_dev__rectshape (pdf_dev *P, buf[len++] = ' '; buf[len++] = 'r'; buf[len++] = 'e'; - buf[len++] = ' '; - buf[len++] = opchr; + if (opchr != ' ') { + buf[len++] = ' '; + buf[len++] = opchr; - buf[len++] = ' '; - buf[len++] = isclip ? 'n' : 'Q'; + buf[len++] = ' '; + buf[len++] = isclip ? 'n' : 'Q'; + } pdf_doc_add_page_content(buf, len); len = 0; return 0; } +static int path_added = 0; + /* FIXME */ static int pdf_dev__flushpath (pdf_dev *P, @@ -815,13 +820,17 @@ pdf_dev__flushpath (pdf_dev *P, pdf_coord *pt; int n_pts, n_seg; int len = 0; + int isclip = 0; int isrect, i, j; ASSERT(pa && PT_OP_VALID(opchr)); - if (PA_LENGTH(pa) <= 0) + isclip = (opchr == 'W') ? 1 : 0; + + if (PA_LENGTH(pa) <= 0 && path_added == 0) return 0; + path_added = 0; graphics_mode(); isrect = pdf_path__isarect(pa, ignore_rule); if (isrect) { @@ -864,6 +873,9 @@ pdf_dev__flushpath (pdf_dev *P, b[len++] = opchr; if (rule == PDF_FILL_RULE_EVENODD) b[len++] = '*'; + if (isclip) { + b[len++] = ' '; b[len++] = 'n'; + } pdf_doc_add_page_content(b, len); @@ -899,6 +911,8 @@ typedef struct pdf_gstate_ /* internal */ pdf_path path; long flags; + /* bookkeeping the origin of the last transform applied */ + pdf_coord pt_fixee; } pdf_gstate; @@ -987,25 +1001,18 @@ m_stack_top (m_stack *stack) #define m_stack_depth(s) ((s) ? (s)->size : 0) - -static m_stack _gsstck; /* FIXME */ - +static m_stack gs_stack; static void -pdf_dev__init_gstate (pdf_gstate *gs) +init_a_gstate (pdf_gstate *gs) { - pdf_path *pa = &gs->path; - pdf_color *cf = &gs->fillcolor; - pdf_color *cs = &gs->strokecolor; - pdf_tmatrix *M = &gs->matrix; - gs->cp.x = 0.0; gs->cp.y = 0.0; - pdf_setmatrix(M, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); + pdf_setmatrix(&gs->matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - pdf_color_graycolor(cs, 0.0); - pdf_color_graycolor(cf, 0.0); + pdf_color_graycolor(&gs->strokecolor, 0.0); + pdf_color_graycolor(&gs->fillcolor, 0.0); gs->linedash.num_dash = 0; gs->linedash.offset = 0; @@ -1018,22 +1025,24 @@ pdf_dev__init_gstate (pdf_gstate *gs) /* Internal variables */ gs->flags = 0; - pdf_path__initpath(pa); + init_a_path(&gs->path); + gs->pt_fixee.x = 0; + gs->pt_fixee.y = 0; return; } static void -pdf_dev__clean_gstate (pdf_gstate *gs) +clear_a_gstate (pdf_gstate *gs) { - pdf_path__cleanpath(&gs->path); + clear_a_path(&gs->path); memset(gs, 0, sizeof(pdf_gstate)); return; } static void -pdf_dev__copy_gstate (pdf_gstate *gs1, pdf_gstate *gs2) +copy_a_gstate (pdf_gstate *gs1, pdf_gstate *gs2) { int i; @@ -1065,6 +1074,8 @@ pdf_dev__copy_gstate (pdf_gstate *gs1, pdf_gstate *gs2) pdf_color_copycolor(&gs1->fillcolor , &gs2->fillcolor); pdf_color_copycolor(&gs1->strokecolor, &gs2->strokecolor); + gs1->pt_fixee.x = gs2->pt_fixee.x; + gs1->pt_fixee.y = gs2->pt_fixee.y; return; } @@ -1072,156 +1083,89 @@ pdf_dev__copy_gstate (pdf_gstate *gs1, pdf_gstate *gs2) void pdf_dev_init_gstates (void) { - m_stack *gss = &_gsstck; pdf_gstate *gs; - m_stack_init(gss); + m_stack_init(&gs_stack); gs = NEW(1, pdf_gstate); - pdf_dev__init_gstate(gs); + init_a_gstate(gs); - m_stack_push(gss, gs); /* Initial state */ + m_stack_push(&gs_stack, gs); /* Initial state */ return; } void -pdf_dev_clean_gstates (void) +pdf_dev_clear_gstates (void) { - m_stack *gss = &_gsstck; pdf_gstate *gs; - if (m_stack_depth(gss) > 1) /* at least 1 elem. */ - WARN("GS stack depth not 0 at end of document."); + if (m_stack_depth(&gs_stack) > 1) /* at least 1 elem. */ + WARN("GS stack depth is not zero at the end of the document."); - while ((gs = m_stack_pop(gss)) != NULL) { - pdf_dev__clean_gstate(gs); + while ((gs = m_stack_pop(&gs_stack)) != NULL) { + clear_a_gstate(gs); RELEASE(gs); } - return; } - int -pdf_dev_currentpoint (pdf_coord *p) -{ - m_stack *gss = &_gsstck; - pdf_gstate *gs = m_stack_top(gss); - pdf_coord *cpt = &gs->cp; - - ASSERT(p); - - p->x = cpt->x; p->y = cpt->y; - - return 0; -} - -int -pdf_dev_currentmatrix (pdf_tmatrix *M) -{ - m_stack *gss = &_gsstck; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(M); - - pdf_copymatrix(M, CTM); - - return 0; -} - -#if 0 -int -pdf_dev_currentcolor (pdf_color *color, int is_fill) +pdf_dev_gsave (void) { - m_stack *gss = &_gsstck; - pdf_gstate *gs = m_stack_top(gss); - pdf_color *fcl = &gs->fillcolor; - pdf_color *scl = &gs->strokecolor; + pdf_gstate *gs0, *gs1; + pdf_color *sc, *fc; - ASSERT(color); + gs0 = m_stack_top(&gs_stack); + gs1 = NEW(1, pdf_gstate); + init_a_gstate(gs1); + copy_a_gstate(gs1, gs0); + pdf_color_get_current(&sc, &fc); + pdf_color_copycolor(&gs1->strokecolor, sc); + pdf_color_copycolor(&gs1->fillcolor, fc); + m_stack_push(&gs_stack, gs1); - pdf_color_copycolor(color, is_fill ? fcl : scl); + pdf_doc_add_page_content(" q", 2); return 0; } -#endif /* 0 */ int -pdf_dev_concat (const pdf_tmatrix *M) +pdf_dev_grestore (void) { - m_stack *gss = &_gsstck; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_tmatrix *CTM = &gs->matrix; - pdf_tmatrix W; - char *buf = FORMAT_BUFF_PTR(NULL); - int len = 0; - - ASSERT(M); + pdf_gstate *gs; + pdf_color sc, fc; - /* Adobe Reader erases page content if there are - * non invertible transformation. - */ - if (fabs(detP(M)) < 1.0e-8) { - WARN("Transformation matrix not invertible."); - WARN("--- M = [%g %g %g %g %g %g]", - M->a, M->b, M->c, M->d, M->e, M->f); - return -1; + if (m_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ + WARN("Too many grestores."); + return -1; } - buf[len++] = ' '; - len += pdf_sprint_matrix(buf + len, M); - buf[len++] = ' '; - buf[len++] = 'c'; - buf[len++] = 'm'; - pdf_doc_add_page_content(buf, len); - - pdf_concatmatrix(CTM, M); - - inversematrix(&W, M); - - pdf_path__transform (cpa, &W); - pdf_coord__transform(cpt, &W); - - return 0; -} - - -int -pdf_dev_gsave (void) -{ - m_stack *gss = &_gsstck; - pdf_gstate *gs0, *gs1; - - gs0 = m_stack_top(gss); - gs1 = NEW(1, pdf_gstate); - - pdf_dev__init_gstate(gs1); - pdf_dev__copy_gstate(gs1, gs0); - - pdf_dev_currentcolor(&gs1->strokecolor, 0); - pdf_dev_currentcolor(&gs1->fillcolor, 1); + gs = m_stack_pop(&gs_stack); +// pdf_color_copycolor(&sc, &gs->strokecolor); +// pdf_color_copycolor(&fc, &gs->fillcolor); + clear_a_gstate(gs); + RELEASE(gs); - m_stack_push(gss, gs1); + pdf_doc_add_page_content(" Q", 2); - pdf_doc_add_page_content(" q", 2); + pdf_dev_reset_fonts(); +// pdf_dev_set_strokingcolor(&sc); +// pdf_dev_set_nonstrokingcolor(&fc); - return 0; + return 0; } int pdf_dev_push_gstate (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs0; gs0 = NEW(1, pdf_gstate); - pdf_dev__init_gstate(gs0); + init_a_gstate(gs0); m_stack_push(gss, gs0); @@ -1232,7 +1176,7 @@ pdf_dev_push_gstate (void) int pdf_dev_pop_gstate (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs; if (m_stack_depth(gss) <= 1) { /* Initial state at bottom */ @@ -1241,7 +1185,7 @@ pdf_dev_pop_gstate (void) } gs = m_stack_pop(gss); - pdf_dev__clean_gstate(gs); + clear_a_gstate(gs); RELEASE(gs); return 0; @@ -1251,16 +1195,15 @@ pdf_dev_pop_gstate (void) int pdf_dev_current_depth (void) { - m_stack *gss = &_gsstck; - - return (m_stack_depth(gss) - 1); /* 0 means initial state */ + return (m_stack_depth(&gs_stack) - 1); /* 0 means initial state */ } void pdf_dev_grestore_to (int depth) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs; + pdf_color sc, fc; ASSERT(depth >= 0); @@ -1271,44 +1214,105 @@ pdf_dev_grestore_to (int depth) while (m_stack_depth(gss) > depth + 1) { pdf_doc_add_page_content(" Q", 2); gs = m_stack_pop(gss); - pdf_dev__clean_gstate(gs); +// pdf_color_copycolor(&sc, &gs->strokecolor); +// pdf_color_copycolor(&fc, &gs->fillcolor); + clear_a_gstate(gs); RELEASE(gs); } pdf_dev_reset_fonts(); - pdf_dev_reset_color(); +// pdf_dev_set_strokingcolor(&sc); +// pdf_dev_set_nonstrokingcolor(&fc); return; } int -pdf_dev_grestore (void) +pdf_dev_currentpoint (pdf_coord *p) { - m_stack *gss = &_gsstck; - pdf_gstate *gs; - pdf_color sc, fc; + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_coord *cpt = &gs->cp; - if (m_stack_depth(gss) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } + ASSERT(p); - gs = m_stack_pop(gss); + p->x = cpt->x; p->y = cpt->y; - pdf_color_copycolor(&sc, &gs->strokecolor); - pdf_color_copycolor(&fc, &gs->fillcolor); + return 0; +} - pdf_dev__clean_gstate(gs); - RELEASE(gs); +int +pdf_dev_currentmatrix (pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_tmatrix *CTM = &gs->matrix; - pdf_doc_add_page_content(" Q", 2); + ASSERT(M); - pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_copymatrix(M, CTM); - pdf_dev_setcolor(&sc, 0); - pdf_dev_setcolor(&fc, 1); + return 0; +} - return 0; +#if 0 +int +pdf_dev_currentcolor (pdf_color *color, int is_fill) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_color *fcl = &gs->fillcolor; + pdf_color *scl = &gs->strokecolor; + + ASSERT(color); + + pdf_color_copycolor(color, is_fill ? fcl : scl); + + return 0; +} +#endif /* 0 */ + +int +pdf_dev_concat (const pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_tmatrix *CTM = &gs->matrix; + pdf_tmatrix W; + char *buf = FORMAT_BUFF_PTR(NULL); + int len = 0; + + ASSERT(M); + + /* Adobe Reader erases page content if there are + * non invertible transformation. + */ + if (fabs(detP(M)) < 1.0e-8) { + WARN("Transformation matrix not invertible."); + WARN("--- M = [%g %g %g %g %g %g]", + M->a, M->b, M->c, M->d, M->e, M->f); + return -1; + } + + if (fabs(M->a - 1.0) > 1.e-8 || fabs(M->b) > 1.e-8 + || fabs(M->c) > 1.e-8 || fabs(M->d - 1.0) > 1.e-8 + || fabs(M->e) > 1.e-8 || fabs(M->f) > 1.e-8) { + buf[len++] = ' '; + len += pdf_sprint_matrix(buf + len, M); + buf[len++] = ' '; + buf[len++] = 'c'; + buf[len++] = 'm'; + pdf_doc_add_page_content(buf, len); + + pdf_concatmatrix(CTM, M); + } + inversematrix(&W, M); + + pdf_path__transform (cpa, &W); + pdf_coord__transform(cpt, &W); + + return 0; } /* @@ -1324,7 +1328,7 @@ pdf_dev_grestore (void) int pdf_dev_setmiterlimit (double mlimit) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1344,7 +1348,7 @@ pdf_dev_setmiterlimit (double mlimit) int pdf_dev_setlinecap (int capstyle) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1361,7 +1365,7 @@ pdf_dev_setlinecap (int capstyle) int pdf_dev_setlinejoin (int joinstyle) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1378,7 +1382,7 @@ pdf_dev_setlinejoin (int joinstyle) int pdf_dev_setlinewidth (double width) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1398,7 +1402,7 @@ pdf_dev_setlinewidth (double width) int pdf_dev_setdash (int count, double *pattern, double offset) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1424,7 +1428,7 @@ pdf_dev_setdash (int count, double *pattern, double offset) int pdf_dev_setflat (int flatness) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); int len = 0; char *buf = FORMAT_BUFF_PTR(NULL); @@ -1445,7 +1449,7 @@ pdf_dev_setflat (int flatness) int pdf_dev_clip (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; @@ -1455,7 +1459,7 @@ pdf_dev_clip (void) int pdf_dev_eoclip (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; @@ -1465,7 +1469,7 @@ pdf_dev_eoclip (void) int pdf_dev_flushpath (char p_op, int fill_rule) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; int error = 0; @@ -1485,7 +1489,7 @@ pdf_dev_flushpath (char p_op, int fill_rule) int pdf_dev_newpath (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *p = &gs->path; @@ -1501,7 +1505,7 @@ pdf_dev_newpath (void) int pdf_dev_moveto (double x, double y) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1514,7 +1518,7 @@ pdf_dev_moveto (double x, double y) int pdf_dev_rmoveto (double x, double y) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1528,7 +1532,7 @@ pdf_dev_rmoveto (double x, double y) int pdf_dev_lineto (double x, double y) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1542,7 +1546,7 @@ pdf_dev_lineto (double x, double y) int pdf_dev_rlineto (double x, double y) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1558,7 +1562,7 @@ pdf_dev_curveto (double x0, double y0, double x1, double y1, double x2, double y2) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1571,12 +1575,44 @@ pdf_dev_curveto (double x0, double y0, return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); } +int +pdf_dev_vcurveto (double x0, double y0, + double x1, double y1) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord p0, p1; + + p0.x = x0; p0.y = y0; + p1.x = x1; p1.y = y1; + + return pdf_path__curveto(cpa, cpt, cpt, &p0, &p1); +} + +int +pdf_dev_ycurveto (double x0, double y0, + double x1, double y1) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord p0, p1; + + p0.x = x0; p0.y = y0; + p1.x = x1; p1.y = y1; + + return pdf_path__curveto(cpa, cpt, &p0, &p1, &p1); +} + int pdf_dev_rcurveto (double x0, double y0, double x1, double y1, double x2, double y2) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1593,7 +1629,7 @@ pdf_dev_rcurveto (double x0, double y0, int pdf_dev_closepath (void) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_coord *cpt = &gs->cp; pdf_path *cpa = &gs->path; @@ -1605,7 +1641,7 @@ pdf_dev_closepath (void) void pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_tmatrix *CTM = &gs->matrix; @@ -1619,7 +1655,7 @@ pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) void pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_tmatrix *CTM = &gs->matrix; @@ -1633,7 +1669,7 @@ pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) void pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_tmatrix *CTM = &gs->matrix; @@ -1647,7 +1683,7 @@ pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) void pdf_dev_itransform (pdf_coord *p, const pdf_tmatrix *M) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_tmatrix *CTM = &gs->matrix; @@ -1662,7 +1698,7 @@ int pdf_dev_arc (double c_x , double c_y, double r, double a_0 , double a_1) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1678,7 +1714,7 @@ int pdf_dev_arcn (double c_x , double c_y, double r, double a_0 , double a_1) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1696,7 +1732,7 @@ pdf_dev_arcx (double c_x , double c_y, int a_d , double xar) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1712,7 +1748,7 @@ int pdf_dev_bspline (double x0, double y0, double x1, double y1, double x2, double y2) { - m_stack *gss = &_gsstck; + m_stack *gss = &gs_stack; pdf_gstate *gs = m_stack_top(gss); pdf_path *cpa = &gs->path; pdf_coord *cpt = &gs->cp; @@ -1772,3 +1808,36 @@ pdf_dev_rectclip (double x, double y, return pdf_dev__rectshape(NULL, &r, NULL, 'W'); } + +int +pdf_dev_rectadd (double x, double y, + double w, double h) +{ + pdf_rect r; + + r.llx = x; + r.lly = y; + r.urx = x + w; + r.ury = y + h; + path_added = 1; + + return pdf_dev__rectshape(NULL, &r, NULL, ' '); +} + +void +pdf_dev_set_fixed_point (double x, double y) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + gs->pt_fixee.x = x; + gs->pt_fixee.y = y; +} + +void +pdf_dev_get_fixed_point (pdf_coord *p) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + p->x = gs->pt_fixee.x; + p->y = gs->pt_fixee.y; +} diff --git a/Build/source/texk/xdvipdfmx/src/pdfdraw.h b/Build/source/texk/xdvipdfmx/src/pdfdraw.h index 1c90851dd75..c2fd27f57d9 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfdraw.h +++ b/Build/source/texk/xdvipdfmx/src/pdfdraw.h @@ -83,6 +83,10 @@ extern int pdf_dev_rlineto (double x0 , double y0); extern int pdf_dev_curveto (double x0 , double y0, double x1 , double y1, double x2 , double y2); +extern int pdf_dev_vcurveto (double x0 , double y0, + double x1 , double y1); +extern int pdf_dev_ycurveto (double x0 , double y0, + double x1 , double y1); extern int pdf_dev_rcurveto (double x0 , double y0, double x1 , double y1, double x2 , double y2); @@ -107,6 +111,7 @@ extern int pdf_dev_rectstroke (double x, double y, ); extern int pdf_dev_rectfill (double x, double y, double w, double h); extern int pdf_dev_rectclip (double x, double y, double w, double h); +extern int pdf_dev_rectadd (double x, double y, double w, double h); extern int pdf_dev_flushpath (char p_op, int fill_rule); @@ -156,4 +161,6 @@ extern void pdf_dev_grestore_to (int depth); extern int pdf_dev_currentcolor (pdf_color *color, int is_fill); extern int pdf_dev_setcolor (const pdf_color *color, int is_fill); +extern void pdf_dev_set_fixed_point (double x, double y); +extern void pdf_dev_get_fixed_point (pdf_coord *p); #endif /* _PDF_DRAW_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/pdfencrypt.c b/Build/source/texk/xdvipdfmx/src/pdfencrypt.c index dc9b8efde20..787712987b5 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfencrypt.c +++ b/Build/source/texk/xdvipdfmx/src/pdfencrypt.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfencrypt.c,v 1.8 2005/07/20 08:49:55 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfencrypt.c,v 1.9 2007/04/03 05:25:50 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -71,7 +71,6 @@ static const unsigned char padding_string[MAX_STR_LEN] = { static char owner_passwd[MAX_PWD_LEN], user_passwd[MAX_PWD_LEN]; -static unsigned char do_encryption = 0; static unsigned char verbose = 0; void pdf_enc_set_verbose (void) @@ -379,7 +378,6 @@ void pdf_enc_set_passwd (unsigned bits, unsigned perm, char *dviname, char *pdfn fflush(stderr); } - do_encryption = 1; key_size = (unsigned char)(bits / 8); algorithm = (key_size == 5 ? 1 : 2); permission = (unsigned long)perm | 0x000000C0; @@ -396,8 +394,6 @@ void pdf_encrypt_data (unsigned char *data, unsigned long len) { unsigned char *result; - if (!do_encryption) return; - memcpy(in_buf, key_data, key_size); in_buf[key_size] = (unsigned char)(current_label) & 0xFF; in_buf[key_size+1] = (unsigned char)(current_label >> 8) & 0xFF; @@ -416,20 +412,15 @@ void pdf_encrypt_data (unsigned char *data, unsigned long len) RELEASE (result); } -void create_encrypt (void) +pdf_obj *pdf_encrypt_obj (void) { pdf_obj *doc_encrypt; - if (!do_encryption) return; - #ifdef DEBUG - fprintf (stderr, "(create_encrypt)"); + fprintf (stderr, "(pdf_encrypt_obj)"); #endif - /* Create an empty Encryption entry and make it - be the root object */ doc_encrypt = pdf_new_dict (); - pdf_set_encrypt (doc_encrypt); /* KEY : Filter * TYPE : name @@ -509,20 +500,15 @@ void create_encrypt (void) pdf_new_name ("P"), pdf_new_number (permission)); - do_encryption = 0; - pdf_release_obj (doc_encrypt); - do_encryption = 1; + return doc_encrypt; } -unsigned char *pdf_enc_id_string (void) +pdf_obj *pdf_enc_id_array (void) { - register int i; - static unsigned char result[MAX_STR_LEN+1]; - - for (i = 0; i < MAX_KEY_LEN; i++) - sprintf((char *)(result+2*i), "%02x", id_string[i]); - - return result; + pdf_obj *id = pdf_new_array(); + pdf_add_array(id, pdf_new_string(id_string, MAX_KEY_LEN)); + pdf_add_array(id, pdf_new_string(id_string, MAX_KEY_LEN)); + return id; } void pdf_enc_set_label (unsigned long label) diff --git a/Build/source/texk/xdvipdfmx/src/pdfencrypt.h b/Build/source/texk/xdvipdfmx/src/pdfencrypt.h index daaa6f52bcc..4735d89d976 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfencrypt.h +++ b/Build/source/texk/xdvipdfmx/src/pdfencrypt.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfencrypt.h,v 1.2 2002/10/30 02:27:13 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfencrypt.h,v 1.3 2007/04/03 05:25:50 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -23,13 +23,14 @@ #ifndef _PDFENCRYPT_H_ #define _PDFENCRYPT_H_ +#include "pdfobj.h" + extern void pdf_enc_set_verbose (void); -extern unsigned char *pdf_enc_id_string (void); -extern void pdf_enc_set_encryption (void); +extern pdf_obj *pdf_enc_id_array (void); extern void pdf_enc_set_label (unsigned long label); extern void pdf_enc_set_generation (unsigned generation); extern void pdf_enc_set_passwd (unsigned size, unsigned perm, char *dviname, char *pdfname); extern void pdf_encrypt_data (unsigned char *data, unsigned long len); -extern void create_encrypt (void); +extern pdf_obj *pdf_encrypt_obj (void); #endif /* _PDFENCRYPT_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/pdfobj.c b/Build/source/texk/xdvipdfmx/src/pdfobj.c index 386eaaff850..1ad7de2a928 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfobj.c +++ b/Build/source/texk/xdvipdfmx/src/pdfobj.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfobj.c,v 1.40 2006/12/06 13:14:54 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfobj.c,v 1.49 2008/02/08 19:02:38 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -42,11 +42,19 @@ #endif /* HAVE_ZLIB */ #include "pdfobj.h" +#include "pdfdev.h" #define STREAM_ALLOC_SIZE 4096u #define ARRAY_ALLOC_SIZE 256 #define IND_OBJECTS_ALLOC_SIZE 512 +#define OBJ_NO_OBJSTM (1 << 0) +/* Objects with this flag will not be put into an object stream. + For instance, all stream objects have this flag set. */ +#define OBJ_NO_ENCRYPT (1 << 1) +/* Objects with this flag will not be encrypted. + This implies OBJ_NO_OBJSTM if encryption is turned on. */ + /* Any of these types can be represented as follows */ struct pdf_obj { @@ -56,6 +64,7 @@ struct pdf_obj all other "label" to zero */ unsigned short generation; /* Only used if "label" is used */ unsigned refcount; /* Number of links to this object */ + int flags; void *data; }; @@ -105,8 +114,8 @@ struct pdf_stream struct pdf_indirect { - unsigned label; - unsigned generation; + unsigned long label; + unsigned short generation; int dirty; /* Dirty objects came from an input file and were not generated by this program. They have a label in a different numbering sequence. These are translated @@ -136,19 +145,35 @@ static char format_buffer[FORMAT_BUF_SIZE]; static struct xref_entry { - long file_position; - pdf_obj *object; - int used; /* Used by PDF import */ -} *output_xref = NULL; + unsigned char type; + unsigned long field2; + unsigned short field3; + int used; /* Used by PDF import */ +} *output_xref; -static unsigned long pdf_max_ind_objects = 0; -static unsigned long next_label = 1; +static unsigned long pdf_max_ind_objects; +static unsigned long next_label; static unsigned long startxref; -static unsigned pdf_root_obj = 0; -static unsigned pdf_info_obj = 0; -static unsigned pdf_encrypt_obj = 0; +static pdf_obj *output_stream; + +#define OBJSTM_MAX_OBJS 200 +/* the limit is only 100 for linearized PDF */ + +typedef struct pdf_objstm +{ + pdf_obj *stream; + unsigned long obj_label[OBJSTM_MAX_OBJS]; + unsigned long obj_pos [OBJSTM_MAX_OBJS]; + unsigned char pos; +} pdf_objstm; + +static int enc_mode; +static int doc_enc_mode; + +static pdf_obj *trailer_dict; +static pdf_obj *xref_stream; /* Internal static routines */ @@ -156,6 +181,8 @@ static void pdf_flush_obj (pdf_obj *object, FILE *file); static void pdf_label_obj (pdf_obj *object); static void pdf_write_obj (pdf_obj *object, FILE *file); +static void pdf_flush_objstm (pdf_objstm *objstm); + static void pdf_out_char (FILE *file, char c); static void pdf_out (FILE *file, const void *buffer, long length); @@ -186,8 +213,8 @@ static void release_dict (pdf_dict *dict); static void write_stream (pdf_stream *stream, FILE *file); static void release_stream (pdf_stream *stream); -static pdf_obj *pdf_ref_file_obj (unsigned long obj_num, unsigned obj_gen); -static pdf_obj *pdf_read_object (unsigned long obj_num, unsigned obj_gen); +static pdf_obj *pdf_ref_file_obj (unsigned long obj_num, unsigned short obj_gen); +static pdf_obj *pdf_read_object (unsigned long obj_num, unsigned short obj_gen); static int verbose = 0; static char compression_level = 9; @@ -212,7 +239,7 @@ pdf_set_compression (int level) return; } -static unsigned pdf_version = 3; +static unsigned pdf_version = 4; void pdf_set_version (unsigned version) @@ -235,13 +262,69 @@ pdf_obj_set_verbose(void) verbose++; } +static pdf_objstm *current_objstm = NULL; + +void +pdf_objstm_init () +{ + if (pdf_version >= 5) { + current_objstm = NEW(1, pdf_objstm); + current_objstm->pos = 0; + } +} + +void +pdf_objstm_close () +{ + if (current_objstm) { + RELEASE(current_objstm); + current_objstm = NULL; + } +} + +static void +add_xref_entry (unsigned long label, unsigned char type, unsigned long field2, unsigned short field3) +{ + if (label >= pdf_max_ind_objects) { + pdf_max_ind_objects = (label/IND_OBJECTS_ALLOC_SIZE+1)*IND_OBJECTS_ALLOC_SIZE; + output_xref = RENEW(output_xref, pdf_max_ind_objects, struct xref_entry); + } + + output_xref[label].type = type; + output_xref[label].field2 = field2; + output_xref[label].field3 = field3; +} + #define BINARY_MARKER "%\344\360\355\370\n" void -pdf_out_init (const char *filename) +pdf_out_init (const char *filename, int do_encryption) { char v; - pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE); + output_xref = NULL; + pdf_max_ind_objects = 0; + add_xref_entry(0, 0, 0, 0xffff); + next_label = 1; + + if (pdf_version >= 5) { + xref_stream = pdf_new_stream(STREAM_COMPRESS); + xref_stream->flags |= OBJ_NO_ENCRYPT; + trailer_dict = pdf_stream_dict(xref_stream); + pdf_add_dict(trailer_dict, pdf_new_name("Type"), pdf_new_name("XRef")); + } else + trailer_dict = pdf_new_dict(); + + output_stream = NULL; + + if (filename == NULL) { /* no filename: writing to stdout */ +#ifdef WIN32 + setmode(fileno(stdout), _O_BINARY); +#endif + pdf_output_file = stdout; + } + else + pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE); + if (!pdf_output_file) { if (strlen(filename) < 128) ERROR("Unable to open \"%s\".", filename); @@ -253,94 +336,134 @@ pdf_out_init (const char *filename) pdf_out(pdf_output_file, &v, 1); pdf_out(pdf_output_file, "\n", 1); pdf_out(pdf_output_file, BINARY_MARKER, strlen(BINARY_MARKER)); + + enc_mode = 0; + doc_enc_mode = do_encryption; } static void -dump_xref (void) +dump_xref_table (void) { long length; unsigned long i; - /* Record where this xref is for trailer */ - startxref = pdf_output_file_position; - pdf_out(pdf_output_file, "xref\n", 5); length = sprintf(format_buffer, "%d %lu\n", 0, next_label); pdf_out(pdf_output_file, format_buffer, length); - length = sprintf(format_buffer, "%010ld %05ld f \n", 0L, 65535L); /* * Every space counts. The space after the 'f' and 'n' is * *essential*. * The PDF spec says the lines must be 20 characters long including the * end of line character. */ - pdf_out(pdf_output_file, format_buffer, length); - for (i = 1; i < next_label; i++){ - length = sprintf(format_buffer, "%010ld %05ld n \n", - output_xref[i-1].file_position, 0L); + for (i = 0; i < next_label; i++) { + unsigned char type = output_xref[i].type; + if (type > 1) + ERROR("object type %hu not allowed in xref table", type); + length = sprintf(format_buffer, "%010lu %05hu %c \n", + output_xref[i].field2, output_xref[i].field3, + type ? 'n' : 'f'); pdf_out(pdf_output_file, format_buffer, length); } - /* Done with xref table */ - RELEASE(output_xref); - output_xref = NULL; } static void -dump_trailer (void) +dump_trailer_dict (void) { - long length; - unsigned long starttrailer; - - starttrailer = pdf_output_file_position; - pdf_out(pdf_output_file, "trailer\n", 8); - pdf_out(pdf_output_file, "<<\n", 3); - - length = sprintf(format_buffer, "/Size %lu\n", next_label); - pdf_out(pdf_output_file, format_buffer, length); - - if (pdf_root_obj == 0) - ERROR ("dump_trailer: Invalid root object"); - length = sprintf(format_buffer, "/Root %u %u R\n", pdf_root_obj, 0); - pdf_out(pdf_output_file, format_buffer, length); + enc_mode = 0; + write_dict(trailer_dict->data, pdf_output_file); + pdf_release_obj(trailer_dict); + pdf_out_char(pdf_output_file, '\n'); +} - if (pdf_encrypt_obj != 0) { - length = sprintf(format_buffer, "/Encrypt %u %u R\n", pdf_encrypt_obj, 0); - pdf_out(pdf_output_file, format_buffer, length); - } - if (pdf_info_obj != 0) { - length = sprintf(format_buffer, "/Info %u %u R\n", pdf_info_obj, 0); - pdf_out(pdf_output_file, format_buffer, length); - } - if (pdf_encrypt_obj != 0) { - unsigned char *id; - id = pdf_enc_id_string(); - length = sprintf(format_buffer, "/ID [<%s> <%s>]\n", id, id); - pdf_out(pdf_output_file, format_buffer, length); +/* + * output a PDF 1.5 cross-reference stream; + * contributed by Matthias Franz (March 21, 2007) + */ +static void +dump_xref_stream (void) +{ + unsigned long pos, i; + unsigned poslen; + unsigned char buf[7] = {0, 0, 0, 0, 0}; + + pdf_obj *w; + + pdf_label_obj(xref_stream); + + /* determine the necessary size of the offset field */ + pos = startxref; /* maximal offset value */ + poslen = 1; + while (pos >>= 8) + poslen++; + + w = pdf_new_array(); + pdf_add_array(w, pdf_new_number(1)); /* type */ + pdf_add_array(w, pdf_new_number(poslen)); /* offset (big-endian) */ + pdf_add_array(w, pdf_new_number(2)); /* generation */ + pdf_add_dict(trailer_dict, pdf_new_name("W"), w); + + /* We need the xref entry for the xref stream right now */ + add_xref_entry(next_label-1, 1, startxref, 0); + + for (i = 0; i < next_label; i++) { + unsigned j; + buf[0] = output_xref[i].type; + pos = output_xref[i].field2; + for (j = poslen; j--; ) { + buf[1+j] = (unsigned char) pos; + pos >>= 8; + } + unsigned short f3 = output_xref[i].field3; + buf[poslen+1] = (unsigned char) (f3 >> 8); + buf[poslen+2] = (unsigned char) (f3); + pdf_add_stream(xref_stream, &buf, poslen+3); } - pdf_out(pdf_output_file, ">>\n", 3); - pdf_out(pdf_output_file, "startxref\n", 10); - - length = sprintf(format_buffer, "%lu\n", startxref); - pdf_out(pdf_output_file, format_buffer, length); - pdf_out(pdf_output_file, "%%EOF\n", 6); + pdf_release_obj(xref_stream); } void pdf_out_flush (void) { if (pdf_output_file) { - dump_xref(); - dump_trailer(); + long length; + + /* Flush current object stream */ + if (current_objstm && current_objstm->pos) + pdf_flush_objstm(current_objstm); + + /* Record where this xref is for trailer */ + startxref = pdf_output_file_position; + + pdf_add_dict(trailer_dict, pdf_new_name("Size"), + pdf_new_number(next_label)); + + if (pdf_version >= 5) + dump_xref_stream(); + else { + dump_xref_table(); + dump_trailer_dict(); + } + + /* Done with xref table */ + RELEASE(output_xref); + + pdf_out(pdf_output_file, "startxref\n", 10); + length = sprintf(format_buffer, "%lu\n", startxref); + pdf_out(pdf_output_file, format_buffer, length); + pdf_out(pdf_output_file, "%%EOF\n", 6); + MESG("\n"); if (verbose) { if (compression_level > 0) { - MESG("Compression eliminated approximately %lu bytes\n", compression_saved); + MESG("Compression saved %ld bytes%s\n", compression_saved, + pdf_version < 5 ? ". Try \"-V 5\" for better compression" : ""); } } - MESG("%lu bytes written", pdf_output_file_position); + MESG("%ld bytes written", pdf_output_file_position); MFCLOSE(pdf_output_file); } @@ -361,50 +484,52 @@ pdf_error_cleanup (void) void pdf_set_root (pdf_obj *object) { - if (pdf_root_obj != 0) { + if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) { ERROR("Root object already set!"); } - if (object->label == 0) { /* Make sure this object has a label */ - pdf_label_obj(object); - } - pdf_root_obj = object->label; + /* Adobe Readers don't like a document catalog inside an encrypted + * object stream, although the PDF v1.5 spec seems to allow this. + * Note that we don't set OBJ_NO_ENCRYPT since the name dictionary in + * a document catalog may contain strings, which should be encrypted. + */ + if (doc_enc_mode) + object->flags |= OBJ_NO_OBJSTM; } void pdf_set_info (pdf_obj *object) { - if (pdf_info_obj != 0) { + if (pdf_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) { ERROR ("Info object already set!"); } - if (object->label == 0) { /* Make sure this object has a label */ - pdf_label_obj(object); - } - pdf_info_obj = object->label; } void -pdf_set_encrypt (pdf_obj *object) +pdf_set_encrypt (pdf_obj *encrypt, pdf_obj *id) { - if (pdf_encrypt_obj != 0) { + if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) { ERROR("Encrypt object already set!"); } - if (object->label == 0) { /* Make sure this object has a label */ - pdf_label_obj(object); - } - pdf_encrypt_obj = object->label; + encrypt->flags |= OBJ_NO_ENCRYPT; + + pdf_add_dict(trailer_dict, pdf_new_name("ID"), id); } static void pdf_out_char (FILE *file, char c) { - fputc(c, file); - /* Keep tallys for xref table *only* if writing a pdf file. */ - if (file == pdf_output_file) { - pdf_output_file_position += 1; - if (c == '\n') - pdf_output_line_position = 0; - else - pdf_output_line_position += 1; + if (output_stream && file == pdf_output_file) + pdf_add_stream(output_stream, &c, 1); + else { + fputc(c, file); + /* Keep tallys for xref table *only* if writing a pdf file. */ + if (file == pdf_output_file) { + pdf_output_file_position += 1; + if (c == '\n') + pdf_output_line_position = 0; + else + pdf_output_line_position += 1; + } } } @@ -419,18 +544,32 @@ void pdf_out_char (FILE *file, char c) static void pdf_out (FILE *file, const void *buffer, long length) { - fwrite(buffer, 1, length, file); - /* Keep tallys for xref table *only* if writing a pdf file */ - if (file == pdf_output_file) { - pdf_output_file_position += length; - pdf_output_line_position += length; - /* "foo\nbar\n "... */ - if (length > 0 && + if (output_stream && file == pdf_output_file) + pdf_add_stream(output_stream, buffer, length); + else { + fwrite(buffer, 1, length, file); + /* Keep tallys for xref table *only* if writing a pdf file */ + if (file == pdf_output_file) { + pdf_output_file_position += length; + pdf_output_line_position += length; + /* "foo\nbar\n "... */ + if (length > 0 && ((char *)buffer)[length-1] == '\n') - pdf_output_line_position = 0; + pdf_output_line_position = 0; + } } } +/* returns 1 if a white-space character is necessary to separate + an object of type1 followed by an object of type2 */ +static +int pdf_need_white (int type1, int type2) +{ + return !(type1 == PDF_STRING || type1 == PDF_ARRAY || type1 == PDF_DICT || + type2 == PDF_STRING || type2 == PDF_NAME || + type2 == PDF_ARRAY || type2 == PDF_DICT); +} + static void pdf_out_white (FILE *file) { @@ -461,6 +600,7 @@ pdf_new_obj(int type) result->label = 0; result->generation = 0; result->refcount = 1; + result->flags = 0; return result; } @@ -480,20 +620,12 @@ pdf_label_obj (pdf_obj *object) if (INVALIDOBJ(object)) ERROR("pdf_label_obj(): passed invalid object."); - if (next_label > pdf_max_ind_objects) { - pdf_max_ind_objects += IND_OBJECTS_ALLOC_SIZE; - output_xref = RENEW(output_xref, pdf_max_ind_objects, struct xref_entry); - } /* * Don't change label on an already labeled object. Ignore such calls. */ if (object->label == 0) { - /* Save so we can lookup this object by its number */ - output_xref[next_label-1].object = object; - output_xref[next_label-1].file_position = 0L; - object->label = next_label; + object->label = next_label++; object->generation = 0; - next_label++; } } @@ -563,13 +695,13 @@ write_indirect (pdf_indirect *indirect, FILE *file) if (indirect->dirty) { if (file == stderr) { pdf_out(file, "{d}", 3); - length = sprintf(format_buffer, "%d %d R", indirect->label, indirect->generation); + length = sprintf(format_buffer, "%lu %hu R", indirect->label, indirect->generation); pdf_out(stderr, format_buffer, length); } else { pdf_obj *clean; if (indirect->dirty_file != pdf_input_file) { - ERROR("Input PDF file doesn't match object: label=%d, from_file=%p, current_file=%p", + ERROR("Input PDF file doesn't match object: label=%lu, from_file=%p, current_file=%p", indirect->label, indirect->dirty_file, pdf_input_file); } clean = pdf_ref_file_obj(indirect->label, indirect->generation); @@ -577,7 +709,7 @@ write_indirect (pdf_indirect *indirect, FILE *file) pdf_release_obj(clean); } } else { - length = sprintf(format_buffer, "%d %d R", indirect->label, indirect->generation); + length = sprintf(format_buffer, "%lu %hu R", indirect->label, indirect->generation); pdf_out(file, format_buffer, length); } } @@ -821,7 +953,10 @@ write_string (pdf_string *str, FILE *file) int nescc = 0, i, count; s = str->string; - pdf_encrypt_data(s, str->length); + + if (enc_mode) + pdf_encrypt_data(s, str->length); + /* * Count all ASCII non-printable characters. */ @@ -1022,13 +1157,17 @@ write_array (pdf_array *array, FILE *file) pdf_out_char(file, '['); if (array->size > 0) { unsigned long i; - + int type1 = PDF_UNDEFINED, type2; + for (i = 0; i < array->size; i++) { - if (i > 0) - pdf_out_white(file); - if (!array->values[i]) + if (array->values[i]) { + type2 = array->values[i]->type; + if (type1 != PDF_UNDEFINED && pdf_need_white(type1, type2)) + pdf_out_white(file); + type1 = type2; + pdf_write_obj(array->values[i], file); + } else WARN("PDF array element #ld undefined.", i); - pdf_write_obj(array->values[i], file); } } pdf_out_char(file, ']'); @@ -1201,10 +1340,7 @@ write_dict (pdf_dict *dict, FILE *file) pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */ while (dict->key != NULL) { pdf_write_obj(dict->key, file); - if (((dict -> value)->type) == PDF_BOOLEAN || - ((dict -> value)->type) == PDF_NUMBER || - ((dict -> value)->type) == PDF_INDIRECT || - ((dict -> value)->type) == PDF_NULL) { + if (pdf_need_white(PDF_NAME, (dict->value)->type)) { pdf_out_white(file); } pdf_write_obj(dict->value, file); @@ -1248,10 +1384,11 @@ release_dict (pdf_dict *data) } /* Array is ended by a node with NULL this pointer */ -void +/* pdf_add_dict returns 0 if the key is new and non-zero otherwise */ +int pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value) { - pdf_dict *data; + pdf_dict *data, *new_node; TYPECHECK(dict, PDF_DICT); TYPECHECK(key, PDF_NAME); @@ -1260,34 +1397,29 @@ pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value) if (value != NULL && INVALIDOBJ(value)) ERROR("pdf_add_dict(): Passed invalid value"); - data = dict->data; /* If this key already exists, simply replace the value */ - while (data->key != NULL) { + for (data = dict->data; data->key != NULL; data = data->next) { if (!strcmp(pdf_name_value(key), pdf_name_value(data->key))) { /* Release the old value */ pdf_release_obj(data->value); /* Release the new key (we don't need it) */ pdf_release_obj(key); data->value = value; - break; + return 1; } - data = data->next; } /* - * If we didn't find the key, build a new "end" node and add + * We didn't find the key. We build a new "end" node and add * the new key just before the end */ - if (data->key == NULL) { - pdf_dict *new_node; - - new_node = NEW (1, pdf_dict); - new_node->key = NULL; - new_node->value = NULL; - new_node->next = NULL; - data->next = new_node; - data->key = key; - data->value = value; - } + new_node = NEW (1, pdf_dict); + new_node->key = NULL; + new_node->value = NULL; + new_node->next = NULL; + data->next = new_node; + data->key = key; + data->value = value; + return 0; } void @@ -1456,6 +1588,7 @@ pdf_new_stream (int flags) data->max_length = 0; result->data = data; + result->flags |= OBJ_NO_OBJSTM; return result; } @@ -1490,19 +1623,25 @@ write_stream (pdf_stream *stream, FILE *file) (stream->_flags & STREAM_COMPRESS) && compression_level > 0) { + pdf_obj *filters = pdf_lookup_dict(stream->dict, "Filter"); + buffer_length = filtered_length + filtered_length/1000 + 14; buffer = NEW(buffer_length, unsigned char); { - pdf_obj *filters; + pdf_obj *filter_name = pdf_new_name("FlateDecode"); - filters = pdf_lookup_dict(stream->dict, "Filter"); - if (!filters) - filters = pdf_new_array(); - /* - * FlateDecode is the first filter to be applied to the stream. - */ - pdf_unshift_array(filters, pdf_new_name("FlateDecode")); - pdf_add_dict(stream->dict, pdf_new_name("Filter"), filters); + if (filters) + /* + * FlateDecode is the first filter to be applied to the stream. + */ + pdf_unshift_array(filters, filter_name); + else + /* + * Adding the filter as a name instead of a one-element array + * is crucial because otherwise Adobe Reader cannot read the + * cross-reference stream any more, cf. the PDF v1.5 Errata. + */ + pdf_add_dict(stream->dict, pdf_new_name("Filter"), filter_name); } #ifdef HAVE_ZLIB_COMPRESS2 if (compress2(buffer, &buffer_length, filtered, @@ -1516,7 +1655,8 @@ write_stream (pdf_stream *stream, FILE *file) } #endif /* HAVE_ZLIB_COMPRESS2 */ RELEASE(filtered); - compression_saved += filtered_length - buffer_length - strlen("/Filter [/FlateDecode]\n"); + compression_saved += filtered_length - buffer_length + - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n")); filtered = buffer; filtered_length = buffer_length; @@ -1541,7 +1681,10 @@ write_stream (pdf_stream *stream, FILE *file) pdf_write_obj(stream->dict, file); pdf_out(file, "\nstream\n", 8); - pdf_encrypt_data(filtered, filtered_length); + + if (enc_mode) + pdf_encrypt_data(filtered, filtered_length); + if (filtered_length > 0) { pdf_out(file, filtered, filtered_length); } @@ -1700,11 +1843,12 @@ pdf_flush_obj (pdf_obj *object, FILE *file) long length; /* - * Record file position. No object is numbered 0, so subtract 1 - * when using as an array index + * Record file position */ - output_xref[object->label-1].file_position = pdf_output_file_position; - length = sprintf(format_buffer, "%lu %d obj\n", object->label, object->generation); + add_xref_entry(object->label, 1, + pdf_output_file_position, object->generation); + length = sprintf(format_buffer, "%lu %hu obj\n", object->label, object->generation); + enc_mode = doc_enc_mode && !(object->flags & OBJ_NO_ENCRYPT); pdf_enc_set_label(object->label); pdf_enc_set_generation(object->generation); pdf_out(file, format_buffer, length); @@ -1712,6 +1856,64 @@ pdf_flush_obj (pdf_obj *object, FILE *file) pdf_out(file, "\nendobj\n", 8); } +static void +pdf_add_objstm (pdf_objstm *objstm, pdf_obj *object) +{ + unsigned char pos = objstm->pos++; + + if (!pos) { + pdf_obj *stream = pdf_new_stream(STREAM_COMPRESS); + pdf_label_obj(stream); + objstm->stream = stream; + } + objstm->obj_label[pos] = object->label; + objstm->obj_pos[pos] = pdf_stream_length(objstm->stream); + + add_xref_entry(object->label, 2, objstm->stream->label, pos); + + output_stream = objstm->stream; + enc_mode = 0; + pdf_write_obj(object, pdf_output_file); + pdf_out_char(pdf_output_file, '\n'); + output_stream = NULL; + + if (pos == OBJSTM_MAX_OBJS-1) + pdf_flush_objstm(objstm); +} + +static void +pdf_flush_objstm (pdf_objstm *objstm) +{ + unsigned char pos = objstm->pos; + pdf_obj *stream_obj = objstm->stream; + TYPECHECK(stream_obj, PDF_STREAM); + pdf_stream *stream = (pdf_stream *) stream_obj->data; + + /* Precede stream data by offset table */ + unsigned char *old_buf = stream->stream; + unsigned long old_length = stream->stream_length; + /* Reserve 22 bytes for each entry (two 10 digit numbers plus two spaces) */ + stream->stream = NEW(old_length + 22*pos, unsigned char); + stream->stream_length = 0; + + unsigned char i; + for (i = 0; i < pos; i++) { + long length = sprintf(format_buffer, "%lu %lu ", + objstm->obj_label[i], objstm->obj_pos[i]); + pdf_add_stream(stream_obj, format_buffer, length); + } + + pdf_obj *dict = pdf_stream_dict(stream_obj); + pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("ObjStm")); + pdf_add_dict(dict, pdf_new_name("N"), pdf_new_number(pos)); + pdf_add_dict(dict, pdf_new_name("First"), pdf_new_number(stream->stream_length)); + + pdf_add_stream(stream_obj, old_buf, old_length); + RELEASE(old_buf); + pdf_release_obj(stream_obj); + objstm->pos = 0; +} + void pdf_release_obj (pdf_obj *object) { @@ -1729,8 +1931,13 @@ pdf_release_obj (pdf_obj *object) * Nothing is using this object so it's okay to remove it. * Nonzero "label" means object needs to be written before it's destroyed. */ - if (object->label && pdf_output_file != NULL) { - pdf_flush_obj(object, pdf_output_file); + if (object->label && pdf_output_file != NULL) { + if (!current_objstm || object->flags & OBJ_NO_OBJSTM + || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT) + || object->generation) + pdf_flush_obj(object, pdf_output_file); + else + pdf_add_objstm(current_objstm, object); } switch (object->type) { case PDF_BOOLEAN: @@ -2020,14 +2227,14 @@ next_object_offset (unsigned long obj_num) * returns the retained existing reference to that object */ static pdf_obj * -pdf_ref_file_obj (unsigned long obj_num, unsigned obj_gen) +pdf_ref_file_obj (unsigned long obj_num, unsigned short obj_gen) { pdf_obj *obj, *ref; if (!checklabel(obj_num, obj_gen)) { WARN("Can't resolve object: %lu %u", obj_num, obj_gen); - return NULL; + return pdf_new_null(); } ref = xref_table[obj_num].indirect; if (ref != NULL) @@ -2050,15 +2257,11 @@ pdf_ref_file_obj (unsigned long obj_num, unsigned obj_gen) pdf_obj * -pdf_new_ref (unsigned long obj_num, int obj_gen) +pdf_new_ref (unsigned long obj_num, unsigned short obj_gen) { pdf_obj *result; pdf_indirect *indirect; - if (!checklabel(obj_num, obj_gen)) { - WARN("Invalid object label: %lu %d", obj_num, obj_gen); - return NULL; - } result = pdf_new_obj(PDF_INDIRECT); indirect = NEW(1, pdf_indirect); result->data = indirect; @@ -2075,7 +2278,7 @@ pdf_new_ref (unsigned long obj_num, int obj_gen) * be replaced with "null". But we won't do that. */ static pdf_obj * -pdf_read_object (unsigned long obj_num, unsigned obj_gen) +pdf_read_object (unsigned long obj_num, unsigned short obj_gen) { pdf_obj *result; long offset, limit, length; @@ -2084,7 +2287,7 @@ pdf_read_object (unsigned long obj_num, unsigned obj_gen) if (!checklabel(obj_num, obj_gen)) { WARN("Trying to read nonexistent object: %lu %u", obj_num, obj_gen); - return NULL; + return pdf_new_null(); } if (labelfreed(obj_num, obj_gen)) { WARN("Trying to read deleted object: %lu %u", @@ -2361,7 +2564,7 @@ pdf_open (FILE *file) } pdf_input_file = file; if (!check_for_pdf(pdf_input_file)) { - WARN("pdf_open: Not a PDF 1.[1-3] file."); + WARN("pdf_open: Not a PDF 1.[1-5] file."); return NULL; } if ((trailer = read_xref()) == NULL) { diff --git a/Build/source/texk/xdvipdfmx/src/pdfobj.h b/Build/source/texk/xdvipdfmx/src/pdfobj.h index 9ca8df47b7e..346e38bd31b 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfobj.h +++ b/Build/source/texk/xdvipdfmx/src/pdfobj.h @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfobj.h,v 1.21 2005/05/04 16:10:06 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfobj.h,v 1.23 2007/11/14 03:36:01 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -51,10 +51,12 @@ typedef struct pdf_obj pdf_obj; extern void pdf_obj_set_verbose (void); extern void pdf_error_cleanup (void); -extern void pdf_out_init (const char *filename); +extern void pdf_out_init (const char *filename, int do_encryption); extern void pdf_out_flush (void); extern void pdf_set_version (unsigned version); extern unsigned pdf_get_version (void); +extern void pdf_objstm_init (void); +extern void pdf_objstm_close (void); extern pdf_obj *pdf_new_obj (int type); extern void pdf_release_obj (pdf_obj *object); @@ -124,7 +126,7 @@ extern pdf_obj *pdf_dict_keys (pdf_obj *dict); * pdf_link_obj() it rather than allocate/free-ing them each time. But I * already removed that. */ -extern void pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value); +extern int pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value); extern void pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value); /* Apply proc(key, value, pdata) for each key-value pairs in dict, stop if proc() @@ -160,7 +162,7 @@ extern void pdf_set_compression (int level); extern void pdf_set_info (pdf_obj *obj); extern void pdf_set_root (pdf_obj *obj); -extern void pdf_set_encrypt (pdf_obj *obj); +extern void pdf_set_encrypt (pdf_obj *encrypt, pdf_obj *id); extern int check_for_pdf (FILE *file); extern pdf_obj *pdf_open (FILE *file); @@ -171,7 +173,7 @@ extern pdf_obj *pdf_import_object (pdf_obj *object); extern int pdfobj_escape_str (char *buffer, int size, const unsigned char *s, int len); -extern pdf_obj *pdf_new_ref (unsigned long label, int generation); +extern pdf_obj *pdf_new_ref (unsigned long label, unsigned short generation); extern void pdf_copy_object (pdf_obj *dst, pdf_obj *src); #endif /* _PDFOBJ_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/pdfparse.c b/Build/source/texk/xdvipdfmx/src/pdfparse.c index c7dc79a2990..3d31b3e6c07 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfparse.c +++ b/Build/source/texk/xdvipdfmx/src/pdfparse.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfparse.c,v 1.39 2005/07/21 05:05:14 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfparse.c,v 1.40 2007/04/03 05:11:39 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -952,7 +952,8 @@ parse_pdf_reference (char **start, char *end) static pdf_obj * try_pdf_reference (char *start, char *end, char **endptr) { - unsigned long id = 0, gen = 0; + unsigned long id = 0; + unsigned short gen = 0; if (endptr) *endptr = start; @@ -989,7 +990,7 @@ try_pdf_reference (char *start, char *end, char **endptr) if (endptr) *endptr = start; - return pdf_new_ref(id, (int) gen); + return pdf_new_ref(id, gen); } pdf_obj * diff --git a/Build/source/texk/xdvipdfmx/src/pdfximage.c b/Build/source/texk/xdvipdfmx/src/pdfximage.c index 72c287fe2d1..c67b8047b73 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfximage.c +++ b/Build/source/texk/xdvipdfmx/src/pdfximage.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfximage.c,v 1.14 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfximage.c,v 1.17 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -63,14 +63,15 @@ static int ps_include_page (pdf_ximage *ximage, const char *file_name); struct attr_ { long width, height; + double xdensity, ydensity; pdf_rect bbox; - double xdpi, ydpi; }; struct pdf_ximage_ { char *ident; char res_name[16]; + long page_no, page_count; int subtype; @@ -79,7 +80,6 @@ struct pdf_ximage_ char *filename; pdf_obj *reference; pdf_obj *resource; - int page_index; int pdf_box; }; @@ -112,18 +112,18 @@ static void pdf_init_ximage_struct (pdf_ximage *I) { I->ident = NULL; + I->page_no = I->page_count = 0; I->filename = NULL; I->subtype = -1; memset(I->res_name, 0, 16); I->reference = NULL; I->resource = NULL; - I->page_index = 0; I->pdf_box = 0; I->attr.width = I->attr.height = 0; + I->attr.xdensity = I->attr.ydensity = 1.0; I->attr.bbox.llx = I->attr.bbox.lly = 0; I->attr.bbox.urx = I->attr.bbox.ury = 0; - I->attr.xdpi = I->attr.ydpi = 72.0; } static void @@ -256,8 +256,8 @@ filter_put_form_attr (pdf_obj *kp, pdf_obj *vp, void *dp) static int -load_image (const char *ident, int page_index, int pdf_box, - const char *fullname, int format, FILE *fp) +load_image (const char *ident, + const char *fullname, int format, FILE *fp, long page_no) { struct ic_ *ic = &_ic; int id = -1; /* ret */ @@ -271,6 +271,7 @@ load_image (const char *ident, int page_index, int pdf_box, I = &ic->ximages[id]; pdf_init_ximage_struct(I); + pdf_ximage_set_page(I, page_no, 0); switch (format) { case IMAGE_TYPE_JPEG: @@ -299,11 +300,12 @@ load_image (const char *ident, int page_index, int pdf_box, case IMAGE_TYPE_PDF: if (_opts.verbose) MESG("[PDF]"); - if (pdf_include_page(I, fp, page_index, pdf_box) < 0) +// if (pdf_include_page(I, fp, page_index, pdf_box) < 0) + if (pdf_include_page(I, fp) < 0) return -1; I->subtype = PDF_XOBJECT_TYPE_FORM; - I->page_index = page_index; - I->pdf_box = pdf_box; +// I->page_index = page_index; +// I->pdf_box = pdf_box; break; case IMAGE_TYPE_EPS: if (_opts.verbose) @@ -348,7 +350,7 @@ load_image (const char *ident, int page_index, int pdf_box, #define dpx_fclose(f) (MFCLOSE((f))) int -pdf_ximage_findresource (const char *ident, int page_index, int pdf_box) +pdf_ximage_findresource (const char *ident, long page_no) { struct ic_ *ic = &_ic; int id = -1; @@ -359,9 +361,8 @@ pdf_ximage_findresource (const char *ident, int page_index, int pdf_box) for (id = 0; id < ic->count; id++) { I = &ic->ximages[id]; - if (I->ident && !strcmp(ident, I->ident) - && page_index == I->page_index - && pdf_box == I->pdf_box) { + if (I->ident && !strcmp(ident, I->ident) && + I->page_no == page_no + (page_no < 0 ? I->page_count+1 : 0)) { return id; } } @@ -393,7 +394,7 @@ pdf_ximage_findresource (const char *ident, int page_index, int pdf_box) id = mps_include_page(ident, fp); break; default: - id = load_image(ident, page_index, pdf_box, fullname, format, fp); + id = load_image(ident, fullname, format, fp, page_no); break; } dpx_fclose(fp); @@ -409,6 +410,20 @@ pdf_ximage_findresource (const char *ident, int page_index, int pdf_box) return id; } +/* Reference: PDF Reference 1.5 v6, pp.321--322 + * + * TABLE 4.42 Additional entries specific to a type 1 form dictionary + * + * BBox rectangle (Required) An array of four numbers in the form coordinate + * system, giving the coordinates of the left, bottom, right, + * and top edges, respectively, of the form XObject's bounding + * box. These boundaries are used to clip the form XObject and + * to determine its size for caching. + * + * Matrix array (Optional) An array of six numbers specifying the form + * matrix, which maps form space into user space. + * Default value: the identity matrix [1 0 0 1 0 0]. + */ void pdf_ximage_init_form_info (xform_info *info) { @@ -425,6 +440,36 @@ pdf_ximage_init_form_info (xform_info *info) info->matrix.f = 0.0; } +/* Reference: PDF Reference 1.5 v6, pp.303--306 + * + * TABLE 4.42 Additional entries specific to an image dictionary + * + * Width integer (Required) The width of the image, in samples. + * + * Height integer (Required) The height of the image, in samples. + * + * ColorSpace name or array + * (Required for images, except those that use the JPXDecode + * filter; not allowed for image masks) The color space in + * which image samples are specified. This may be any type + * of color space except Patter. + * + * If the image uses the JPXDecode filter, this entry is + * optional. + * + * BitsPerComponent integer + * (Required except for image masks and images that use the + * JPXDecode filter) The number of bits used to represent + * each color component. Only a single value may be specified; + * the number of bits is the same for all color components. + * Valid values are 1,2,4,8, and (in PDF1.5) 16. If ImageMask + * is true, this entry is optional, and if speficified, its + * value must be 1. + * + * If the image stream uses the JPXDecode filter, this entry + * is optional and ignored if present. The bit depth is + * determined in the process of decoding the JPEG2000 image. + */ void pdf_ximage_init_image_info (ximage_info *info) { @@ -434,7 +479,7 @@ pdf_ximage_init_image_info (ximage_info *info) info->bits_per_component = 0; info->num_components = 0; info->min_dpi = 0; - info->xdpi = info->ydpi = 72.0; + info->xdensity = info->ydensity = 1.0; } void @@ -444,15 +489,14 @@ pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) ximage_info *info = image_info; if (!PDF_OBJ_STREAMTYPE(resource)) - ERROR("Image XObject must be stream type."); + ERROR("Image XObject must be of stream type."); I->subtype = PDF_XOBJECT_TYPE_IMAGE; - I->attr.width = info->width; - I->attr.height = info->height; - - I->attr.xdpi = info->xdpi; - I->attr.ydpi = info->ydpi; + I->attr.width = info->width; /* The width of the image, in samples */ + I->attr.height = info->height; /* The height of the image, in samples */ + I->attr.xdensity = info->xdensity; + I->attr.ydensity = info->ydensity; I->reference = pdf_ref_obj(resource); @@ -469,21 +513,36 @@ pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) } void -pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) +pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) { - xform_info *info = form_info; + xform_info *info = form_info; I->subtype = PDF_XOBJECT_TYPE_FORM; + I->attr.bbox.llx = info->bbox.llx; I->attr.bbox.lly = info->bbox.lly; I->attr.bbox.urx = info->bbox.urx; I->attr.bbox.ury = info->bbox.ury; I->reference = pdf_ref_obj(resource); + pdf_release_obj(resource); /* Caller don't know we are using reference. */ I->resource = NULL; } +long +pdf_ximage_get_page (pdf_ximage *I) +{ + return I->page_no; +} + +void +pdf_ximage_set_page (pdf_ximage *I, long page_no, long page_count) +{ + I->page_no = page_no; + I->page_count = page_count; +} + #define CHECK_ID(c,n) do {\ if ((n) < 0 || (n) >= (c)->count) {\ @@ -495,8 +554,8 @@ pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) pdf_obj * pdf_ximage_get_reference (int id) { - struct ic_ *ic = &_ic; - pdf_ximage *I; + struct ic_ *ic = &_ic; + pdf_ximage *I; CHECK_ID(ic, id); @@ -504,16 +563,17 @@ pdf_ximage_get_reference (int id) if (!I->reference) I->reference = pdf_ref_obj(I->resource); - return pdf_link_obj(I->reference); + return pdf_link_obj(I->reference); } +/* called from pdfdoc.c only for late binding */ int pdf_ximage_defineresource (const char *ident, int subtype, void *info, pdf_obj *resource) { - struct ic_ *ic = &_ic; - int id; - pdf_ximage *I; + struct ic_ *ic = &_ic; + int id; + pdf_ximage *I; id = ic->count; if (ic->count >= ic->capacity) { @@ -532,12 +592,10 @@ pdf_ximage_defineresource (const char *ident, switch (subtype) { case PDF_XOBJECT_TYPE_IMAGE: pdf_ximage_set_image(I, info, resource); - I->subtype = PDF_XOBJECT_TYPE_IMAGE; sprintf(I->res_name, "Im%d", id); break; case PDF_XOBJECT_TYPE_FORM: pdf_ximage_set_form (I, info, resource); - I->subtype = PDF_XOBJECT_TYPE_FORM; sprintf(I->res_name, "Fm%d", id); break; default: @@ -552,71 +610,77 @@ pdf_ximage_defineresource (const char *ident, char * pdf_ximage_get_resname (int id) { - struct ic_ *ic = &_ic; - pdf_ximage *I; + struct ic_ *ic = &_ic; + pdf_ximage *I; CHECK_ID(ic, id); I = GET_IMAGE(ic, id); - return I->res_name; + return I->res_name; } + /* depth... * Dvipdfm treat "depth" as "yoffset" for pdf:image and pdf:uxobj * not as vertical dimension of scaled image. (And there are bugs.) * This part contains incompatibile behaviour than dvipdfm! */ -#define EBB_DPI 72 /* was 100 in dvipdfmx; changed to 72 to match xetex's ideas - about graphics resolution/scaling */ +#define EBB_DPI 72 + static void scale_to_fit_I (pdf_tmatrix *T, transform_info *p, pdf_ximage *I) { - double s_x, s_y; - long wdx = I->attr.width; - long htx = I->attr.height; - double ar, dp; - double xdpi = I->attr.xdpi; - double ydpi = I->attr.ydpi; - - /* if image didn't have DPI info, then treat it as EBB_DPI */ - if (xdpi == 0.0) - xdpi = EBB_DPI; - if (ydpi == 0.0) - ydpi = EBB_DPI; + double s_x, s_y, d_x, d_y; + double wd0, ht0, dp, xscale, yscale; - if (htx == 0) { - WARN("Image height=0!"); - htx = 1; + if (p->flags & INFO_HAS_USER_BBOX) { + wd0 = p->bbox.urx - p->bbox.llx; + ht0 = p->bbox.ury - p->bbox.lly; + xscale = I->attr.width * I->attr.xdensity / wd0; + yscale = I->attr.height * I->attr.ydensity / ht0; + d_x = -p->bbox.llx / wd0; + d_y = -p->bbox.lly / ht0; + } else { + wd0 = I->attr.width * I->attr.xdensity; + ht0 = I->attr.height * I->attr.ydensity; + xscale = yscale = 1.0; + d_x = 0.0; + d_y = 0.0; } - ar = (double) wdx / htx; + if (wd0 == 0.0) { + WARN("Image width=0.0!"); + wd0 = 1.0; + } + if (ht0 == 0.0) { + WARN("Image height=0.0!"); + ht0 = 1.0; + } - /* only width/height --> uniform (keep aspect ratio) - * no width-height --> uniform with 72dpi implied (?) - * both width-height --> non-uniform - */ if ( (p->flags & INFO_HAS_WIDTH ) && (p->flags & INFO_HAS_HEIGHT) ) { - s_x = p->width; s_y = p->height + p->depth; - dp = p->depth; - } else if ( p->flags & INFO_HAS_WIDTH ) { - s_x = p->width; s_y = s_x / ar; + s_x = p->width * xscale; + s_y = (p->height + p->depth) * yscale; + dp = p->depth * yscale; + } else if ( p->flags & INFO_HAS_WIDTH ) { + s_x = p->width * xscale; + s_y = s_x * ((double)I->attr.height / I->attr.width); dp = 0.0; - } else if ( p->flags & INFO_HAS_HEIGHT ) { - s_y = p->height + p->depth; s_x = s_y * ar; - dp = p->depth; + } else if ( p->flags & INFO_HAS_HEIGHT) { + s_y = (p->height + p->depth) * yscale; + s_x = s_y * ((double)I->attr.width / I->attr.height); + dp = p->depth * yscale; } else { - s_x = wdx * 72.0 / xdpi; - s_y = htx * 72.0 / ydpi; + s_x = wd0; + s_y = ht0; dp = 0.0; } - - T->a = s_x; T->c = 0.0; - T->b = 0.0; T->d = s_y; - T->e = 0.0; T->f = -dp; + T->a = s_x; T->c = 0.0; + T->b = 0.0; T->d = s_y; + T->e = d_x * s_x / xscale; T->f = d_y * s_y / yscale - dp; return; } @@ -677,15 +741,16 @@ scale_to_fit_F (pdf_tmatrix *T, } +/* called from pdfdev.c and spc_html.c */ int pdf_ximage_scale_image (int id, - pdf_tmatrix *M, /* ret */ - pdf_rect *r, /* ret */ - transform_info *p /* arg */ + pdf_tmatrix *M, /* return value for trans matrix */ + pdf_rect *r, /* return value for clipping */ + transform_info *p /* argument from specials */ ) { - struct ic_ *ic = &_ic; - pdf_ximage *I; + struct ic_ *ic = &_ic; + pdf_ximage *I; CHECK_ID(ic, id); @@ -694,13 +759,47 @@ pdf_ximage_scale_image (int id, pdf_setmatrix(M, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); switch (I->subtype) { + /* Reference: PDF Reference 1.5 v6, p.302 + * + * An image can be placed on the output page in any desired position, + * orientation, and size by using the cm operator to modify the current + * transformation matrix (CTM) so as to map the unit square of user space + * to the rectangle or parallelogram in which the image is to be painted. + * + * There is neither BBox nor Matrix key in the image XObject. + * Everything must be controlled by the cm operator. + * + * The argument [p] contains the user-defined bounding box, the scailing + * factor of which is bp as EPS and PDF. On the other hand, I->attr + * contains the (sampling) width and the (sampling) height of the image. + * + * There is no problem if a bitmap image has density information. + * Otherwise, DVIPDFM's ebb generates bounding box as 100px = 72bp = 1in. + * In this case, screen captured images look bad. Moreover, DVIPDFM's ebb + * ignores all density information and use just 100px = 72bp = 1in. + * + * On the other hand, pdfTeX uses 100px = 100bp to get a better quality + * for screen captured images. + * + * DVIPDFMx's xbb generates bounding box as 100px = 100bp in the same + * way as pdfTeX. Furthermore, it takes care of density information too. + */ case PDF_XOBJECT_TYPE_IMAGE: scale_to_fit_I(M, p, I); - r->llx = 0.0; - r->lly = 0.0; - r->urx = M->a; - r->ury = M->d; + if (p->flags & INFO_HAS_USER_BBOX) { + r->llx = p->bbox.llx / (I->attr.width * I->attr.xdensity); + r->lly = p->bbox.lly / (I->attr.height * I->attr.ydensity); + r->urx = p->bbox.urx / (I->attr.width * I->attr.xdensity); + r->ury = p->bbox.ury / (I->attr.height * I->attr.ydensity); + } else { + r->llx = 0.0; + r->lly = 0.0; + r->urx = 1.0; + r->ury = 1.0; + } break; + /* User-defined transformation and clipping are controlled by + * the cm operator and W operator, explicitly */ case PDF_XOBJECT_TYPE_FORM: scale_to_fit_F(M, p, I); if (p->flags & INFO_HAS_USER_BBOX) { @@ -708,7 +807,7 @@ pdf_ximage_scale_image (int id, r->lly = p->bbox.lly; r->urx = p->bbox.urx; r->ury = p->bbox.ury; - } else { + } else { /* I->attr.bbox from the image bounding box */ r->llx = I->attr.bbox.llx; r->lly = I->attr.bbox.lly; r->urx = I->attr.bbox.urx; @@ -736,6 +835,11 @@ void set_distiller_template (char *s) return; } +char *get_distiller_template (void) +{ + return _opts.cmdtmpl; +} + static int ps_include_page (pdf_ximage *ximage, const char *filename) { @@ -776,7 +880,8 @@ ps_include_page (pdf_ximage *ximage, const char *filename) dpx_delete_temp_file(temp); return -1; } - error = pdf_include_page(ximage, fp, 0, pdfbox_crop); +// error = pdf_include_page(ximage, fp, 0, pdfbox_crop); + error = pdf_include_page(ximage, fp); MFCLOSE(fp); if (_opts.verbose > 1) { @@ -803,5 +908,3 @@ static int check_for_ps (FILE *image_file) return 1; return 0; } - - diff --git a/Build/source/texk/xdvipdfmx/src/pdfximage.h b/Build/source/texk/xdvipdfmx/src/pdfximage.h index 730e5a1f9c5..782af5c106c 100644 --- a/Build/source/texk/xdvipdfmx/src/pdfximage.h +++ b/Build/source/texk/xdvipdfmx/src/pdfximage.h @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pdfximage.h,v 1.8 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pdfximage.h,v 1.11 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -39,10 +39,9 @@ typedef struct { int bits_per_component; int num_components; - double xdpi; - double ydpi; - long min_dpi; /* NOT USED YET */ + + double xdensity, ydensity; /* scale factor for bp */ } ximage_info; typedef struct { @@ -63,7 +62,7 @@ extern char *pdf_ximage_get_resname (int xobj_id); extern pdf_obj *pdf_ximage_get_reference (int xobj_id); -extern int pdf_ximage_findresource (const char *ident, int page_index, int pdf_box); +extern int pdf_ximage_findresource (const char *ident, long page_no/*, int pdf_box*/); extern int pdf_ximage_defineresource (const char *ident, int subtype, void *cdata, pdf_obj *resource); @@ -72,9 +71,12 @@ extern void pdf_ximage_init_image_info (ximage_info *info); extern void pdf_ximage_init_form_info (xform_info *info); extern void pdf_ximage_set_image (pdf_ximage *ximage, void *info, pdf_obj *resource); extern void pdf_ximage_set_form (pdf_ximage *ximage, void *info, pdf_obj *resource); +extern void pdf_ximage_set_page (pdf_ximage *ximage, long page_no, long page_count); +extern long pdf_ximage_get_page (pdf_ximage *I); /* from psimage.h */ extern void set_distiller_template (char *s); +extern char *get_distiller_template (void); extern int pdf_ximage_scale_image (int id, @@ -83,4 +85,6 @@ pdf_ximage_scale_image (int id, transform_info *p /* arg */ ); +/* from dvipdfmx.c */ +extern void pdf_ximage_disable_ebb (void); #endif /* _PDFXIMAGE_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/pngimage.c b/Build/source/texk/xdvipdfmx/src/pngimage.c index 9d680b73afd..0176411e514 100644 --- a/Build/source/texk/xdvipdfmx/src/pngimage.c +++ b/Build/source/texk/xdvipdfmx/src/pngimage.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/pngimage.c,v 1.24 2004/09/11 14:50:29 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/pngimage.c,v 1.25 2007/05/18 05:19:01 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -165,8 +165,8 @@ png_include_image (pdf_ximage *ximage, FILE *png_file) png_structp png_ptr; png_infop png_info_ptr; png_byte bpc, color_type; - png_uint_32 width, height, rowbytes; - + png_uint_32 width, height, rowbytes, xppm, yppm; + pdf_ximage_init_image_info(&info); stream = NULL; @@ -192,9 +192,8 @@ png_include_image (pdf_ximage *ximage, FILE *png_file) 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); - - info.xdpi = png_get_x_pixels_per_meter(png_ptr, png_info_ptr) * 0.0254; - info.ydpi = png_get_y_pixels_per_meter(png_ptr, png_info_ptr) * 0.0254; + xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr); + yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr); /* We do not need 16-bpc color. Ask libpng to convert down to 8-bpc. */ if (bpc > 8) { @@ -214,6 +213,10 @@ png_include_image (pdf_ximage *ximage, FILE *png_file) info.width = width; info.height = height; info.bits_per_component = bpc; + if (xppm > 0) + info.xdensity = 72.0 / 0.0254 / xppm; + if (yppm > 0) + info.ydensity = 72.0 / 0.0254 / yppm; stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte); read_image_data(png_ptr, png_info_ptr, stream_data_ptr, height, rowbytes); diff --git a/Build/source/texk/xdvipdfmx/src/pst_obj.c b/Build/source/texk/xdvipdfmx/src/pst_obj.c index 55d5773cdd9..dde44284cf6 100644 --- a/Build/source/texk/xdvipdfmx/src/pst_obj.c +++ b/Build/source/texk/xdvipdfmx/src/pst_obj.c @@ -555,9 +555,11 @@ parse_long (unsigned char **inbuf, unsigned char *inbufend, unsigned char base, } else { break; } - val = val * base + c; + if (val < (LONG_MAX - c) / base) { + val = val * base + c; + count++; + } cur++; - count++; } if (ndigits != NULL) diff --git a/Build/source/texk/xdvipdfmx/src/spc_color.c b/Build/source/texk/xdvipdfmx/src/spc_color.c index 27c318f8825..35880193012 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_color.c +++ b/Build/source/texk/xdvipdfmx/src/spc_color.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_color.c,v 1.5 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_color.c,v 1.6 2007/11/22 11:45:39 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -74,18 +74,14 @@ spc_color_at_end_document (void) static int spc_handler_color_push (struct spc_env *spe, struct spc_arg *args) { - int error = 0; + int error; pdf_color colorspec; - pdf_color_push(); /* save currentcolor */ - if (args->curptr < args->endptr) { - error = spc_util_read_colorspec(spe, &colorspec, args, 1); - if (!error) { - pdf_dev_setcolor(&colorspec, 0); - pdf_dev_setcolor(&colorspec, 1); - } + error = spc_util_read_colorspec(spe, &colorspec, args, 1); + if (!error) { + pdf_color_push(&colorspec, &colorspec); } - + return error; } @@ -97,9 +93,8 @@ spc_handler_color_pop (struct spc_env *spe, struct spc_arg *args) return 0; } -/* _FIXME_ ... I don't understand this well. - * Dvips's implementation is to clear color stack and then - * push color? +/* Invoked by the special command "color rgb .625 0 0". + * DVIPS clears the color stack, and then saves and sets the given color. */ static int spc_handler_color_default (struct spc_env *spe, struct spc_arg *args) @@ -109,10 +104,9 @@ spc_handler_color_default (struct spc_env *spe, struct spc_arg *args) error = spc_util_read_colorspec(spe, &colorspec, args, 1); if (!error) { - pdf_color_clear(); - pdf_dev_setcolor(&colorspec, 0); - pdf_dev_setcolor(&colorspec, 1); - pdf_color_push(); /* save currentcolor */ + pdf_color_set_default(&colorspec); + pdf_color_clear_stack(); /* the default color is saved on color_stack */ + pdf_color_push(&colorspec, &colorspec); } return error; diff --git a/Build/source/texk/xdvipdfmx/src/spc_dvips.c b/Build/source/texk/xdvipdfmx/src/spc_dvips.c index 39578065626..2eac7ebcbd1 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_dvips.c +++ b/Build/source/texk/xdvipdfmx/src/spc_dvips.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_dvips.c,v 1.9 2005/08/19 12:06:24 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_dvips.c,v 1.10 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -32,6 +32,9 @@ #include "dpxfile.h" +#include "dvi.h" +#include "dvicodes.h" + #include "pdfparse.h" #include "pdfdoc.h" @@ -45,8 +48,10 @@ #include "specials.h" #include "spc_util.h" +#include "mfileio.h" #include "spc_dvips.h" +#include "spc_xtx.h" static int block_pending = 0; @@ -54,6 +59,39 @@ static double pending_x = 0.0; static double pending_y = 0.0; static int position_set = 0; +static char** ps_headers = 0; +static int num_ps_headers = 0; + +static int +spc_handler_ps_header (struct spc_env *spe, struct spc_arg *args) +{ + char *ps_header, *pro; + + skip_white(&args->curptr, args->endptr); + if (args->curptr + 1 >= args->endptr || + args->curptr[0] != '=') { + spc_warn(spe, "No filename specified for PSfile special."); + return -1; + } + args->curptr++; + + pro = malloc(args->endptr - args->curptr + 1); + strncpy(pro, args->curptr, args->endptr - args->curptr); + pro[args->endptr - args->curptr] = 0; + ps_header = kpse_find_file(pro, kpse_tex_ps_header_format, 0); + if (!ps_header) { + spc_warn(spe, "PS header %s not found.", pro); + return -1; + } + free(pro); + + if (!(num_ps_headers & 0x0f)) + ps_headers = realloc(ps_headers, sizeof(char*) * (num_ps_headers + 16)); + ps_headers[num_ps_headers++] = ps_header; + args->curptr = args->endptr; + return 0; +} + static char * parse_filename (char **pp, char *endptr) { @@ -119,12 +157,12 @@ spc_handler_ps_file (struct spc_env *spe, struct spc_arg *args) } transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 1) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 1) < 0) { RELEASE(filename); return -1; } - form_id = pdf_ximage_findresource(filename, 0, 0); + form_id = pdf_ximage_findresource(filename, 1); if (form_id < 0) { spc_warn(spe, "Failed to read image file: %s", filename); RELEASE(filename); @@ -157,7 +195,7 @@ spc_handler_ps_plotfile (struct spc_env *spe, struct spc_arg *args) return -1; } - form_id = pdf_ximage_findresource(filename, 0, 0); + form_id = pdf_ximage_findresource(filename, 1); if (form_id < 0) { spc_warn(spe, "Could not open PS file: %s", filename); error = -1; @@ -243,6 +281,462 @@ spc_handler_ps_literal (struct spc_env *spe, struct spc_arg *args) return error; } +static char *global_defs = 0; +static char *page_defs = 0; +static char *temporary_defs = 0; +static char *distiller_template = 0; +static pdf_coord *put_stack; +static int put_stack_depth = -1; +static char *gs_in = 0; + +static int +spc_handler_ps_tricks_gdef (struct spc_env *spe, struct spc_arg *args) +{ + FILE* fp; + + fp = fopen(global_defs, "a"); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\n"); + fclose(fp); + + return 0; +} + +static int +spc_handler_ps_tricks_pdef (struct spc_env *spe, struct spc_arg *args) +{ + FILE* fp; + pdf_tmatrix M, T = { 1, 0, 0, 1, 0, 0 }; + pdf_coord pt; + + pdf_dev_currentmatrix(&M); + pdf_dev_get_fixed_point(&pt); + T.e = pt.x; + T.f = pt.y; + pdf_concatmatrix(&M, &T); + if (page_defs == 0) + page_defs = dpx_create_temp_file(); + fp = fopen(page_defs, "a"); + fprintf(fp, "gsave initmatrix [%f %f %f %f %f %f] concat %f %f moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user - pt.x, spe->y_user - pt.y); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\ngrestore\n"); + fclose(fp); + + return 0; +} + +static int +spc_handler_ps_tricks_tdef (struct spc_env *spe, struct spc_arg *args) +{ + FILE* fp; + if (!temporary_defs) + temporary_defs = dpx_create_temp_file(); + fp = fopen(temporary_defs, "w"); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\n"); + fclose(fp); + + return 0; +} + +static int calculate_PS (char *string, int length, double *res1, double *res2); + +static int +spc_handler_ps_tricks_bput (struct spc_env *spe, struct spc_arg *args, int must_def, int pre_def) +{ + char *PutBegin, *formula, *ncLabel; + int label = 0; + pdf_coord tr; + pdf_tmatrix M, T = { 1, 0, 0, 1, 0, 0 }; + + if (must_def != 0) { + ncLabel = strstr(args->curptr, "LPut"); + if (ncLabel != 0 && ncLabel < args->endptr - 3) + label = 1; + ncLabel = strstr(args->curptr, "HPutPos"); + if (ncLabel != 0 && ncLabel < args->endptr - 6) + label = 1; + } + + if (pre_def == 0) { + dpx_delete_temp_file(temporary_defs); + temporary_defs = 0; + } + + pdf_dev_currentmatrix(&M); + formula = malloc(args->endptr - args->curptr + 120); + if (label != 0) { + sprintf(formula, "[%f %f %f %f %f %f] concat %f %f moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user + get_origin(1), spe->y_user + get_origin(0)); + } else + sprintf(formula, "[%f %f %f %f %f %f] concat %f %f moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user, spe->y_user); + strncat(formula, args->curptr, args->endptr - args->curptr); + PutBegin = strstr(formula, "PutBegin"); + strcpy(PutBegin, "exch = ="); + *(PutBegin + 8) = 0; + if (calculate_PS(formula, strlen(formula), &tr.x, &tr.y) == 0) { + if (!(++put_stack_depth & 0x0f)) + put_stack = realloc(put_stack, (put_stack_depth + 16) * sizeof(pdf_coord)); + put_stack[put_stack_depth] = tr; + } + T.e = tr.x; T.f = tr.y; + + pdf_dev_concat(&T); + + if (must_def != 0) { + FILE* fp; + if (!temporary_defs) + temporary_defs = dpx_create_temp_file(); + fp = fopen(temporary_defs, "a"); + fprintf(fp, "gsave\n"); + if (label == 0) + fprintf(fp, "[%f %f %f %f %f %f] concat %f %f moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user, spe->y_user); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\ngrestore\n"); + fclose(fp); + } + + free(formula); + return 0; +} + +static int +spc_handler_ps_tricks_eput (struct spc_env *spe, struct spc_arg *args) +{ + pdf_coord tr = put_stack[put_stack_depth--]; + pdf_tmatrix M = { 1, 0, 0, 1, -tr.x, -tr.y }; + + pdf_dev_concat(&M); + + return 0; +} + +/* Rotation without gsave/grestore. */ +static double* RAngles = 0; +static int RAngleCount = -1; + +static int +spc_handler_ps_tricks_brotate (struct spc_env *spe, struct spc_arg *args) +{ + double value, RAngle = 0; + char *cmd, *RotBegin; + int i, l = args->endptr - args->curptr; + + static char *pre = "tx@Dict begin /RAngle { %f } def\n"; + static char *post = "= end"; + + if (!(++RAngleCount & 0x0f)) + RAngles = realloc(RAngles, (RAngleCount + 16) * sizeof(double)); + for (i = 0; i < RAngleCount; i++) + RAngle += RAngles[i]; + cmd = calloc(l + strlen(pre) + strlen(post) + 12, 1); + sprintf(cmd, pre, RAngle); + strncat(cmd, args->curptr, l); + RotBegin = strstr(cmd, "RotBegin"); + strcpy(RotBegin, post); + if (calculate_PS(cmd, strlen(cmd), &value, 0) != 0) + return -1; + RAngles[RAngleCount] = value; + + return spc_handler_xtx_do_rotate (spe->x_user, spe->y_user, value); +} + +static int +spc_handler_ps_tricks_erotate (struct spc_env *spe, struct spc_arg *args) +{ + double value = RAngles[RAngleCount--]; + + return spc_handler_xtx_do_rotate (spe->x_user, spe->y_user, (-1.0) * value); +} + +static int +check_next_obj(unsigned char * buffer) +{ + switch (buffer[0]) { + case XXX1: + if (buffer[1] < 5) + return 0; + buffer += 2; + break; + case XXX2: + buffer += 3; + break; + case XXX3: + buffer += 4; + break; + case XXX4: + buffer += 5; + break; + default: + return 0; + } + + if (strncmp(buffer, "pst:", 4)) + return 0; + return 1; +} + +static int +spc_handler_ps_tricks_parse_path (struct spc_env *spe, struct spc_arg *args, + int flag) +{ + FILE* fp; + int k; + pdf_tmatrix M; + char *distiller_template = get_distiller_template(); + char *gs_out; + char *clip; + int error; + + if (!distiller_template) + distiller_template = get_distiller_template(); + + pdf_dev_currentmatrix(&M); + if (!gs_in) { + gs_in = dpx_create_temp_file(); + if (!gs_in) { + WARN("Failed to create temporary input file for PSTricks image conversion."); + return -1; + } + fp = fopen(gs_in, "w"); + for (k = 0; k < num_ps_headers; k++) + fprintf(fp, "(%s) run\n", ps_headers[k]); + fprintf(fp, "[%f %f %f %f %f %f] concat %f %f translate 0 0 moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user, spe->y_user); + fprintf(fp, "(%s) run\n", global_defs); + if (page_defs != 0) + fprintf(fp, "(%s) run\n", page_defs); + +#if 0 + fprintf(fp, "/clip {stroke} def\n"); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); +#else + clip = strstr(args->curptr, " clip"); + if (clip == 0 || clip > args->endptr - 5) { + fprintf(fp, "tx@TextPathDict begin /stroke {} def\n"); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\nend\n"); + fclose(fp); + return 0; + } else { + fwrite(args->curptr, 1, clip - args->curptr, fp); + fprintf(fp, " stroke "); + skip_white(&clip, args->endptr); + parse_ident(&clip, args->endptr); + fwrite(clip, 1, args->endptr - clip, fp); + } +#endif + } else { + fp = fopen(gs_in, "a"); + fprintf(fp, "flattenpath stroke\n"); + } + fclose(fp); + + gs_out = dpx_create_temp_file(); + if (!gs_out) { + WARN("Failed to create temporary output file for PSTricks image conversion."); + RELEASE(gs_in); + gs_in = 0; + return -1; + } + + error = dpx_file_apply_filter(distiller_template, gs_in, gs_out); + if (error) { + WARN("Image format conversion for PSTricks failed."); + RELEASE(gs_in); + gs_in = 0; + return error; + } + + fp = fopen(gs_out, "r"); + if (pdf_copy_clip(fp, 1, 0, 0) != 0) { + spc_warn(spe, "Failed to parse the clipping path."); + RELEASE(gs_in); + gs_in = 0; + RELEASE(gs_out); + return -1; + } + fclose(fp); + + dpx_delete_temp_file(gs_out); + dpx_delete_temp_file(gs_in); + gs_in = 0; + + return 0; +} + +static int +spc_handler_ps_tricks_render (struct spc_env *spe, struct spc_arg *args) +{ + FILE* fp; + int k; + pdf_tmatrix M; + + if (!distiller_template) + distiller_template = get_distiller_template(); + + pdf_dev_currentmatrix(&M); + if (!gs_in) { + gs_in = dpx_create_temp_file(); + if (!gs_in) { + WARN("Failed to create temporary input file for PSTricks image conversion."); + return -1; + } + fp = fopen(gs_in, "w"); + for (k = 0; k < num_ps_headers; k++) + fprintf(fp, "(%s) run\n", ps_headers[k]); + fprintf(fp, "[%f %f %f %f %f %f] concat %f %f translate 0 0 moveto\n", M.a, M.b, M.c, M.d, M.e, M.f, spe->x_user, spe->y_user); + fprintf(fp, "(%s) run\n", global_defs); + if (page_defs != 0) + fprintf(fp, "(%s) run\n", page_defs); + } else + fp = fopen(gs_in, "a"); + + fprintf(fp, "\nsave\n"); + fwrite(args->curptr, 1, args->endptr - args->curptr, fp); + fprintf(fp, "\ncount 1 sub {pop} repeat restore\n"); + + if (check_next_obj(args->endptr)) { + fclose(fp); + } else { + char *distiller_template = get_distiller_template(); + char *gs_out; + int error, form_id; + transform_info p; + transform_info_clear(&p); + pdf_invertmatrix(&M); + p.matrix = M; + + fclose(fp); + + gs_out = dpx_create_temp_file(); + if (!gs_out) { + WARN("Failed to create temporary output file for PSTricks image conversion."); + RELEASE(gs_in); + gs_in = 0; + return -1; + } + + error = dpx_file_apply_filter(distiller_template, gs_in, gs_out); + if (error) { + WARN("Image format conversion for PSTricks failed."); + RELEASE(gs_in); + gs_in = 0; + return error; + } + + form_id = pdf_ximage_findresource(gs_out, 1/*, 0*/); + if (form_id < 0) { + spc_warn(spe, "Failed to read converted PSTricks image file."); + RELEASE(gs_in); + gs_in = 0; + RELEASE(gs_out); + return -1; + } + pdf_dev_put_image(form_id, &p, 0, 0); + + dpx_delete_temp_file(gs_out); + dpx_delete_temp_file(gs_in); + gs_in = 0; + } + + return 0; +} + +typedef enum { + render = 1 << 0, + global_def = 1 << 1, + page_def = 1 << 2, + new_temp = 1 << 3, + add_temp = 1 << 4, + begin_put = 1 << 5, + end_put = 1 << 6, + begin_rotate = 1 << 7, + end_rotate = 1 << 8, + parse = 1 << 9, + req_ref = 1 << 10 +} Operation; + +/* ToDo: all the substring search must be centralized so that * + * keys can be read from external configuration. */ +struct pstricks_key_ { + char * key; + Operation exec; +} pstricks_key[] = { + /* The first 5 are hard-coded here. */ + {"LPut", add_temp | req_ref}, + {"HPutPos", add_temp | req_ref}, + {"PutBegin", begin_put}, + {"RotBegin", begin_rotate}, + {"clip", parse}, + /* The rest can be read from an external source. */ + {"NewNode", page_def | req_ref}, + {"InitNC", render | new_temp}, + {"/Glbx", add_temp}, + {"NewtonSolving", add_temp}, + {"PutEnd", end_put}, + {"RotEnd", end_rotate}, + {"mtrxc", parse}, + {"stroke", render}, + {"fill", render}, + {"Fill", render}, + {" Glbx", req_ref}, + {"TextPathShow", parse}, + {"/rotAngle", page_def}, + {"NAngle", req_ref} +}; + +static int +spc_handler_ps_trickscmd (struct spc_env *spe, struct spc_arg *args) +{ + char *test_string; + int k, error = 0, f_exec = 0; + + /* Hack time! */ + /* The problem is that while any macros in pstricks.tex + * can be overridden by the codes in pstricks.con, you cannot + * modify the pst@Verb specials generated by other PSTricks + * packages. So pstricks generate specials won't signal what + * to expect for you. + */ + test_string = malloc(args->endptr - args->curptr + 1); + strncpy(test_string, args->curptr, args->endptr - args->curptr); + test_string[args->endptr - args->curptr] = 0; + for (k = 0; k < sizeof(pstricks_key) / sizeof(pstricks_key[0]); k++) { + if (strstr(test_string, pstricks_key[k].key) != 0) + f_exec |= pstricks_key[k].exec; + } + free(test_string); + + if (f_exec & new_temp) + error |= spc_handler_ps_tricks_tdef(spe, args); + if (f_exec & render) + error |= spc_handler_ps_tricks_render(spe, args); + if (f_exec & parse) + error |= spc_handler_ps_tricks_parse_path(spe, args, f_exec); + if (f_exec & begin_put) + error |= spc_handler_ps_tricks_bput(spe, args, (f_exec & add_temp), (f_exec & req_ref)); + if (f_exec & end_put) + error |= spc_handler_ps_tricks_eput(spe, args); + if (f_exec & begin_rotate) + error |= spc_handler_ps_tricks_brotate(spe, args); + if (f_exec & end_rotate) + error |= spc_handler_ps_tricks_erotate(spe, args); + if (f_exec & page_def) + error |= spc_handler_ps_tricks_pdef (spe, args); + if (f_exec == 0) + error |= spc_handler_ps_tricks_pdef (spe, args); + + args->curptr = args->endptr; + return error; +} + +static int +spc_handler_ps_tricksobj (struct spc_env *spe, struct spc_arg *args) +{ + int error = spc_handler_ps_tricks_render(spe, args); + args->curptr = args->endptr; + return error; +} + static int spc_handler_ps_default (struct spc_env *spe, struct spc_arg *args) { @@ -283,18 +777,30 @@ spc_handler_ps_default (struct spc_env *spe, struct spc_arg *args) } static struct spc_handler dvips_handlers[] = { + {"header", spc_handler_ps_header}, {"PSfile", spc_handler_ps_file}, {"psfile", spc_handler_ps_file}, {"ps: plotfile", spc_handler_ps_plotfile}, /* FIXME */ {"PS: plotfile", spc_handler_ps_plotfile}, /* FIXME */ {"PS:", spc_handler_ps_literal}, {"ps:", spc_handler_ps_literal}, + {"PST:", spc_handler_ps_trickscmd}, + {"pst:", spc_handler_ps_tricksobj}, {"\" ", spc_handler_ps_default} }; int spc_dvips_at_begin_page (void) { + FILE* fp; + + if (page_defs) { + dpx_delete_temp_file(page_defs); + page_defs = 0; + } + + put_stack_depth = -1; + return 0; } @@ -302,18 +808,31 @@ int spc_dvips_at_end_page (void) { mps_eop_cleanup(); + if (!temporary_defs) { + dpx_delete_temp_file(temporary_defs); + temporary_defs = 0; + } return 0; } int spc_dvips_at_begin_document (void) { + FILE* fp; + + /* This, together with \pscharpath support code, must be moved to xtex.pro header. */ + global_defs = dpx_create_temp_file(); + fp = fopen(global_defs, "w"); + fprintf(fp, "tx@Dict begin /STV {} def end\n"); + fclose(fp); return 0; } int spc_dvips_at_end_document (void) { + dpx_delete_temp_file(global_defs); + dpx_delete_temp_file(page_defs); return 0; } @@ -376,8 +895,8 @@ spc_dvips_setup_handler (struct spc_handler *handle, for (i = 0; i < sizeof(dvips_handlers) / sizeof(struct spc_handler); i++) { - if (keylen == strlen(dvips_handlers[i].key) && - !strncmp(key, dvips_handlers[i].key, keylen)) { + if (keylen <= strlen(dvips_handlers[i].key) && + !strncmp(key, dvips_handlers[i].key, strlen(dvips_handlers[i].key))) { skip_white(&args->curptr, args->endptr); @@ -393,3 +912,50 @@ spc_dvips_setup_handler (struct spc_handler *handle, return -1; } +#ifdef __EMX__ +#define GS_CALCULATOR "gsos2 -q -dNOPAUSE -dBATCH -sDEVICE=nullpage -f " +#else +#define GS_CALCULATOR "gs -q -dNOPAUSE -dBATCH -sDEVICE=nullpage -f " +#endif + +static +int calculate_PS (char *string, int length, double *res1, double *res2) { + char *formula, *cmd; + FILE *fp, *coord; + int k; + + if (res1 == 0 && res2 == 0) + return -1; + formula = dpx_create_temp_file(); + fp = fopen(formula, "w"); + for (k = 0; k < num_ps_headers; k++) + fprintf(fp, "(%s) run\n", ps_headers[k]); + fprintf(fp, "0 0 moveto\n"); + fprintf(fp, "(%s) run\n", global_defs); + if (page_defs != 0) + fprintf(fp, "(%s) run\n", page_defs); + if (temporary_defs) + fprintf(fp, "(%s) run\n", temporary_defs); + fwrite(string, 1, length, fp); + fclose(fp); + k = strlen(GS_CALCULATOR) + strlen(formula) + 2; + cmd = malloc(k); + strcpy(cmd, GS_CALCULATOR); + strcat(cmd, " "); + strcat(cmd, formula); + + coord = popen(cmd, "r"); + if (coord) { + if (res1 == 0) + fscanf(coord, " %lf ", res2); + else if (res2 == 0) + fscanf(coord, " %lf ", res1); + else + fscanf(coord, " %lf %lf ", res1, res2); + } else + return -1; + + pclose(coord); + dpx_delete_temp_file(formula); + return 0; +} diff --git a/Build/source/texk/xdvipdfmx/src/spc_html.c b/Build/source/texk/xdvipdfmx/src/spc_html.c index 956d1a548be..322c53475ce 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_html.c +++ b/Build/source/texk/xdvipdfmx/src/spc_html.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_html.c,v 1.5 2005/08/14 15:50:36 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_html.c,v 1.6 2007/01/19 11:00:48 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -635,7 +635,7 @@ spc_html__img_empty (struct spc_env *spe, pdf_obj *attr, struct spc_html_ *sd) return error; } - id = pdf_ximage_findresource(pdf_string_value(src), 0, 0); + id = pdf_ximage_findresource(pdf_string_value(src), 0/*, 0*/); if (id < 0) { spc_warn(spe, "Could not find/load image: %s", pdf_string_value(src)); error = -1; diff --git a/Build/source/texk/xdvipdfmx/src/spc_misc.c b/Build/source/texk/xdvipdfmx/src/spc_misc.c index a4b908eaac1..51e0ceee7d2 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_misc.c +++ b/Build/source/texk/xdvipdfmx/src/spc_misc.c @@ -134,7 +134,7 @@ spc_handler_postscriptbox (struct spc_env *spe, struct spc_arg *ap) } MFCLOSE(fp); - form_id = pdf_ximage_findresource(filename, 0, 0); + form_id = pdf_ximage_findresource(filename, 0/*, 0*/); if (form_id < 0) { spc_warn(spe, "Failed to load image file: %s", filename); return -1; diff --git a/Build/source/texk/xdvipdfmx/src/spc_pdfm.c b/Build/source/texk/xdvipdfmx/src/spc_pdfm.c index 45357cccb7f..6d914149d86 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_pdfm.c +++ b/Build/source/texk/xdvipdfmx/src/spc_pdfm.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_pdfm.c,v 1.24 2006/12/11 12:46:03 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_pdfm.c,v 1.30 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -331,7 +331,6 @@ spc_handler_pdfm_put (struct spc_env *spe, struct spc_arg *ap) } skip_white(&ap->curptr, ap->endptr); - obj2 = parse_pdf_object(&ap->curptr, ap->endptr); if (!obj2) { spc_warn(spe, "Missing (an) object(s) to put into \"%s\"!", ident); @@ -392,7 +391,7 @@ spc_handler_pdfm_put (struct spc_env *spe, struct spc_arg *ap) break; } pdf_release_obj(obj2); - + RELEASE(ident); return error; } @@ -526,6 +525,7 @@ maybe_reencode_utf8(pdf_obj *instring) } pdf_set_string(instring, wbuf, op - wbuf); + return 0; } @@ -640,7 +640,7 @@ spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) } transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { if (ident) RELEASE(ident); return -1; @@ -774,9 +774,9 @@ spc_handler_pdfm_bcolor (struct spc_env *spe, struct spc_arg *ap) if (error) spc_warn(spe, "Invalid color specification?"); else { - pdf_color_push(); /* save currentcolor */ - pdf_dev_setcolor(&fc, 1); - pdf_dev_setcolor(&sc, 0); + pdf_color_push(&sc, &fc); /* save currentcolor */ + pdf_dev_set_strokingcolor(&sc); + pdf_dev_set_nonstrokingcolor(&fc); } return error; @@ -802,8 +802,8 @@ spc_handler_pdfm_scolor (struct spc_env *spe, struct spc_arg *ap) spc_warn(spe, "Invalid color specification?"); else { pdf_color_set_default(&fc); /* ????? */ - pdf_dev_setcolor(&fc, 1); - pdf_dev_setcolor(&sc, 0); + pdf_dev_set_strokingcolor(&sc); + pdf_dev_set_nonstrokingcolor(&fc); } return error; @@ -824,7 +824,7 @@ spc_handler_pdfm_btrans (struct spc_env *spe, struct spc_arg *args) transform_info ti; transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { return -1; } @@ -862,11 +862,29 @@ spc_handler_pdfm_outline (struct spc_env *spe, struct spc_arg *args) { struct spc_pdf_ *sd = &_pdf_stat; pdf_obj *item_dict, *tmp; - int level; + int level, is_open = -1; int current_depth; skip_white(&args->curptr, args->endptr); + /* + * pdf:outline is extended to support open/close feature + * + * pdf:outline 1 ... (as DVIPDFM) + * pdf:outline [] 1 ... (open bookmark) + * pdf:outline [-] 1 ... (closed bookmark) + */ + if (args->curptr+3 < args->endptr && *args->curptr == '[') { + args->curptr++; + if (*args->curptr == '-') { + args->curptr++; + } else { + is_open = 1; + } + args->curptr++; + } + skip_white(&args->curptr, args->endptr); + tmp = parse_pdf_object(&args->curptr, args->endptr); if (!tmp) { spc_warn(spe, "Missing number for outline item depth."); @@ -912,7 +930,7 @@ spc_handler_pdfm_outline (struct spc_env *spe, struct spc_arg *args) pdf_doc_bookmarks_down(); } - pdf_doc_bookmarks_add(item_dict, -1); /* Use global setting for open/close */ + pdf_doc_bookmarks_add(item_dict, is_open); return 0; } @@ -940,8 +958,8 @@ spc_handler_pdfm_article (struct spc_env *spe, struct spc_arg *args) info_dict = parse_pdf_dict(&args->curptr, args->endptr); #endif /* ENABLE_TOUNICODE */ if (!info_dict) { - RELEASE(ident); spc_warn(spe, "Ignoring article with invalid info dictionary."); + RELEASE(ident); return -1; } @@ -981,7 +999,7 @@ spc_handler_pdfm_bead (struct spc_env *spe, struct spc_arg *args) /* If okay so far, try to get a bounding box */ transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { RELEASE(article_name); return -1; } @@ -1035,6 +1053,7 @@ spc_handler_pdfm_bead (struct spc_env *spe, struct spc_arg *args) page_no = pdf_doc_current_page_number(); pdf_doc_add_bead(article_name, NULL, page_no, &rect); + RELEASE(article_name); return 0; } @@ -1046,6 +1065,7 @@ spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) char *ident = NULL; pdf_obj *fspec; transform_info ti; + long page_no; skip_white(&args->curptr, args->endptr); if (args->curptr[0] == '@') { @@ -1059,7 +1079,8 @@ spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) } transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + page_no = 1; + if (spc_util_read_dimtrns(spe, &ti, args, &page_no, 0) < 0) { if (ident) RELEASE(ident); return -1; @@ -1075,10 +1096,12 @@ spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) } else if (!PDF_OBJ_STRINGTYPE(fspec)) { spc_warn(spe, "Missing filename string for pdf:image."); pdf_release_obj(fspec); + if (ident) + RELEASE(ident); return -1; } - xobj_id = pdf_ximage_findresource(pdf_string_value(fspec), 0, 0); + xobj_id = pdf_ximage_findresource(pdf_string_value(fspec), page_no); if (xobj_id < 0) { spc_warn(spe, "Could not find image resource..."); pdf_release_obj(fspec); @@ -1311,8 +1334,8 @@ spc_handler_pdfm_object (struct spc_env *spe, struct spc_arg *args) object = parse_pdf_object(&args->curptr, args->endptr); if (!object) { - RELEASE(ident); spc_warn(spe, "Could not find an object definition for \"%s\".", ident); + RELEASE(ident); return -1; } else { spc_push_object(ident, object); @@ -1451,16 +1474,16 @@ spc_handler_pdfm_fstream (struct spc_env *spe, struct spc_arg *args) pdf_release_obj(tmp); if (!fullname) { spc_warn(spe, "Could not find file."); - RELEASE(ident); pdf_release_obj(fstream); + RELEASE(ident); return -1; } fp = MFOPEN(fullname, FOPEN_RBIN_MODE); if (!fp) { spc_warn(spe, "Could not open file: %s", fullname); - RELEASE(ident); pdf_release_obj(fstream); + RELEASE(ident); return -1; } @@ -1488,8 +1511,8 @@ spc_handler_pdfm_fstream (struct spc_env *spe, struct spc_arg *args) tmp = parse_pdf_dict(&args->curptr, args->endptr); if (!tmp) { spc_warn(spe, "Parsing dictionary failed."); - RELEASE(ident); pdf_release_obj(fstream); + RELEASE(ident); return -1; } if (pdf_lookup_dict(tmp, "Length")) { @@ -1541,7 +1564,7 @@ spc_handler_pdfm_bform (struct spc_env *spe, struct spc_arg *args) } transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { RELEASE(ident); return -1; } @@ -1654,7 +1677,7 @@ spc_handler_pdfm_uxobj (struct spc_env *spe, struct spc_arg *args) transform_info_clear(&ti); if (args->curptr < args->endptr) { - if (spc_util_read_dimtrns(spe, &ti, args, 0) < 0) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { RELEASE(ident); return -1; } @@ -1666,7 +1689,7 @@ spc_handler_pdfm_uxobj (struct spc_env *spe, struct spc_arg *args) */ xobj_id = findresource(sd, ident); if (xobj_id < 0) { - xobj_id = pdf_ximage_findresource(ident, 0, 0); + xobj_id = pdf_ximage_findresource(ident, 0); if (xobj_id < 0) { spc_warn(spe, "Specified (image) object doesn't exist: %s", ident); RELEASE(ident); @@ -1814,6 +1837,7 @@ spc_handler_pdfm_mapfile (struct spc_env *spe, struct spc_arg *args) } else { error = pdf_load_fontmap_file(mapfile, mode); } + RELEASE(mapfile); return error; } @@ -1825,7 +1849,6 @@ spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) { struct spc_pdf_ *sd = &_pdf_stat; char *cmap_name; - int error = 0; /* First clear */ sd->cd.cmap_id = -1; @@ -1845,19 +1868,20 @@ spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) cmap_name = parse_ident(&args->curptr, args->endptr); if (!cmap_name) { spc_warn(spe, "Missing ToUnicode mapping name..."); - return -1; + return -1; } sd->cd.cmap_id = CMap_cache_find(cmap_name); if (sd->cd.cmap_id < 0) { spc_warn(spe, "Failed to load ToUnicode mapping: %s", cmap_name); - error = -1; + RELEASE(cmap_name); + return -1; } /* Shift-JIS like encoding may contain backslash in 2nd byte. * WARNING: This will add nasty extension to PDF parser. */ - if (!error && sd->cd.cmap_id >= 0) { + if (sd->cd.cmap_id >= 0) { if (strstr(cmap_name, "RKSJ") || strstr(cmap_name, "B5") || strstr(cmap_name, "GBK") || @@ -1865,8 +1889,7 @@ spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) sd->cd.unescape_backslash = 1; } RELEASE(cmap_name); - - return error; + return 0; } #endif /* ENABLE_TOUNICODE */ diff --git a/Build/source/texk/xdvipdfmx/src/spc_util.c b/Build/source/texk/xdvipdfmx/src/spc_util.c index bfe10f88720..fd143e8b0a7 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_util.c +++ b/Build/source/texk/xdvipdfmx/src/spc_util.c @@ -1,8 +1,8 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_util.c,v 1.7 2005/08/12 16:27:52 chofchof Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_util.c,v 1.10 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2007 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team Copyright (C) 1998, 1999 by Mark A. Wicks @@ -238,6 +238,8 @@ spc_util_read_colorspec (struct spc_env *spe, pdf_color *colorspec, struct spc_a else error = spc_read_color_pdf(spe, colorspec, ap); + skip_blank(&ap->curptr, ap->endptr); + return error; } @@ -267,26 +269,39 @@ spc_util_read_length (struct spc_env *spe, double *vp /* ret. */, struct spc_arg v = atof(q); RELEASE(q); + skip_white(&ap->curptr, ap->endptr); q = parse_c_ident(&ap->curptr, ap->endptr); if (q) { - if (strlen(q) > strlen("true") && + char *qq = q; + if (strlen(q) >= strlen("true") && !memcmp(q, "true", strlen("true"))) { u /= spe->mag != 0.0 ? spe->mag : 1.0; /* inverse magnify */ q += strlen("true"); } - for (k = 0; ukeys[k] && strcmp(ukeys[k], q); k++); - switch (k) { - case K_UNIT__PT: u *= 72.0 / 72.27; break; - case K_UNIT__IN: u *= 72.0; break; - case K_UNIT__CM: u *= 72.0 / 2.54 ; break; - case K_UNIT__MM: u *= 72.0 / 25.4 ; break; - case K_UNIT__BP: u *= 1.0 ; break; - default: - spc_warn(spe, "Unknown unit of measure: %s", q); - error = -1; - break; + if (strlen(q) == 0) { + RELEASE(qq); + skip_white(&ap->curptr, ap->endptr); + qq = q = parse_c_ident(&ap->curptr, ap->endptr); + } + if (q) { + for (k = 0; ukeys[k] && strcmp(ukeys[k], q); k++); + switch (k) { + case K_UNIT__PT: u *= 72.0 / 72.27; break; + case K_UNIT__IN: u *= 72.0; break; + case K_UNIT__CM: u *= 72.0 / 2.54 ; break; + case K_UNIT__MM: u *= 72.0 / 25.4 ; break; + case K_UNIT__BP: u *= 1.0 ; break; + default: + spc_warn(spe, "Unknown unit of measure: %s", q); + error = -1; + break; + } + RELEASE(qq); + } + else { + spc_warn(spe, "Missing unit of measure after \"true\""); + error = -1; } - RELEASE(q); } *vp = v * u; @@ -396,9 +411,8 @@ spc_read_dimtrns_dvips (struct spc_env *spe, transform_info *t, struct spc_arg * spc_warn(spe, "Missing value for dimension/transformation: %s", kp); error = -1; } - + RELEASE(kp); if (!vp || error) { - RELEASE(kp); break; } @@ -461,7 +475,7 @@ spc_read_dimtrns_dvips (struct spc_env *spe, transform_info *t, struct spc_arg * static int -spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *ap) +spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *ap, long *page_no) { int has_scale, has_xscale, has_yscale, has_rotate, has_matrix; const char *_dtkeys[] = { @@ -478,6 +492,8 @@ spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *a "bbox", /* See "Dvipdfmx User's Manual", p.5 */ #define K_TRN__MATRIX 8 "matrix", +#define K_TRN__PAGE 9 + "page", NULL }; double xscale, yscale, rotate; @@ -577,6 +593,15 @@ spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *a } } break; + case K_TRN__PAGE: + { + double page; + if (page_no && spc_util_read_numbers(&page, 1, spe, ap) == 1) + *page_no = (long) page; + else + error = -1; + } + break; default: error = -1; break; @@ -615,14 +640,15 @@ spc_read_dimtrns_pdfm (struct spc_env *spe, transform_info *p, struct spc_arg *a } int -spc_util_read_dimtrns (struct spc_env *spe, transform_info *ti, struct spc_arg *args, int syntax) +spc_util_read_dimtrns (struct spc_env *spe, transform_info *ti, struct spc_arg *args, long *page_no, int syntax) { ASSERT(ti && spe && args); if (syntax) { + ASSERT(!page_no); return spc_read_dimtrns_dvips(spe, ti, args); } else { - return spc_read_dimtrns_pdfm (spe, ti, args); + return spc_read_dimtrns_pdfm (spe, ti, args, page_no); } return -1; @@ -636,6 +662,7 @@ spc_util_read_dimtrns (struct spc_env *spe, transform_info *ti, struct spc_arg * #ifdef cmyk #undef cmyk #endif +#define gray(g) {1, {g}} #define rgb8(r,g,b) {3, {((r)/255.0), ((g)/255.0), ((b)/255.0), 0.0}} #define cmyk(c,m,y,k) {4, {(c), (m), (y), (k)}} @@ -709,9 +736,13 @@ static struct colordef_ {"Sepia", cmyk(0.00, 0.83, 1.00, 0.70)}, {"Brown", cmyk(0.00, 0.81, 1.00, 0.60)}, {"Tan", cmyk(0.14, 0.42, 0.56, 0.00)}, - {"Gray", cmyk(0.00, 0.00, 0.00, 0.50)}, - {"Black", cmyk(0.00, 0.00, 0.00, 1.00)}, - {"White", cmyk(0.00, 0.00, 0.00, 0.00)}, + /* Adobe Reader 7 and 8 had problem when gray and cmyk black colors + * are mixed. No problem with Previewer.app. + * It happens when \usepackage[dvipdfm]{graphicx} and then called + * \usepackage{color} without dvipdfm option. */ + {"Gray", gray(0.5)}, + {"Black", gray(0.0)}, + {"White", gray(1.0)}, {NULL} }; diff --git a/Build/source/texk/xdvipdfmx/src/spc_util.h b/Build/source/texk/xdvipdfmx/src/spc_util.h index 1c0bbc01119..a10becda1fa 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_util.h +++ b/Build/source/texk/xdvipdfmx/src/spc_util.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/spc_util.h,v 1.4 2005/07/30 11:44:18 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/spc_util.h,v 1.5 2008/02/13 20:22:21 matthias Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -36,7 +36,7 @@ * This is for reading *single* color specification. */ extern int spc_util_read_colorspec (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *args, int syntax); -extern int spc_util_read_dimtrns (struct spc_env *spe, transform_info *dimtrns, struct spc_arg *args, int syntax); +extern int spc_util_read_dimtrns (struct spc_env *spe, transform_info *dimtrns, struct spc_arg *args, long *page, int syntax); extern int spc_util_read_length (struct spc_env *spe, double *length, struct spc_arg *ap); extern int spc_util_read_numbers (double *values, int num_values, struct spc_env *spe, struct spc_arg *args); diff --git a/Build/source/texk/xdvipdfmx/src/spc_xtx.c b/Build/source/texk/xdvipdfmx/src/spc_xtx.c index 57b7ae72e72..7369b6978ae 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_xtx.c +++ b/Build/source/texk/xdvipdfmx/src/spc_xtx.c @@ -74,6 +74,7 @@ spc_xtx_at_end_document (void) int spc_xtx_at_begin_page (void) { + /*pdf_dev_set_fixed_point(0, 0);*/ return 0; } @@ -84,49 +85,105 @@ spc_xtx_at_end_page (void) } static int -spc_handler_xtx_scale (struct spc_env *spe, struct spc_arg *args) +spc_handler_xtx_do_scale (double x_user, double y_user, double valueX, double valueY) { pdf_tmatrix M = { 0, 0, 0, 0, 0, 0 }; - double values[2]; + pdf_coord pt; - if (spc_util_read_numbers(&values[0], 2, spe, args) < 2) { - return -1; - } /* Create transformation matrix */ - M.a = values[0]; - M.d = values[1]; - M.e = ((1.0 - M.a) * spe->x_user - M.c * spe->y_user); - M.f = ((1.0 - M.d) * spe->y_user - M.b * spe->x_user); + M.a = valueX; + M.d = valueY; + M.e = ((1.0 - M.a) * x_user - M.c * y_user); + M.f = ((1.0 - M.d) * y_user - M.b * x_user); pdf_dev_concat(&M); + pdf_dev_get_fixed_point(&pt); + pdf_dev_set_fixed_point(x_user - pt.x, y_user - pt.y); return 0; } +static int +spc_handler_xtx_scale (struct spc_env *spe, struct spc_arg *args) +{ + double values[2]; + + if (spc_util_read_numbers(&values[0], 2, spe, args) < 2) { + return -1; + } + args->curptr = args->endptr; + + return spc_handler_xtx_do_scale(spe->x_user, spe->y_user, values[0], values[1]); +} + +/* Scaling without gsave/grestore. */ +static pdf_coord *scaleFactors = 0; +static int scaleFactorCount = -1; static int -spc_handler_xtx_rotate (struct spc_env *spe, struct spc_arg *args) +spc_handler_xtx_bscale (struct spc_env *spe, struct spc_arg *args) { - pdf_tmatrix M = { 0, 0, 0, 0, 0, 0 }; - double value; + double values[2]; - if (spc_util_read_numbers(&value, 1, spe, args) < 1) { + if (!(++scaleFactorCount & 0x0f)) + scaleFactors = realloc(scaleFactors, (scaleFactorCount + 16) * sizeof(pdf_coord)); + if (spc_util_read_numbers(&values[0], 2, spe, args) < 2) { return -1; } + if (fabs(values[0]) < 1.e-7 || fabs(values[1]) < 1.e-7) { + return -1; + } + scaleFactors[scaleFactorCount].x = 1 / values[0]; + scaleFactors[scaleFactorCount].y = 1 / values[1]; + args->curptr = args->endptr; + + return spc_handler_xtx_do_scale (spe->x_user, spe->y_user, values[0], values[1]); +} + +static int +spc_handler_xtx_escale (struct spc_env *spe, struct spc_arg *args) +{ + pdf_coord factor = scaleFactors[scaleFactorCount--]; + + args->curptr = args->endptr; + + return spc_handler_xtx_do_scale (spe->x_user, spe->y_user, factor.x, factor.y); +} + +int +spc_handler_xtx_do_rotate (double x_user, double y_user, double value) +{ + pdf_tmatrix M = { 0, 0, 0, 0, 0, 0 }; + pdf_coord pt; /* Create transformation matrix */ M.a = cos(value * M_PI / 180); M.b = sin(value * M_PI / 180); M.c = -M.b; M.d = M.a; - M.e = ((1.0 - M.a) * spe->x_user - M.c * spe->y_user); - M.f = ((1.0 - M.d) * spe->y_user - M.b * spe->x_user); + M.e = ((1.0 - M.a) * x_user - M.c * y_user); + M.f = ((1.0 - M.d) * y_user - M.b * x_user); pdf_dev_concat(&M); + pdf_dev_get_fixed_point(&pt); + pdf_dev_set_fixed_point(x_user - pt.x, y_user - pt.y); return 0; } +static int +spc_handler_xtx_rotate (struct spc_env *spe, struct spc_arg *args) +{ + double value; + + if (spc_util_read_numbers(&value, 1, spe, args) < 1) { + return -1; + } + args->curptr = args->endptr; + + return spc_handler_xtx_do_rotate (spe->x_user, spe->y_user, value); +} + static int spc_handler_xtx_gsave (struct spc_env *spe, struct spc_arg *args) { @@ -275,6 +332,61 @@ spc_handler_xtx_fontmapfile (struct spc_env *spe, struct spc_arg *args) return error; } +static char overlay_name[256]; + +static int +spc_handler_xtx_initoverlay (struct spc_env *spe, struct spc_arg *args) +{ + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return -1; + strncpy(overlay_name, args->curptr, args->endptr - args->curptr); + overlay_name[args->endptr - args->curptr] = 0; + + args->curptr = args->endptr; + return 0; +} + +static int +spc_handler_xtx_clipoverlay (struct spc_env *spe, struct spc_arg *args) +{ + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return -1; + pdf_dev_grestore(); + pdf_dev_gsave(); + if (strncmp(overlay_name, args->curptr, strlen(overlay_name)) != 0 + && strncmp("all", args->curptr, strlen("all")) != 0) + pdf_doc_add_page_content(" 0 0 m W n", 10); + + args->curptr = args->endptr; + return 0; +} + +static int +spc_handler_xtx_renderingmode (struct spc_env *spe, struct spc_arg *args) +{ + double value; + + if (spc_util_read_numbers(&value, 1, spe, args) < 1) { + return -1; + } + if ((int) value < 0 || (int) value > 7) { + spc_warn(spe, "Invalid text rendering mode %d.\n", (int) value); + return -1; + } + sprintf(work_buffer, " %d Tr", (int) value); + pdf_doc_add_page_content(work_buffer, strlen(work_buffer)); + skip_white(&args->curptr, args->endptr); + if (args->curptr < args->endptr) { + pdf_doc_add_page_content(" ", 1); + pdf_doc_add_page_content(args->curptr, args->endptr - args->curptr); + } + + args->curptr = args->endptr; + return 0; +} + static int spc_handler_xtx_unsupportedcolor (struct spc_env *spe, struct spc_arg *args) { @@ -312,6 +424,8 @@ static struct spc_handler xtx_handlers[] = { {"grestore", spc_handler_xtx_grestore}, {"scale", spc_handler_xtx_scale}, + {"bscale", spc_handler_xtx_bscale}, + {"escale", spc_handler_xtx_escale}, {"rotate", spc_handler_xtx_rotate}, {"fontmapline", spc_handler_xtx_fontmapline}, @@ -319,6 +433,10 @@ static struct spc_handler xtx_handlers[] = { {"shadow", spc_handler_xtx_unsupported}, {"colorshadow", spc_handler_xtx_unsupported}, + {"renderingmode", spc_handler_xtx_renderingmode}, + + {"initoverlay", spc_handler_xtx_initoverlay}, + {"clipoverlay", spc_handler_xtx_clipoverlay}, }; int diff --git a/Build/source/texk/xdvipdfmx/src/spc_xtx.h b/Build/source/texk/xdvipdfmx/src/spc_xtx.h index c47ce06cf63..5c4f77bca3a 100644 --- a/Build/source/texk/xdvipdfmx/src/spc_xtx.h +++ b/Build/source/texk/xdvipdfmx/src/spc_xtx.h @@ -38,5 +38,6 @@ extern int spc_xtx_at_end_document (void); extern int spc_xtx_check_special (const char *buffer, long size); extern int spc_xtx_setup_handler (struct spc_handler *handle, struct spc_env *spe, struct spc_arg *args); +extern int spc_handler_xtx_do_rotate (double x_user, double y_user, double value); #endif /* _SPC_XTX_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/specials.h b/Build/source/texk/xdvipdfmx/src/specials.h index 2be14952ea9..4fcdb07a31e 100644 --- a/Build/source/texk/xdvipdfmx/src/specials.h +++ b/Build/source/texk/xdvipdfmx/src/specials.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/specials.h,v 1.3 2005/07/31 16:44:42 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/specials.h,v 1.4 2007/01/20 23:53:20 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. diff --git a/Build/source/texk/xdvipdfmx/src/truetype.c b/Build/source/texk/xdvipdfmx/src/truetype.c index 0a1c164bca4..23c63d4fed0 100644 --- a/Build/source/texk/xdvipdfmx/src/truetype.c +++ b/Build/source/texk/xdvipdfmx/src/truetype.c @@ -117,10 +117,29 @@ pdf_font_open_truetype (pdf_font *font) ASSERT( fontdict && descriptor ); { + char fontname[256]; + int n; pdf_obj *tmp; - tmp = tt_get_fontdesc(sfont, &embedding, 1); + + memset(fontname, 0, 256); + length = tt_get_ps_fontname(sfont, fontname, 255); + if (length < 1) { + length = MIN(strlen(ident), 255); + strncpy(fontname, ident, length); + } + fontname[length] = '\0'; + for (n = 0; n < length; n++) { + if (fontname[n] == 0) { + memmove(fontname + n, fontname + n + 1, length - n - 1); + } + } + if (strlen(fontname) == 0) + ERROR("Can't find valid fontname for \"%s\".", ident); + pdf_font_set_fontname(font, fontname); + + tmp = tt_get_fontdesc(sfont, &embedding, 1, fontname); if (!tmp) { - ERROR("Could not obtain neccesary font info."); + ERROR("Could not obtain necessary font info."); sfnt_close(sfont); if (fp) DPXFCLOSE(fp); @@ -164,27 +183,6 @@ pdf_font_open_truetype (pdf_font *font) } } - { - char fontname[256]; - int n; - - memset(fontname, 0, 256); - length = tt_get_ps_fontname(sfont, fontname, 255); - if (length < 1) { - length = MIN(strlen(ident), 255); - strncpy(fontname, ident, length); - } - fontname[length] = '\0'; - for (n = 0; n < length; n++) { - if (fontname[n] == 0) { - memmove(fontname + n, fontname + n + 1, length - n - 1); - } - } - if (strlen(fontname) == 0) - ERROR("Can't find valid fontname for \"%s\".", ident); - pdf_font_set_fontname(font, fontname); - } - sfnt_close(sfont); if (fp) DPXFCLOSE(fp); diff --git a/Build/source/texk/xdvipdfmx/src/tt_aux.c b/Build/source/texk/xdvipdfmx/src/tt_aux.c index 45d9a233da0..e9da131885f 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_aux.c +++ b/Build/source/texk/xdvipdfmx/src/tt_aux.c @@ -38,6 +38,13 @@ extern int always_embed; /* flag declared in dvipdfmx.c */ +static int verbose = 0; + +void tt_aux_set_verbose() +{ + ++verbose; +} + ULONG ttc_read_offset (sfnt *sfont, int ttc_idx) { LONG version; @@ -137,7 +144,7 @@ ULONG ttc_read_offset (sfnt *sfont, int ttc_idx) #define ALLCAP (1 << 16) /* All-cap font */ #define SMALLCAP (1 << 17) /* Small-cap font */ #define FORCEBOLD (1 << 18) /* Force bold at small text sizes */ -pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int type) +pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int type, const char* fontname) { pdf_obj *descriptor = NULL; pdf_obj *bbox = NULL; @@ -184,26 +191,16 @@ pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int type) /* the least restrictive license granted takes precedence. */ *embed = 1; } else if (os2->fsType & 0x0004) { - static char previewWarningIssued = 0; - if (previewWarningIssued == 0) { - fprintf(stderr, - "\n** NOTICE: This document contains a `Preview & Print only' licensed font **\n"); - previewWarningIssued = 1; - } + if (verbose > 0) + MESG("** NOTICE: Font \"%s\" permits \"Preview & Print\" embedding only **\n", fontname); *embed = 1; } else { if (always_embed) { - static char licenseWarningIssued = 0; - if (licenseWarningIssued == 0) { - fprintf(stderr, - "\n** NOTICE: This document contains an embedded font with licensing restrictions **\n"); - licenseWarningIssued = 1; - } + MESG("** NOTICE: Font \"%s\" may be subject to embedding restrictions **\n", fontname); *embed = 1; } else { - fprintf(stderr, - "\n*** Embedding disabled due to licensing restriction ***\n"); + WARN("Embedding of font \"%s\" disabled due to license restrictions", fontname); *embed = 0; } } diff --git a/Build/source/texk/xdvipdfmx/src/tt_aux.h b/Build/source/texk/xdvipdfmx/src/tt_aux.h index d2528d53335..2353c5e576e 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_aux.h +++ b/Build/source/texk/xdvipdfmx/src/tt_aux.h @@ -26,10 +26,12 @@ #include "pdfobj.h" #include "sfnt.h" +extern void tt_aux_set_verbose(); + /* TTC (TrueType Collection) */ extern ULONG ttc_read_offset (sfnt *sfont, int ttc_idx); /* FontDescriptor */ -extern pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int type); +extern pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int type, const char* fontname); #endif /* _TT_AUX_H_ */ diff --git a/Build/source/texk/xdvipdfmx/src/tt_cmap.c b/Build/source/texk/xdvipdfmx/src/tt_cmap.c index ea8fb0e304e..56076346993 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_cmap.c +++ b/Build/source/texk/xdvipdfmx/src/tt_cmap.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/tt_cmap.c,v 1.24 2005/07/08 14:18:05 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_cmap.c,v 1.25 2007/04/13 06:48:03 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -521,7 +521,7 @@ tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) cmap->map = read_cmap12(sfont, length); break; default: - WARN("Unrecognized TrueType cmap format."); + WARN("Unrecognized OpenType/TrueType cmap format."); tt_cmap_release(cmap); return NULL; } @@ -557,7 +557,7 @@ tt_cmap_release (tt_cmap *cmap) release_cmap12(cmap->map); break; default: - ERROR("Unrecognized TrueType cmap format."); + ERROR("Unrecognized OpenType/TrueType cmap format."); } } RELEASE(cmap); @@ -575,7 +575,7 @@ tt_cmap_lookup (tt_cmap *cmap, long cc) ASSERT(cmap); if (cc > 0xffffL && cmap->format < 12) { - WARN("Four bytes charcode not supported in TrueType cmap format 0...6."); + WARN("Four bytes charcode not supported in OpenType/TrueType cmap format 0...6."); return 0; } @@ -596,7 +596,7 @@ tt_cmap_lookup (tt_cmap *cmap, long cc) gid = lookup_cmap12(cmap->map, (ULONG) cc); break; default: - ERROR("Unrecognized TrueType cmap subtable format"); + ERROR("Unrecognized OpenType/TrueType cmap subtable format"); break; } @@ -889,6 +889,8 @@ handle_subst_glyphs (CMap *cmap, for (k = 0; k < unicode_count; ++k) { len += UC_sput_UTF16BE(unicodes[k], &p, wbuf+WBUF_SIZE); } + wbuf[0] = (gid >> 8) & 0xff; + wbuf[1] = gid & 0xff; CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len); } } @@ -1117,7 +1119,7 @@ otf_create_ToUnicode_stream (const char *font_name, #endif if (!sfont) { - ERROR("Could not open TrueType font file \"%s\"", font_name); + ERROR("Could not open OpenType/TrueType font file \"%s\"", font_name); } switch (sfont->type) { @@ -1133,7 +1135,7 @@ otf_create_ToUnicode_stream (const char *font_name, } if (sfnt_read_table_directory(sfont, offset) < 0) { - ERROR("Could not read TrueType table directory."); + ERROR("Could not read OpenType/TrueType table directory."); } cmap_add_id = CMap_cache_find(cmap_name); @@ -1162,7 +1164,7 @@ otf_create_ToUnicode_stream (const char *font_name, } } if (cmap_obj == NULL) - WARN("Unable to read TrueType Unicode cmap table."); + WARN("Unable to read OpenType/TrueType Unicode cmap table."); tt_cmap_release(ttcmap); CMap_set_silent(0); @@ -1614,10 +1616,10 @@ handle_gsub (pdf_obj *conf, rv = otl_gsub_select(gsub_list, script, language, feature); if (rv < 0) { if (flag == 'p') { - WARN("No GSUB featre %s.%s.%s loaded...", + WARN("No GSUB feature %s.%s.%s loaded...", script, language, feature); } else if (flag == 'r') { - ERROR("No GSUB featre %s.%s.%s loaded...", + ERROR("No GSUB feature %s.%s.%s loaded...", script, language, feature); } } else { @@ -1685,7 +1687,7 @@ fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); sfont = sfnt_open(fp, -1); #endif if (!sfont) { - ERROR("Could not open TrueType font file \"%s\"", map_name); + ERROR("Could not open OpenType/TrueType font file \"%s\"", map_name); } switch (sfont->type) { case SFNT_TYPE_TTC: @@ -1699,12 +1701,12 @@ fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); offset = 0; break; default: - ERROR("Not a TrueType/TTC font?: %s", map_name); + ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name); break; } if (sfnt_read_table_directory(sfont, offset) < 0) - ERROR("Could not read TrueType table directory."); + ERROR("Could not read OpenType/TrueType table directory."); base_name = NEW(strlen(map_name)+strlen("-UCS4-H")+5, char); if (wmode) @@ -1761,18 +1763,21 @@ fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); return cmap_id; } - ttcmap = tt_cmap_read(sfont, 3, 10); + ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */ if (!ttcmap) { - ttcmap = tt_cmap_read(sfont, 3, 1); - } - if (!ttcmap) { - ERROR("Unable to read TrueType Unicode cmap table."); + ttcmap = tt_cmap_read(sfont, 3, 1); /* Microsoft UCS2 */ + if (!ttcmap) { + ttcmap = tt_cmap_read(sfont, 0, 3); /* Unicode 2.0 or later */ + if (!ttcmap) { + ERROR("Unable to read OpenType/TrueType Unicode cmap table."); + } + } } cmap_id = load_base_CMap(base_name, wmode, (is_cidfont ? &csi : NULL), GIDToCIDMap, ttcmap); if (cmap_id < 0) - ERROR("Failed to read TrueType cmap table."); + ERROR("Failed to read OpenType/TrueType cmap table."); if (!otl_tags) { RELEASE(cmap_name); @@ -1847,7 +1852,7 @@ fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); } opt_conf = otl_conf_find_opt(conf, opt_tag); if (!opt_conf) - ERROR("There are no option \"%s\" in \"%s\".", + ERROR("There is no option \"%s\" in \"%s\".", opt_tag, conf_name); load_gsub(opt_conf, gsub_list, sfont); } @@ -1858,7 +1863,7 @@ fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); if (opt_tag) { opt_conf = otl_conf_find_opt(conf, opt_tag); if (!opt_conf) - ERROR("There are no option \"%s\" in \"%s\".", + ERROR("There is no option \"%s\" in \"%s\".", opt_tag, conf_name); handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded); } diff --git a/Build/source/texk/xdvipdfmx/src/tt_glyf.c b/Build/source/texk/xdvipdfmx/src/tt_glyf.c index 3e3e5571281..ef06abbae44 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_glyf.c +++ b/Build/source/texk/xdvipdfmx/src/tt_glyf.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.2 2005/06/09 14:31:11 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.3 2007/02/14 05:56:43 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -249,7 +249,7 @@ tt_build_tables (sfnt *sfont, struct tt_glyphs *g) g->emsize = head->unitsPerEm; sfnt_locate_table(sfont, "hmtx"); - hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); os2 = tt_read_os2__table(sfont); if (os2) { @@ -261,7 +261,7 @@ tt_build_tables (sfnt *sfont, struct tt_glyphs *g) struct tt_vhea_table *vhea; vhea = tt_read_vhea_table(sfont); sfnt_locate_table(sfont, "vmtx"); - vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics); + vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings); RELEASE(vhea); } else { vmtx = NULL; @@ -425,15 +425,15 @@ tt_build_tables (sfnt *sfont, struct tt_glyphs *g) padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0; glyf_table_size += g->gd[i].length + padlen; if (!num_hm_known && last_advw != g->gd[i].advw) { - hhea->numberOfHMetrics = g->gd[i].gid + 2; + hhea->numOfLongHorMetrics = g->gd[i].gid + 2; num_hm_known = 1; } } /* All advance widths are same. */ if (!num_hm_known) { - hhea->numberOfHMetrics = 1; + hhea->numOfLongHorMetrics = 1; } - hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2; + hmtx_table_size = hhea->numOfLongHorMetrics * 2 + (g->last_gid + 1) * 2; /* * Choosing short format does not always give good result @@ -456,9 +456,9 @@ tt_build_tables (sfnt *sfont, struct tt_glyphs *g) long gap, j; gap = (long) g->gd[i].gid - prev - 1; for (j = 1; j <= gap; j++) { - if (prev + j == hhea->numberOfHMetrics - 1) { + if (prev + j == hhea->numOfLongHorMetrics - 1) { p += sfnt_put_ushort(p, last_advw); - } else if (prev + j < hhea->numberOfHMetrics) { + } else if (prev + j < hhea->numOfLongHorMetrics) { p += sfnt_put_ushort(p, 0); } p += sfnt_put_short (p, 0); @@ -469,7 +469,7 @@ tt_build_tables (sfnt *sfont, struct tt_glyphs *g) } } padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0; - if (g->gd[i].gid < hhea->numberOfHMetrics) { + if (g->gd[i].gid < hhea->numOfLongHorMetrics) { p += sfnt_put_ushort(p, g->gd[i].advw); } p += sfnt_put_short (p, g->gd[i].lsb); @@ -559,7 +559,7 @@ tt_get_metrics (sfnt *sfont, struct tt_glyphs *g) g->emsize = head->unitsPerEm; sfnt_locate_table(sfont, "hmtx"); - hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); os2 = tt_read_os2__table(sfont); g->default_advh = os2->sTypoAscender - os2->sTypoDescender; @@ -569,7 +569,7 @@ tt_get_metrics (sfnt *sfont, struct tt_glyphs *g) struct tt_vhea_table *vhea; vhea = tt_read_vhea_table(sfont); sfnt_locate_table(sfont, "vmtx"); - vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics); + vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics, vhea->numOfExSideBearings); RELEASE(vhea); } else { vmtx = NULL; diff --git a/Build/source/texk/xdvipdfmx/src/tt_post.c b/Build/source/texk/xdvipdfmx/src/tt_post.c index 5a2b513e156..8779010a205 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_post.c +++ b/Build/source/texk/xdvipdfmx/src/tt_post.c @@ -138,15 +138,20 @@ tt_read_post_table (sfnt *sfont) post->names = NULL; } else if (post->Version == 0x00020000UL) { if (read_v2_post_names(post, sfont) < 0) { - WARN("Invalid TrueType 'post' table..."); + WARN("Invalid version 2.0 'post' table"); tt_release_post_table(post); post = NULL; } - } else if (post->Version == 0x00030000UL) { + } else if (post->Version == 0x00030000UL) { /* no glyph names provided */ post->numberOfGlyphs = 0; /* wrong */ post->glyphNamePtr = NULL; post->count = 0; post->names = NULL; + } else if (post->Version == 0x00040000UL) { /* Apple format for printer-based fonts */ + post->numberOfGlyphs = 0; /* don't bother constructing char names, not sure if they'll ever be needed */ + post->glyphNamePtr = NULL; + post->count = 0; + post->names = NULL; } else { WARN("Unknown 'post' version: %08X", post->Version); tt_release_post_table(post); diff --git a/Build/source/texk/xdvipdfmx/src/tt_table.c b/Build/source/texk/xdvipdfmx/src/tt_table.c index e76f0554d3f..a7d1cb13063 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_table.c +++ b/Build/source/texk/xdvipdfmx/src/tt_table.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.7 2004/09/11 14:50:29 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.8 2007/02/14 05:56:43 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -33,7 +33,7 @@ /* tables contains information refered by other tables maxp->numGlyphs, etc --> loca, etc - hhea->numberOfHMetrics --> hmtx + hhea->numOfLongHorMetrics --> hmtx head->indexToLocFormat --> loca head->glyphDataFormat --> glyf */ @@ -163,20 +163,21 @@ char *tt_pack_hhea_table (struct tt_hhea_table *table) p = data = NEW(TT_HHEA_TABLE_SIZE, char); p += sfnt_put_ulong(p, table->version); - p += sfnt_put_short(p, table->Ascender); - p += sfnt_put_short(p, table->Descender); - p += sfnt_put_short(p, table->LineGap); + p += sfnt_put_short(p, table->ascent); + p += sfnt_put_short(p, table->descent); + p += sfnt_put_short(p, table->lineGap); p += sfnt_put_ushort(p, table->advanceWidthMax); p += sfnt_put_short(p, table->minLeftSideBearing); p += sfnt_put_short(p, table->minRightSideBearing); p += sfnt_put_short(p, table->xMaxExtent); p += sfnt_put_short(p, table->caretSlopeRise); p += sfnt_put_short(p, table->caretSlopeRun); - for (i = 0; i < 5; i++) { + p += sfnt_put_short(p, table->caretOffset); + for (i = 0; i < 4; i++) { p += sfnt_put_short(p, table->reserved[i]); } p += sfnt_put_short(p, table->metricDataFormat); - p += sfnt_put_ushort(p, table->numberOfHMetrics); + p += sfnt_put_ushort(p, table->numOfLongHorMetrics); return data; } @@ -185,28 +186,32 @@ struct tt_hhea_table * tt_read_hhea_table (sfnt *sfont) { int i; + ULONG len; struct tt_hhea_table *table = NULL; - table = NEW(1, struct tt_hhea_table); - + len = sfnt_find_table_len(sfont, "hhea"); sfnt_locate_table(sfont, "hhea"); - table->version = sfnt_get_ulong(sfont); - table->Ascender = sfnt_get_short (sfont); - table->Descender = sfnt_get_short(sfont); - table->LineGap = sfnt_get_short(sfont); + + table = NEW(1, struct tt_hhea_table); + table->version = sfnt_get_ulong(sfont); + table->ascent = sfnt_get_short (sfont); + table->descent = sfnt_get_short(sfont); + table->lineGap = sfnt_get_short(sfont); table->advanceWidthMax = sfnt_get_ushort(sfont); table->minLeftSideBearing = sfnt_get_short(sfont); table->minRightSideBearing = sfnt_get_short(sfont); table->xMaxExtent = sfnt_get_short(sfont); table->caretSlopeRise = sfnt_get_short(sfont); table->caretSlopeRun = sfnt_get_short(sfont); - for(i = 0; i < 5; i++) { + table->caretOffset = sfnt_get_short(sfont); + for(i = 0; i < 4; i++) { table->reserved[i] = sfnt_get_short(sfont); } table->metricDataFormat = sfnt_get_short(sfont); if (table->metricDataFormat != 0) - ERROR("unknown metricDaraFormat"); - table->numberOfHMetrics = sfnt_get_ushort(sfont); + ERROR("unknown metricDataFormat"); + table->numOfLongHorMetrics = sfnt_get_ushort(sfont); + table->numOfExSideBearings = (USHORT)((len - table->numOfLongHorMetrics * 4) / 2); return table; } @@ -230,9 +235,10 @@ tt_pack_vhea_table (struct tt_vhea_table *table) p += sfnt_put_short(p, table->caretSlopeRise); p += sfnt_put_short(p, table->caretSlopeRun); p += sfnt_put_short(p, table->caretOffset); - for(i = 0; i < 5; i++) { + for(i = 0; i < 4; i++) { p += sfnt_put_short(p, table->reserved[i]); } + p += sfnt_put_short(p, table->metricDataFormat); p += sfnt_put_ushort(p, table->numOfLongVerMetrics); return data; @@ -240,11 +246,13 @@ tt_pack_vhea_table (struct tt_vhea_table *table) struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont) { - int i; + int i; + ULONG len; struct tt_vhea_table *table = NULL; table = NEW(1, struct tt_vhea_table); + len = sfnt_find_table_len(sfont, "vhea"); sfnt_locate_table(sfont, "vhea"); table->version = sfnt_get_ulong(sfont); table->vertTypoAscender = sfnt_get_short (sfont); @@ -257,10 +265,12 @@ struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont) table->caretSlopeRise = sfnt_get_short(sfont); table->caretSlopeRun = sfnt_get_short(sfont); table->caretOffset = sfnt_get_short(sfont); - for(i=0;i<5;i++) { + for(i = 0; i < 4; i++) { (table->reserved)[i] = sfnt_get_short(sfont); } + table->metricDataFormat = sfnt_get_short(sfont); table->numOfLongVerMetrics = sfnt_get_ushort(sfont); + table->numOfExSideBearings = (USHORT)((len - table->numOfLongVerMetrics * 4) / 2); return table; } @@ -310,17 +320,20 @@ tt_read_VORG_table (sfnt *sfont) */ struct tt_longMetrics * -tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics) +tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics, USHORT numExSideBearings) { struct tt_longMetrics *m; USHORT gid, last_adv = 0; + SHORT last_esb = 0; m = NEW(numGlyphs, struct tt_longMetrics); for (gid = 0; gid < numGlyphs; gid++) { if (gid < numLongMetrics) last_adv = sfnt_get_ushort(sfont); - m[gid].sideBearing = sfnt_get_short(sfont); + if (gid < numLongMetrics + numExSideBearings) + last_esb = sfnt_get_short(sfont); m[gid].advance = last_adv; + m[gid].sideBearing = last_esb; } return m; @@ -370,21 +383,30 @@ tt_read_os2__table (sfnt *sfont) table->fsSelection = sfnt_get_ushort(sfont); table->usFirstCharIndex = sfnt_get_ushort(sfont); table->usLastCharIndex = sfnt_get_ushort(sfont); - table->sTypoAscender = sfnt_get_short(sfont); - table->sTypoDescender = sfnt_get_short(sfont); - table->sTypoLineGap = sfnt_get_short(sfont); - table->usWinAscent = sfnt_get_ushort(sfont); - table->usWinDescent = sfnt_get_ushort(sfont); - table->ulCodePageRange1 = sfnt_get_ulong(sfont); - table->ulCodePageRange2 = sfnt_get_ulong(sfont); - if (table->version == 0x0002) { - table->sxHeight = sfnt_get_short(sfont); - table->sCapHeight = sfnt_get_short(sfont); - table->usDefaultChar = sfnt_get_ushort(sfont); - table->usBreakChar = sfnt_get_ushort(sfont); - table->usMaxContext = sfnt_get_ushort(sfont); + if (sfnt_find_table_len(sfont, "OS/2") >= 78) { + /* these fields are not present in the original Apple spec (68-byte table), + but Microsoft's version of "format 0" does include them... grr! */ + table->sTypoAscender = sfnt_get_short(sfont); + table->sTypoDescender = sfnt_get_short(sfont); + table->sTypoLineGap = sfnt_get_short(sfont); + table->usWinAscent = sfnt_get_ushort(sfont); + table->usWinDescent = sfnt_get_ushort(sfont); + if (table->version > 0) { + /* format 1 adds the following 2 fields */ + table->ulCodePageRange1 = sfnt_get_ulong(sfont); + table->ulCodePageRange2 = sfnt_get_ulong(sfont); + if (table->version > 1) { + /* and formats 2 and 3 (current) include 5 more.... these share the + same fields, only the precise definition of some was changed */ + table->sxHeight = sfnt_get_short(sfont); + table->sCapHeight = sfnt_get_short(sfont); + table->usDefaultChar = sfnt_get_ushort(sfont); + table->usBreakChar = sfnt_get_ushort(sfont); + table->usMaxContext = sfnt_get_ushort(sfont); + } + } } - + return table; } diff --git a/Build/source/texk/xdvipdfmx/src/tt_table.h b/Build/source/texk/xdvipdfmx/src/tt_table.h index 6bc73ca6808..30679a78a56 100644 --- a/Build/source/texk/xdvipdfmx/src/tt_table.h +++ b/Build/source/texk/xdvipdfmx/src/tt_table.h @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.h,v 1.6 2004/09/11 14:50:29 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.h,v 1.7 2007/02/14 05:56:43 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -51,18 +51,20 @@ struct tt_head_table struct tt_hhea_table { Fixed version; - FWord Ascender; - FWord Descender; - FWord LineGap; + FWord ascent; + FWord descent; + FWord lineGap; uFWord advanceWidthMax; FWord minLeftSideBearing; FWord minRightSideBearing; FWord xMaxExtent; SHORT caretSlopeRise; SHORT caretSlopeRun; - SHORT reserved[5]; /* set to 0 */ + FWord caretOffset; + SHORT reserved[4]; /* set to 0 */ SHORT metricDataFormat; - USHORT numberOfHMetrics; + USHORT numOfLongHorMetrics; + USHORT numOfExSideBearings; /* extra information */ }; struct tt_vhea_table @@ -78,8 +80,10 @@ struct tt_vhea_table SHORT caretSlopeRise; SHORT caretSlopeRun; SHORT caretOffset; - SHORT reserved[5]; /* set to 0 */ + SHORT reserved[4]; /* set to 0 */ + SHORT metricDataFormat; USHORT numOfLongVerMetrics; + USHORT numOfExSideBearings; /* extra information */ }; struct tt_maxp_table @@ -179,7 +183,7 @@ extern struct tt_VORG_table *tt_read_VORG_table (sfnt *sfont); /* hmtx and vmtx */ extern struct tt_longMetrics *tt_read_longMetrics (sfnt *sfont, - USHORT numGlyphs, USHORT numLongMetrics); + USHORT numGlyphs, USHORT numLongMetrics, USHORT numExSideBearings); /* OS/2 table */ extern struct tt_os2__table *tt_read_os2__table (sfnt *sfont); diff --git a/Build/source/texk/xdvipdfmx/src/type1.c b/Build/source/texk/xdvipdfmx/src/type1.c index e896508210e..f7488f43ac1 100644 --- a/Build/source/texk/xdvipdfmx/src/type1.c +++ b/Build/source/texk/xdvipdfmx/src/type1.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/type1.c,v 1.38 2005/07/17 09:53:38 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/type1.c,v 1.39 2007/04/17 10:06:30 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -268,7 +268,7 @@ get_font_attr (pdf_font *font, cff_font *cffont) } static void -add_metrics (pdf_font *font, cff_font *cffont, double *widths, long num_glyphs) +add_metrics (pdf_font *font, cff_font *cffont, char **enc_vec, double *widths, long num_glyphs) { pdf_obj *fontdict, *descriptor; pdf_obj *tmp_array; @@ -321,7 +321,7 @@ add_metrics (pdf_font *font, cff_font *cffont, double *widths, long num_glyphs) } for (code = firstchar; code <= lastchar; code++) { if (usedchars[code]) { - gid = cff_encoding_lookup(cffont, code); + gid = cff_glyph_lookup(cffont, enc_vec[code]); pdf_add_array(tmp_array, pdf_new_number(ROUND(widths[gid], 1.0))); } else { @@ -541,16 +541,12 @@ pdf_font_load_type1 (pdf_font *font) pdf_new_name("Encoding"), pdf_new_name(pdf_encoding_get_name(encoding_id))); } else { -#if 0 - /* - * Gs not working with this. - */ + /* CAUTION: Ghostscript may not work with this. Which Ghostscript? */ pdf_add_dict(fontdict, pdf_new_name("Encoding"), - pdf_get_encoding_resource(enc)); -#endif + pdf_get_encoding_reference(encoding_id)); if (!pdf_lookup_dict(fontdict, "ToUnicode")) - pdf_attach_ToUnicode_CMap(fontdict, encoding_id, usedchars); + pdf_attach_ToUnicode_CMap(fontdict, encoding_id, usedchars); } enc_vec = pdf_encoding_get_encoding(encoding_id); } else { @@ -781,7 +777,7 @@ pdf_font_load_type1 (pdf_font *font) if (verbose > 2) MESG("]"); - add_metrics(font, cffont, widths, num_glyphs); + add_metrics(font, cffont, enc_vec, widths, num_glyphs); offset = write_fontfile(font, cffont, num_glyphs); if (verbose > 1) diff --git a/Build/source/texk/xdvipdfmx/src/type1c.c b/Build/source/texk/xdvipdfmx/src/type1c.c index ae91baafe22..2478d71cb44 100644 --- a/Build/source/texk/xdvipdfmx/src/type1c.c +++ b/Build/source/texk/xdvipdfmx/src/type1c.c @@ -142,7 +142,7 @@ pdf_font_open_type1c (pdf_font *font) * Create font descriptor from OpenType tables. * We can also use CFF TOP DICT/Private DICT for this. */ - tmp = tt_get_fontdesc(sfont, &embedding, 1); + tmp = tt_get_fontdesc(sfont, &embedding, 1, fontname); if (!tmp) { ERROR("Could not obtain neccesary font info from OpenType table."); return -1; diff --git a/Build/source/texk/xdvipdfmx/src/vf.c b/Build/source/texk/xdvipdfmx/src/vf.c index 589c5907767..a310c083da7 100644 --- a/Build/source/texk/xdvipdfmx/src/vf.c +++ b/Build/source/texk/xdvipdfmx/src/vf.c @@ -1,4 +1,4 @@ -/* $Header: /home/cvsroot/dvipdfmx/src/vf.c,v 1.16 2005/07/20 10:41:54 hirata Exp $ +/* $Header: /home/cvsroot/dvipdfmx/src/vf.c,v 1.17 2007/04/17 10:12:04 chofchof Exp $ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. @@ -768,7 +768,8 @@ static void vf_xxx (SIGNED_QUAD len, unsigned char **start, unsigned char *end) * Warning message from virtual font. */ if (!memcmp((char *)p, "Warning:", 8)) { - WARN("VF:%s", p+8); + if (verbose) + WARN("VF:%s", p+8); } else { dvi_do_special(buffer, len); } -- cgit v1.2.3