From de569c5d3871e3aea62a0d01e2f86d50f1202591 Mon Sep 17 00:00:00 2001 From: Peter Breitenlohner Date: Mon, 29 Jul 2013 12:13:50 +0000 Subject: dvipdfm-x: Merging dvipdfmx and xdvipdfmx, now just one set of source files git-svn-id: svn://tug.org/texlive/trunk@31302 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/dvipdfm-x/ChangeLog | 9 + Build/source/texk/dvipdfm-x/Makefile.am | 186 +- Build/source/texk/dvipdfm-x/Makefile.in | 1389 +++++------ Build/source/texk/dvipdfm-x/cff.c | 8 +- Build/source/texk/dvipdfm-x/cff.h | 6 + Build/source/texk/dvipdfm-x/cidtype0.c | 2092 ++++++++++++++++ Build/source/texk/dvipdfm-x/dvi.c | 2801 ++++++++++++++++++++++ Build/source/texk/dvipdfm-x/dvi.h | 8 +- Build/source/texk/dvipdfm-x/dvicodes.h | 7 +- Build/source/texk/dvipdfm-x/dvipdfm-bb.test | 20 +- Build/source/texk/dvipdfm-x/dvipdfmx.c | 1058 +++++++++ Build/source/texk/dvipdfm-x/dvipdfmx.h | 13 +- Build/source/texk/dvipdfm-x/dvipdfmx.test | 22 +- Build/source/texk/dvipdfm-x/epdf.c | 974 ++++++++ Build/source/texk/dvipdfm-x/epdf.h | 7 +- Build/source/texk/dvipdfm-x/jpegimage.c | 951 ++++++++ Build/source/texk/dvipdfm-x/mpost.c | 12 - Build/source/texk/dvipdfm-x/pdfcolor.c | 1589 +++++++++++++ Build/source/texk/dvipdfm-x/pdfcolor.h | 11 +- Build/source/texk/dvipdfm-x/pdfdev.c | 1963 +++++++++++++++ Build/source/texk/dvipdfm-x/pdfdev.h | 8 +- Build/source/texk/dvipdfm-x/pdfdoc.c | 2742 +++++++++++++++++++++ Build/source/texk/dvipdfm-x/pdfdraw.c | 2022 ++++++++++++++++ Build/source/texk/dvipdfm-x/pdfdraw.h | 7 +- Build/source/texk/dvipdfm-x/pdfnames.c | 584 +++++ Build/source/texk/dvipdfm-x/pdfobj.c | 3294 ++++++++++++++++++++++++++ Build/source/texk/dvipdfm-x/pdfximage.c | 970 ++++++++ Build/source/texk/dvipdfm-x/spc_pdfm.c | 2143 +++++++++++++++++ Build/source/texk/dvipdfm-x/spc_tpic.c | 1136 +++++++++ Build/source/texk/dvipdfm-x/spc_util.c | 11 - Build/source/texk/dvipdfm-x/spc_util.h | 3 - Build/source/texk/dvipdfm-x/spc_xtx.c | 2 +- Build/source/texk/dvipdfm-x/src/cidtype0.c | 2076 ---------------- Build/source/texk/dvipdfm-x/src/dvi.c | 2481 ------------------- Build/source/texk/dvipdfm-x/src/dvipdfmx.c | 1043 -------- Build/source/texk/dvipdfm-x/src/epdf.c | 968 -------- Build/source/texk/dvipdfm-x/src/jpegimage.c | 920 ------- Build/source/texk/dvipdfm-x/src/pdfcolor.c | 1580 ------------ Build/source/texk/dvipdfm-x/src/pdfdev.c | 2015 ---------------- Build/source/texk/dvipdfm-x/src/pdfdoc.c | 2745 --------------------- Build/source/texk/dvipdfm-x/src/pdfdraw.c | 1884 --------------- Build/source/texk/dvipdfm-x/src/pdfnames.c | 499 ---- Build/source/texk/dvipdfm-x/src/pdfobj.c | 3264 ------------------------- Build/source/texk/dvipdfm-x/src/pdfximage.c | 961 -------- Build/source/texk/dvipdfm-x/src/spc_pdfm.c | 2130 ----------------- Build/source/texk/dvipdfm-x/src/spc_tpic.c | 1136 --------- Build/source/texk/dvipdfm-x/src/tt_cmap.c | 1938 --------------- Build/source/texk/dvipdfm-x/src/type1c.c | 756 ------ Build/source/texk/dvipdfm-x/src/xbb.c | 483 ---- Build/source/texk/dvipdfm-x/tfm.c | 4 +- Build/source/texk/dvipdfm-x/truetype.c | 4 - Build/source/texk/dvipdfm-x/tt_aux.c | 22 +- Build/source/texk/dvipdfm-x/tt_aux.h | 2 - Build/source/texk/dvipdfm-x/tt_cmap.c | 1946 +++++++++++++++ Build/source/texk/dvipdfm-x/type1c.c | 764 ++++++ Build/source/texk/dvipdfm-x/vf.c | 42 +- Build/source/texk/dvipdfm-x/xbb.c | 461 ++++ Build/source/texk/dvipdfm-x/xdvipdfm-bb.test | 20 +- Build/source/texk/dvipdfm-x/xdvipdfmx.test | 22 +- Build/source/texk/dvipdfm-x/xsrc/cidtype0.c | 2076 ---------------- Build/source/texk/dvipdfm-x/xsrc/dvi.c | 2754 --------------------- Build/source/texk/dvipdfm-x/xsrc/dvipdfmx.c | 1022 -------- Build/source/texk/dvipdfm-x/xsrc/epdf.c | 915 ------- Build/source/texk/dvipdfm-x/xsrc/jpegimage.c | 979 -------- Build/source/texk/dvipdfm-x/xsrc/pdfcolor.c | 1584 ------------- Build/source/texk/dvipdfm-x/xsrc/pdfdev.c | 2004 ---------------- Build/source/texk/dvipdfm-x/xsrc/pdfdoc.c | 2719 --------------------- Build/source/texk/dvipdfm-x/xsrc/pdfdraw.c | 1906 --------------- Build/source/texk/dvipdfm-x/xsrc/pdfnames.c | 519 ---- Build/source/texk/dvipdfm-x/xsrc/pdfobj.c | 3244 ------------------------- Build/source/texk/dvipdfm-x/xsrc/pdfximage.c | 957 -------- Build/source/texk/dvipdfm-x/xsrc/spc_pdfm.c | 2125 ----------------- Build/source/texk/dvipdfm-x/xsrc/spc_tpic.c | 1130 --------- Build/source/texk/dvipdfm-x/xsrc/tt_cmap.c | 1944 --------------- Build/source/texk/dvipdfm-x/xsrc/type1c.c | 756 ------ Build/source/texk/dvipdfm-x/xsrc/xbb.c | 443 ---- 76 files changed, 28317 insertions(+), 54974 deletions(-) create mode 100644 Build/source/texk/dvipdfm-x/cidtype0.c create mode 100644 Build/source/texk/dvipdfm-x/dvi.c create mode 100644 Build/source/texk/dvipdfm-x/dvipdfmx.c create mode 100644 Build/source/texk/dvipdfm-x/epdf.c create mode 100644 Build/source/texk/dvipdfm-x/jpegimage.c create mode 100644 Build/source/texk/dvipdfm-x/pdfcolor.c create mode 100644 Build/source/texk/dvipdfm-x/pdfdev.c create mode 100644 Build/source/texk/dvipdfm-x/pdfdoc.c create mode 100644 Build/source/texk/dvipdfm-x/pdfdraw.c create mode 100644 Build/source/texk/dvipdfm-x/pdfnames.c create mode 100644 Build/source/texk/dvipdfm-x/pdfobj.c create mode 100644 Build/source/texk/dvipdfm-x/pdfximage.c create mode 100644 Build/source/texk/dvipdfm-x/spc_pdfm.c create mode 100644 Build/source/texk/dvipdfm-x/spc_tpic.c delete mode 100644 Build/source/texk/dvipdfm-x/src/cidtype0.c delete mode 100644 Build/source/texk/dvipdfm-x/src/dvi.c delete mode 100644 Build/source/texk/dvipdfm-x/src/dvipdfmx.c delete mode 100644 Build/source/texk/dvipdfm-x/src/epdf.c delete mode 100644 Build/source/texk/dvipdfm-x/src/jpegimage.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfcolor.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfdev.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfdoc.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfdraw.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfnames.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfobj.c delete mode 100644 Build/source/texk/dvipdfm-x/src/pdfximage.c delete mode 100644 Build/source/texk/dvipdfm-x/src/spc_pdfm.c delete mode 100644 Build/source/texk/dvipdfm-x/src/spc_tpic.c delete mode 100644 Build/source/texk/dvipdfm-x/src/tt_cmap.c delete mode 100644 Build/source/texk/dvipdfm-x/src/type1c.c delete mode 100644 Build/source/texk/dvipdfm-x/src/xbb.c create mode 100644 Build/source/texk/dvipdfm-x/tt_cmap.c create mode 100644 Build/source/texk/dvipdfm-x/type1c.c create mode 100644 Build/source/texk/dvipdfm-x/xbb.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/cidtype0.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/dvi.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/dvipdfmx.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/epdf.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/jpegimage.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfcolor.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfdev.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfdoc.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfdraw.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfnames.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfobj.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/pdfximage.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/spc_pdfm.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/spc_tpic.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/tt_cmap.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/type1c.c delete mode 100644 Build/source/texk/dvipdfm-x/xsrc/xbb.c (limited to 'Build/source') diff --git a/Build/source/texk/dvipdfm-x/ChangeLog b/Build/source/texk/dvipdfm-x/ChangeLog index 44bd4920145..c4be0aef5cc 100644 --- a/Build/source/texk/dvipdfm-x/ChangeLog +++ b/Build/source/texk/dvipdfm-x/ChangeLog @@ -1,3 +1,12 @@ +2013-07-29 Peter Breitenlohner + + * Removed diffs between src/ and xsrc/ version of the remaining + files and moved them to the top-level: cidtype0.c, dvi.c, + dvipdfmx.c, epdf.c, jpegimage.c, pdfcolor.c, pdfdev.c, pdfdoc.c, + pdfdraw.c, pdfobj.c, pdfximage.c, spc_pdfm.c, spc_tpic.c, + tt_cmap.c, type1c.c, xbb.c. + * Makefile.am: Adapted. + 2013-07-22 Peter Breitenlohner * tt_aux.c, tt_post.c: Try to avoid a segfault for some broken diff --git a/Build/source/texk/dvipdfm-x/Makefile.am b/Build/source/texk/dvipdfm-x/Makefile.am index c47b65ce706..4533b562f97 100644 --- a/Build/source/texk/dvipdfm-x/Makefile.am +++ b/Build/source/texk/dvipdfm-x/Makefile.am @@ -26,187 +26,163 @@ xdvipdfmx_CPPFLAGS = -DXETEX -I$(srcdir)/xsrc $(FREETYPE2_INCLUDES) $(common_cpp AM_CFLAGS = $(WARNING_CFLAGS) libutil_a_SOURCES = \ + agl.h \ + bmpimage.h \ + cff_dict.h \ + cff_limits.h \ + cff_stdstr.h \ + cff_types.h \ + cid_basefont.h \ + cidtype0.c \ + cidtype0.h \ + cidtype2.h \ + cmap.h \ + cmap_p.h \ + cmap_read.h \ + cmap_write.h \ cs_type2.c \ cs_type2.h \ dpxconf.c \ dpxconf.h \ dpxcrypt.c \ dpxcrypt.h \ + dpxfile.h \ + dpxutil.h \ + dvi.h \ + dvicodes.h \ + dvipdfmx.h \ + epdf.h \ error.c \ error.h \ + jpegimage.h \ mem.c \ mem.h \ mfileio.c \ mfileio.h \ + mpost.h \ numbers.c \ numbers.h \ + otl_conf.h \ otl_opt.c \ otl_opt.h \ + pdfcolor.h \ + pdfdev.h \ + pdfdoc.h \ pdfencrypt.c \ pdfencrypt.h \ pdfencoding.c \ pdfencoding.h \ + pdflimits.h \ + pdfnames.h \ + pdfobj.h \ + pdfparse.h \ + pdfresource.h \ + pdfximage.h \ + pkfont.h \ + pngimage.h \ + pst.h \ + pst_obj.h \ + spc_color.h \ + spc_dvips.h \ + spc_html.h \ + spc_misc.h \ + spc_pdfm.h \ + spc_tpic.h \ + spc_util.h \ + specials.h \ subfont.c \ subfont.h \ system.h \ + t1_char.h \ + t1_load.h \ + tfm.h \ + truetype.h \ + tt_aux.h \ + tt_glyf.h \ + tt_gsub.h \ + tt_post.h \ + tt_table.h \ + type1.h \ + type1c.c \ + type1c.h \ unicode.c \ - unicode.h - -nodist_dvipdfmx_SOURCES = $(common_sources) $(dvipdfmx_sources) -nodist_xdvipdfmx_SOURCES = $(common_sources) $(xdvipdfmx_sources) - -dvipdfmx_LDADD = $(KPATHSEA_LIBS) $(LIBPNG_LIBS) $(ZLIB_LIBS) libutil.a -xdvipdfmx_LDADD = $(FREETYPE2_LIBS) $(dvipdfmx_LDADD) - -$(dvipdfmx_OBJECTS) $(xdvipdfmx_OBJECTS): config.force + unicode.h \ + vf.h -common_sources = \ +dvipdfmx_SOURCES = \ agl.c \ - agl.h \ bmpimage.c \ - bmpimage.h \ cff.c \ cff.h \ cff_dict.c \ - cff_dict.h \ - cff_limits.h \ - cff_stdstr.h \ - cff_types.h \ cid.c \ cid.h \ - cid_basefont.h \ cid_p.h \ - cidtype0.h \ cidtype2.c \ - cidtype2.h \ cmap.c \ - cmap.h \ - cmap_p.h \ cmap_read.c \ - cmap_read.h \ cmap_write.c \ - cmap_write.h \ dpxfile.c \ - dpxfile.h \ dpxutil.c \ - dpxutil.h \ - dvi.h \ - dvicodes.h \ - dvipdfmx.h \ - epdf.h \ + dvi.c \ + dvipdfmx.c \ + epdf.c \ fontmap.c \ fontmap.h \ - jpegimage.h \ + jpegimage.c \ mpost.c \ - mpost.h \ otl_conf.c \ - otl_conf.h \ - pdfcolor.h \ - pdfdev.h \ - pdfdoc.h \ + pdfcolor.c \ + pdfdev.c \ + pdfdoc.c \ + pdfdraw.c \ pdfdraw.h \ pdffont.c \ pdffont.h \ - pdflimits.h \ - pdfnames.h \ - pdfobj.h \ + pdfnames.c \ + pdfobj.c \ pdfparse.c \ - pdfparse.h \ pdfresource.c \ - pdfresource.h \ - pdfximage.h \ + pdfximage.c \ pkfont.c \ - pkfont.h \ pngimage.c \ - pngimage.h \ pst.c \ - pst.h \ pst_obj.c \ - pst_obj.h \ sfnt.c \ sfnt.h \ spc_color.c \ - spc_color.h \ spc_dvips.c \ - spc_dvips.h \ spc_html.c \ - spc_html.h \ spc_misc.c \ - spc_misc.h \ - spc_pdfm.h \ - spc_tpic.h \ + spc_pdfm.c \ + spc_tpic.c \ spc_util.c \ - spc_util.h \ + spc_xtx.c \ + spc_xtx.h \ specials.c \ - specials.h \ t1_char.c \ - t1_char.h \ t1_load.c \ - t1_load.h \ tfm.c \ - tfm.h \ truetype.c \ - truetype.h \ tt_aux.c \ - tt_aux.h \ + tt_cmap.c \ tt_cmap.h \ tt_glyf.c \ - tt_glyf.h \ tt_gsub.c \ - tt_gsub.h \ tt_post.c \ - tt_post.h \ tt_table.c \ - tt_table.h \ type0.c \ type0.h \ type1.c \ - type1.h \ - type1c.h \ vf.c \ - vf.h + xbb.c -dvipdfmx_sources = \ - src/cidtype0.c \ - src/dvi.c \ - src/dvipdfmx.c \ - src/epdf.c \ - src/jpegimage.c \ - src/pdfcolor.c \ - src/pdfdev.c \ - src/pdfdoc.c \ - src/pdfdraw.c \ - src/pdfnames.c \ - src/pdfobj.c \ - src/pdfximage.c \ - src/spc_pdfm.c \ - src/spc_tpic.c \ - src/tt_cmap.c \ - src/type1c.c \ - src/xbb.c +nodist_xdvipdfmx_SOURCES = $(dvipdfmx_SOURCES) -xdvipdfmx_sources = \ - xsrc/cidtype0.c \ - xsrc/dvi.c \ - xsrc/dvipdfmx.c \ - xsrc/epdf.c \ - xsrc/jpegimage.c \ - xsrc/pdfcolor.c \ - xsrc/pdfdev.c \ - xsrc/pdfdoc.c \ - xsrc/pdfdraw.c \ - xsrc/pdfnames.c \ - xsrc/pdfobj.c \ - xsrc/pdfximage.c \ - xsrc/spc_pdfm.c \ - xsrc/spc_tpic.c \ - spc_xtx.c \ - spc_xtx.h \ - xsrc/tt_cmap.c \ - xsrc/type1c.c \ - xsrc/xbb.c +dvipdfmx_LDADD = $(KPATHSEA_LIBS) $(LIBPNG_LIBS) $(ZLIB_LIBS) libutil.a +xdvipdfmx_LDADD = $(FREETYPE2_LIBS) $(dvipdfmx_LDADD) -EXTRA_DIST = $(common_sources) $(dvipdfmx_sources) $(xdvipdfmx_sources) +$(dvipdfmx_OBJECTS) $(xdvipdfmx_OBJECTS): config.force ## Links ## @@ -302,7 +278,7 @@ xdvipdfmx_tests = xdvipdfmx.test xdvipdfm-bb.test if XDVIPDFMX TESTS += $(xdvipdfmx_tests) endif XDVIPDFMX -EXTRA_DIST += $(dvipdfmx_tests) $(xdvipdfmx_tests) +EXTRA_DIST = $(dvipdfmx_tests) $(xdvipdfmx_tests) ## Test Data ## EXTRA_DIST += tests/dvipdfmx.cfg diff --git a/Build/source/texk/dvipdfm-x/Makefile.in b/Build/source/texk/dvipdfm-x/Makefile.in index d4b7a757dff..9e5ab7c1622 100644 --- a/Build/source/texk/dvipdfm-x/Makefile.in +++ b/Build/source/texk/dvipdfm-x/Makefile.in @@ -146,11 +146,11 @@ am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libutil_a_AR = $(AR) $(ARFLAGS) libutil_a_LIBADD = -am_libutil_a_OBJECTS = cs_type2.$(OBJEXT) dpxconf.$(OBJEXT) \ - dpxcrypt.$(OBJEXT) error.$(OBJEXT) mem.$(OBJEXT) \ - mfileio.$(OBJEXT) numbers.$(OBJEXT) otl_opt.$(OBJEXT) \ - pdfencrypt.$(OBJEXT) pdfencoding.$(OBJEXT) subfont.$(OBJEXT) \ - unicode.$(OBJEXT) +am_libutil_a_OBJECTS = cidtype0.$(OBJEXT) cs_type2.$(OBJEXT) \ + dpxconf.$(OBJEXT) dpxcrypt.$(OBJEXT) error.$(OBJEXT) \ + mem.$(OBJEXT) mfileio.$(OBJEXT) numbers.$(OBJEXT) \ + otl_opt.$(OBJEXT) pdfencrypt.$(OBJEXT) pdfencoding.$(OBJEXT) \ + subfont.$(OBJEXT) type1c.$(OBJEXT) unicode.$(OBJEXT) libutil_a_OBJECTS = $(am_libutil_a_OBJECTS) @DVIPDFMX_TRUE@am__EXEEXT_1 = dvipdfmx$(EXEEXT) @XDVIPDFMX_TRUE@am__EXEEXT_2 = xdvipdfmx$(EXEEXT) @@ -166,78 +166,68 @@ AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = -am__objects_1 = dvipdfmx-agl.$(OBJEXT) dvipdfmx-bmpimage.$(OBJEXT) \ - dvipdfmx-cff.$(OBJEXT) dvipdfmx-cff_dict.$(OBJEXT) \ - dvipdfmx-cid.$(OBJEXT) dvipdfmx-cidtype2.$(OBJEXT) \ - dvipdfmx-cmap.$(OBJEXT) dvipdfmx-cmap_read.$(OBJEXT) \ - dvipdfmx-cmap_write.$(OBJEXT) dvipdfmx-dpxfile.$(OBJEXT) \ - dvipdfmx-dpxutil.$(OBJEXT) dvipdfmx-fontmap.$(OBJEXT) \ - dvipdfmx-mpost.$(OBJEXT) dvipdfmx-otl_conf.$(OBJEXT) \ - dvipdfmx-pdffont.$(OBJEXT) dvipdfmx-pdfparse.$(OBJEXT) \ - dvipdfmx-pdfresource.$(OBJEXT) dvipdfmx-pkfont.$(OBJEXT) \ +am_dvipdfmx_OBJECTS = dvipdfmx-agl.$(OBJEXT) \ + dvipdfmx-bmpimage.$(OBJEXT) dvipdfmx-cff.$(OBJEXT) \ + dvipdfmx-cff_dict.$(OBJEXT) dvipdfmx-cid.$(OBJEXT) \ + dvipdfmx-cidtype2.$(OBJEXT) dvipdfmx-cmap.$(OBJEXT) \ + dvipdfmx-cmap_read.$(OBJEXT) dvipdfmx-cmap_write.$(OBJEXT) \ + dvipdfmx-dpxfile.$(OBJEXT) dvipdfmx-dpxutil.$(OBJEXT) \ + dvipdfmx-dvi.$(OBJEXT) dvipdfmx-dvipdfmx.$(OBJEXT) \ + dvipdfmx-epdf.$(OBJEXT) dvipdfmx-fontmap.$(OBJEXT) \ + dvipdfmx-jpegimage.$(OBJEXT) dvipdfmx-mpost.$(OBJEXT) \ + dvipdfmx-otl_conf.$(OBJEXT) dvipdfmx-pdfcolor.$(OBJEXT) \ + dvipdfmx-pdfdev.$(OBJEXT) dvipdfmx-pdfdoc.$(OBJEXT) \ + dvipdfmx-pdfdraw.$(OBJEXT) dvipdfmx-pdffont.$(OBJEXT) \ + dvipdfmx-pdfnames.$(OBJEXT) dvipdfmx-pdfobj.$(OBJEXT) \ + dvipdfmx-pdfparse.$(OBJEXT) dvipdfmx-pdfresource.$(OBJEXT) \ + dvipdfmx-pdfximage.$(OBJEXT) dvipdfmx-pkfont.$(OBJEXT) \ dvipdfmx-pngimage.$(OBJEXT) dvipdfmx-pst.$(OBJEXT) \ dvipdfmx-pst_obj.$(OBJEXT) dvipdfmx-sfnt.$(OBJEXT) \ dvipdfmx-spc_color.$(OBJEXT) dvipdfmx-spc_dvips.$(OBJEXT) \ dvipdfmx-spc_html.$(OBJEXT) dvipdfmx-spc_misc.$(OBJEXT) \ - dvipdfmx-spc_util.$(OBJEXT) dvipdfmx-specials.$(OBJEXT) \ - dvipdfmx-t1_char.$(OBJEXT) dvipdfmx-t1_load.$(OBJEXT) \ - dvipdfmx-tfm.$(OBJEXT) dvipdfmx-truetype.$(OBJEXT) \ - dvipdfmx-tt_aux.$(OBJEXT) dvipdfmx-tt_glyf.$(OBJEXT) \ + dvipdfmx-spc_pdfm.$(OBJEXT) dvipdfmx-spc_tpic.$(OBJEXT) \ + dvipdfmx-spc_util.$(OBJEXT) dvipdfmx-spc_xtx.$(OBJEXT) \ + dvipdfmx-specials.$(OBJEXT) dvipdfmx-t1_char.$(OBJEXT) \ + dvipdfmx-t1_load.$(OBJEXT) dvipdfmx-tfm.$(OBJEXT) \ + dvipdfmx-truetype.$(OBJEXT) dvipdfmx-tt_aux.$(OBJEXT) \ + dvipdfmx-tt_cmap.$(OBJEXT) dvipdfmx-tt_glyf.$(OBJEXT) \ dvipdfmx-tt_gsub.$(OBJEXT) dvipdfmx-tt_post.$(OBJEXT) \ dvipdfmx-tt_table.$(OBJEXT) dvipdfmx-type0.$(OBJEXT) \ - dvipdfmx-type1.$(OBJEXT) dvipdfmx-vf.$(OBJEXT) -am__dirstamp = $(am__leading_dot)dirstamp -am__objects_2 = src/dvipdfmx-cidtype0.$(OBJEXT) \ - src/dvipdfmx-dvi.$(OBJEXT) src/dvipdfmx-dvipdfmx.$(OBJEXT) \ - src/dvipdfmx-epdf.$(OBJEXT) src/dvipdfmx-jpegimage.$(OBJEXT) \ - src/dvipdfmx-pdfcolor.$(OBJEXT) src/dvipdfmx-pdfdev.$(OBJEXT) \ - src/dvipdfmx-pdfdoc.$(OBJEXT) src/dvipdfmx-pdfdraw.$(OBJEXT) \ - src/dvipdfmx-pdfnames.$(OBJEXT) src/dvipdfmx-pdfobj.$(OBJEXT) \ - src/dvipdfmx-pdfximage.$(OBJEXT) \ - src/dvipdfmx-spc_pdfm.$(OBJEXT) \ - src/dvipdfmx-spc_tpic.$(OBJEXT) src/dvipdfmx-tt_cmap.$(OBJEXT) \ - src/dvipdfmx-type1c.$(OBJEXT) src/dvipdfmx-xbb.$(OBJEXT) -nodist_dvipdfmx_OBJECTS = $(am__objects_1) $(am__objects_2) -dvipdfmx_OBJECTS = $(nodist_dvipdfmx_OBJECTS) + dvipdfmx-type1.$(OBJEXT) dvipdfmx-vf.$(OBJEXT) \ + dvipdfmx-xbb.$(OBJEXT) +dvipdfmx_OBJECTS = $(am_dvipdfmx_OBJECTS) am__DEPENDENCIES_1 = dvipdfmx_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) libutil.a -am__objects_3 = xdvipdfmx-agl.$(OBJEXT) xdvipdfmx-bmpimage.$(OBJEXT) \ +am__objects_1 = xdvipdfmx-agl.$(OBJEXT) xdvipdfmx-bmpimage.$(OBJEXT) \ xdvipdfmx-cff.$(OBJEXT) xdvipdfmx-cff_dict.$(OBJEXT) \ xdvipdfmx-cid.$(OBJEXT) xdvipdfmx-cidtype2.$(OBJEXT) \ xdvipdfmx-cmap.$(OBJEXT) xdvipdfmx-cmap_read.$(OBJEXT) \ xdvipdfmx-cmap_write.$(OBJEXT) xdvipdfmx-dpxfile.$(OBJEXT) \ - xdvipdfmx-dpxutil.$(OBJEXT) xdvipdfmx-fontmap.$(OBJEXT) \ + xdvipdfmx-dpxutil.$(OBJEXT) xdvipdfmx-dvi.$(OBJEXT) \ + xdvipdfmx-dvipdfmx.$(OBJEXT) xdvipdfmx-epdf.$(OBJEXT) \ + xdvipdfmx-fontmap.$(OBJEXT) xdvipdfmx-jpegimage.$(OBJEXT) \ xdvipdfmx-mpost.$(OBJEXT) xdvipdfmx-otl_conf.$(OBJEXT) \ - xdvipdfmx-pdffont.$(OBJEXT) xdvipdfmx-pdfparse.$(OBJEXT) \ - xdvipdfmx-pdfresource.$(OBJEXT) xdvipdfmx-pkfont.$(OBJEXT) \ - xdvipdfmx-pngimage.$(OBJEXT) xdvipdfmx-pst.$(OBJEXT) \ - xdvipdfmx-pst_obj.$(OBJEXT) xdvipdfmx-sfnt.$(OBJEXT) \ - xdvipdfmx-spc_color.$(OBJEXT) xdvipdfmx-spc_dvips.$(OBJEXT) \ - xdvipdfmx-spc_html.$(OBJEXT) xdvipdfmx-spc_misc.$(OBJEXT) \ - xdvipdfmx-spc_util.$(OBJEXT) xdvipdfmx-specials.$(OBJEXT) \ + xdvipdfmx-pdfcolor.$(OBJEXT) xdvipdfmx-pdfdev.$(OBJEXT) \ + xdvipdfmx-pdfdoc.$(OBJEXT) xdvipdfmx-pdfdraw.$(OBJEXT) \ + xdvipdfmx-pdffont.$(OBJEXT) xdvipdfmx-pdfnames.$(OBJEXT) \ + xdvipdfmx-pdfobj.$(OBJEXT) xdvipdfmx-pdfparse.$(OBJEXT) \ + xdvipdfmx-pdfresource.$(OBJEXT) xdvipdfmx-pdfximage.$(OBJEXT) \ + xdvipdfmx-pkfont.$(OBJEXT) xdvipdfmx-pngimage.$(OBJEXT) \ + xdvipdfmx-pst.$(OBJEXT) xdvipdfmx-pst_obj.$(OBJEXT) \ + xdvipdfmx-sfnt.$(OBJEXT) xdvipdfmx-spc_color.$(OBJEXT) \ + xdvipdfmx-spc_dvips.$(OBJEXT) xdvipdfmx-spc_html.$(OBJEXT) \ + xdvipdfmx-spc_misc.$(OBJEXT) xdvipdfmx-spc_pdfm.$(OBJEXT) \ + xdvipdfmx-spc_tpic.$(OBJEXT) xdvipdfmx-spc_util.$(OBJEXT) \ + xdvipdfmx-spc_xtx.$(OBJEXT) xdvipdfmx-specials.$(OBJEXT) \ xdvipdfmx-t1_char.$(OBJEXT) xdvipdfmx-t1_load.$(OBJEXT) \ xdvipdfmx-tfm.$(OBJEXT) xdvipdfmx-truetype.$(OBJEXT) \ - xdvipdfmx-tt_aux.$(OBJEXT) xdvipdfmx-tt_glyf.$(OBJEXT) \ - xdvipdfmx-tt_gsub.$(OBJEXT) xdvipdfmx-tt_post.$(OBJEXT) \ - xdvipdfmx-tt_table.$(OBJEXT) xdvipdfmx-type0.$(OBJEXT) \ - xdvipdfmx-type1.$(OBJEXT) xdvipdfmx-vf.$(OBJEXT) -am__objects_4 = xsrc/xdvipdfmx-cidtype0.$(OBJEXT) \ - xsrc/xdvipdfmx-dvi.$(OBJEXT) xsrc/xdvipdfmx-dvipdfmx.$(OBJEXT) \ - xsrc/xdvipdfmx-epdf.$(OBJEXT) \ - xsrc/xdvipdfmx-jpegimage.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfcolor.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfdev.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfdoc.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfdraw.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfnames.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfobj.$(OBJEXT) \ - xsrc/xdvipdfmx-pdfximage.$(OBJEXT) \ - xsrc/xdvipdfmx-spc_pdfm.$(OBJEXT) \ - xsrc/xdvipdfmx-spc_tpic.$(OBJEXT) xdvipdfmx-spc_xtx.$(OBJEXT) \ - xsrc/xdvipdfmx-tt_cmap.$(OBJEXT) \ - xsrc/xdvipdfmx-type1c.$(OBJEXT) xsrc/xdvipdfmx-xbb.$(OBJEXT) -nodist_xdvipdfmx_OBJECTS = $(am__objects_3) $(am__objects_4) + xdvipdfmx-tt_aux.$(OBJEXT) xdvipdfmx-tt_cmap.$(OBJEXT) \ + xdvipdfmx-tt_glyf.$(OBJEXT) xdvipdfmx-tt_gsub.$(OBJEXT) \ + xdvipdfmx-tt_post.$(OBJEXT) xdvipdfmx-tt_table.$(OBJEXT) \ + xdvipdfmx-type0.$(OBJEXT) xdvipdfmx-type1.$(OBJEXT) \ + xdvipdfmx-vf.$(OBJEXT) xdvipdfmx-xbb.$(OBJEXT) +nodist_xdvipdfmx_OBJECTS = $(am__objects_1) xdvipdfmx_OBJECTS = $(nodist_xdvipdfmx_OBJECTS) am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) libutil.a @@ -306,8 +296,8 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libutil_a_SOURCES) $(nodist_call_dvipdfmx_SOURCES) \ - $(nodist_dvipdfmx_SOURCES) $(nodist_xdvipdfmx_SOURCES) -DIST_SOURCES = $(libutil_a_SOURCES) + $(dvipdfmx_SOURCES) $(nodist_xdvipdfmx_SOURCES) +DIST_SOURCES = $(libutil_a_SOURCES) $(dvipdfmx_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -671,190 +661,160 @@ dvipdfmx_CPPFLAGS = -I$(srcdir)/src $(common_cppflags) xdvipdfmx_CPPFLAGS = -DXETEX -I$(srcdir)/xsrc $(FREETYPE2_INCLUDES) $(common_cppflags) AM_CFLAGS = $(WARNING_CFLAGS) libutil_a_SOURCES = \ + agl.h \ + bmpimage.h \ + cff_dict.h \ + cff_limits.h \ + cff_stdstr.h \ + cff_types.h \ + cid_basefont.h \ + cidtype0.c \ + cidtype0.h \ + cidtype2.h \ + cmap.h \ + cmap_p.h \ + cmap_read.h \ + cmap_write.h \ cs_type2.c \ cs_type2.h \ dpxconf.c \ dpxconf.h \ dpxcrypt.c \ dpxcrypt.h \ + dpxfile.h \ + dpxutil.h \ + dvi.h \ + dvicodes.h \ + dvipdfmx.h \ + epdf.h \ error.c \ error.h \ + jpegimage.h \ mem.c \ mem.h \ mfileio.c \ mfileio.h \ + mpost.h \ numbers.c \ numbers.h \ + otl_conf.h \ otl_opt.c \ otl_opt.h \ + pdfcolor.h \ + pdfdev.h \ + pdfdoc.h \ pdfencrypt.c \ pdfencrypt.h \ pdfencoding.c \ pdfencoding.h \ + pdflimits.h \ + pdfnames.h \ + pdfobj.h \ + pdfparse.h \ + pdfresource.h \ + pdfximage.h \ + pkfont.h \ + pngimage.h \ + pst.h \ + pst_obj.h \ + spc_color.h \ + spc_dvips.h \ + spc_html.h \ + spc_misc.h \ + spc_pdfm.h \ + spc_tpic.h \ + spc_util.h \ + specials.h \ subfont.c \ subfont.h \ system.h \ + t1_char.h \ + t1_load.h \ + tfm.h \ + truetype.h \ + tt_aux.h \ + tt_glyf.h \ + tt_gsub.h \ + tt_post.h \ + tt_table.h \ + type1.h \ + type1c.c \ + type1c.h \ unicode.c \ - unicode.h + unicode.h \ + vf.h -nodist_dvipdfmx_SOURCES = $(common_sources) $(dvipdfmx_sources) -nodist_xdvipdfmx_SOURCES = $(common_sources) $(xdvipdfmx_sources) -dvipdfmx_LDADD = $(KPATHSEA_LIBS) $(LIBPNG_LIBS) $(ZLIB_LIBS) libutil.a -xdvipdfmx_LDADD = $(FREETYPE2_LIBS) $(dvipdfmx_LDADD) -common_sources = \ +dvipdfmx_SOURCES = \ agl.c \ - agl.h \ bmpimage.c \ - bmpimage.h \ cff.c \ cff.h \ cff_dict.c \ - cff_dict.h \ - cff_limits.h \ - cff_stdstr.h \ - cff_types.h \ cid.c \ cid.h \ - cid_basefont.h \ cid_p.h \ - cidtype0.h \ cidtype2.c \ - cidtype2.h \ cmap.c \ - cmap.h \ - cmap_p.h \ cmap_read.c \ - cmap_read.h \ cmap_write.c \ - cmap_write.h \ dpxfile.c \ - dpxfile.h \ dpxutil.c \ - dpxutil.h \ - dvi.h \ - dvicodes.h \ - dvipdfmx.h \ - epdf.h \ + dvi.c \ + dvipdfmx.c \ + epdf.c \ fontmap.c \ fontmap.h \ - jpegimage.h \ + jpegimage.c \ mpost.c \ - mpost.h \ otl_conf.c \ - otl_conf.h \ - pdfcolor.h \ - pdfdev.h \ - pdfdoc.h \ + pdfcolor.c \ + pdfdev.c \ + pdfdoc.c \ + pdfdraw.c \ pdfdraw.h \ pdffont.c \ pdffont.h \ - pdflimits.h \ - pdfnames.h \ - pdfobj.h \ + pdfnames.c \ + pdfobj.c \ pdfparse.c \ - pdfparse.h \ pdfresource.c \ - pdfresource.h \ - pdfximage.h \ + pdfximage.c \ pkfont.c \ - pkfont.h \ pngimage.c \ - pngimage.h \ pst.c \ - pst.h \ pst_obj.c \ - pst_obj.h \ sfnt.c \ sfnt.h \ spc_color.c \ - spc_color.h \ spc_dvips.c \ - spc_dvips.h \ spc_html.c \ - spc_html.h \ spc_misc.c \ - spc_misc.h \ - spc_pdfm.h \ - spc_tpic.h \ + spc_pdfm.c \ + spc_tpic.c \ spc_util.c \ - spc_util.h \ + spc_xtx.c \ + spc_xtx.h \ specials.c \ - specials.h \ t1_char.c \ - t1_char.h \ t1_load.c \ - t1_load.h \ tfm.c \ - tfm.h \ truetype.c \ - truetype.h \ tt_aux.c \ - tt_aux.h \ + tt_cmap.c \ tt_cmap.h \ tt_glyf.c \ - tt_glyf.h \ tt_gsub.c \ - tt_gsub.h \ tt_post.c \ - tt_post.h \ tt_table.c \ - tt_table.h \ type0.c \ type0.h \ type1.c \ - type1.h \ - type1c.h \ vf.c \ - vf.h + xbb.c -dvipdfmx_sources = \ - src/cidtype0.c \ - src/dvi.c \ - src/dvipdfmx.c \ - src/epdf.c \ - src/jpegimage.c \ - src/pdfcolor.c \ - src/pdfdev.c \ - src/pdfdoc.c \ - src/pdfdraw.c \ - src/pdfnames.c \ - src/pdfobj.c \ - src/pdfximage.c \ - src/spc_pdfm.c \ - src/spc_tpic.c \ - src/tt_cmap.c \ - src/type1c.c \ - src/xbb.c - -xdvipdfmx_sources = \ - xsrc/cidtype0.c \ - xsrc/dvi.c \ - xsrc/dvipdfmx.c \ - xsrc/epdf.c \ - xsrc/jpegimage.c \ - xsrc/pdfcolor.c \ - xsrc/pdfdev.c \ - xsrc/pdfdoc.c \ - xsrc/pdfdraw.c \ - xsrc/pdfnames.c \ - xsrc/pdfobj.c \ - xsrc/pdfximage.c \ - xsrc/spc_pdfm.c \ - xsrc/spc_tpic.c \ - spc_xtx.c \ - spc_xtx.h \ - xsrc/tt_cmap.c \ - xsrc/type1c.c \ - xsrc/xbb.c - -EXTRA_DIST = $(common_sources) $(dvipdfmx_sources) \ - $(xdvipdfmx_sources) $(dvipdfmx_tests) $(xdvipdfmx_tests) \ - tests/dvipdfmx.cfg tests/image.jpeg tests/imgjpeg.bb \ - tests/imgjpeg.xbb tests/picjpeg.bb tests/picjpeg.xbb \ - tests/image.pdf tests/imgpdf.bb tests/imgpdf.xbb \ - tests/picpdf.bb tests/picpdf.xbb tests/image.png \ - tests/imgpng.bb tests/imgpng.xbb tests/picpng.bb \ - tests/picpng.xbb +nodist_xdvipdfmx_SOURCES = $(dvipdfmx_SOURCES) +dvipdfmx_LDADD = $(KPATHSEA_LIBS) $(LIBPNG_LIBS) $(ZLIB_LIBS) libutil.a +xdvipdfmx_LDADD = $(FREETYPE2_LIBS) $(dvipdfmx_LDADD) bin_links = $(am__append_3) call_dvipdfmx_CPPFLAGS = -DEXEPROG=\"dvipdfmx.exe\" nodist_call_dvipdfmx_SOURCES = callexe.c @@ -875,6 +835,12 @@ DISTCLEANFILES = config.force img*.* pic*.* TESTS = $(am__append_5) $(am__append_6) dvipdfmx_tests = dvipdfmx.test dvipdfm-bb.test xdvipdfmx_tests = xdvipdfmx.test xdvipdfm-bb.test +EXTRA_DIST = $(dvipdfmx_tests) $(xdvipdfmx_tests) tests/dvipdfmx.cfg \ + tests/image.jpeg tests/imgjpeg.bb tests/imgjpeg.xbb \ + tests/picjpeg.bb tests/picjpeg.xbb tests/image.pdf \ + tests/imgpdf.bb tests/imgpdf.xbb tests/picpdf.bb \ + tests/picpdf.xbb tests/image.png tests/imgpng.bb \ + tests/imgpng.xbb tests/picpng.bb tests/picpng.xbb all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -997,90 +963,10 @@ clean-noinstPROGRAMS: call_dvipdfmx$(EXEEXT): $(call_dvipdfmx_OBJECTS) $(call_dvipdfmx_DEPENDENCIES) $(EXTRA_call_dvipdfmx_DEPENDENCIES) @rm -f call_dvipdfmx$(EXEEXT) $(AM_V_CCLD)$(LINK) $(call_dvipdfmx_OBJECTS) $(call_dvipdfmx_LDADD) $(LIBS) -src/$(am__dirstamp): - @$(MKDIR_P) src - @: > src/$(am__dirstamp) -src/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/$(DEPDIR) - @: > src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-cidtype0.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-dvi.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-dvipdfmx.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-epdf.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-jpegimage.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfcolor.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfdev.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfdoc.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfdraw.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfnames.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfobj.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-pdfximage.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-spc_pdfm.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-spc_tpic.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-tt_cmap.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-type1c.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) -src/dvipdfmx-xbb.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) dvipdfmx$(EXEEXT): $(dvipdfmx_OBJECTS) $(dvipdfmx_DEPENDENCIES) $(EXTRA_dvipdfmx_DEPENDENCIES) @rm -f dvipdfmx$(EXEEXT) $(AM_V_CCLD)$(LINK) $(dvipdfmx_OBJECTS) $(dvipdfmx_LDADD) $(LIBS) -xsrc/$(am__dirstamp): - @$(MKDIR_P) xsrc - @: > xsrc/$(am__dirstamp) -xsrc/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) xsrc/$(DEPDIR) - @: > xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-cidtype0.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-dvi.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-dvipdfmx.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-epdf.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-jpegimage.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfcolor.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfdev.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfdoc.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfdraw.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfnames.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfobj.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-pdfximage.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-spc_pdfm.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-spc_tpic.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-tt_cmap.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-type1c.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) -xsrc/xdvipdfmx-xbb.$(OBJEXT): xsrc/$(am__dirstamp) \ - xsrc/$(DEPDIR)/$(am__dirstamp) xdvipdfmx$(EXEEXT): $(xdvipdfmx_OBJECTS) $(xdvipdfmx_DEPENDENCIES) $(EXTRA_xdvipdfmx_DEPENDENCIES) @rm -f xdvipdfmx$(EXEEXT) @@ -1123,13 +1009,12 @@ uninstall-dist_binSCRIPTS: mostlyclean-compile: -rm -f *.$(OBJEXT) - -rm -f src/*.$(OBJEXT) - -rm -f xsrc/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call_dvipdfmx-callexe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cidtype0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cs_type2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpxconf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpxcrypt.Po@am__quote@ @@ -1144,12 +1029,23 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-cmap_write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-dpxfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-dpxutil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-dvi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-dvipdfmx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-epdf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-fontmap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-jpegimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-mpost.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-otl_conf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfcolor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfdev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfdoc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfdraw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdffont.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfnames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfobj.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfresource.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pdfximage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pkfont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pngimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-pst.Po@am__quote@ @@ -1159,13 +1055,17 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_dvips.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_html.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_pdfm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_tpic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-spc_xtx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-specials.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-t1_char.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-t1_load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tfm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-truetype.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tt_aux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tt_cmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tt_glyf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tt_gsub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-tt_post.Po@am__quote@ @@ -1173,6 +1073,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-type0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-type1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-vf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dvipdfmx-xbb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfileio.Po@am__quote@ @@ -1181,6 +1082,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdfencoding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdfencrypt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subfont.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/type1c.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unicode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-agl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-bmpimage.Po@am__quote@ @@ -1193,12 +1095,23 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-cmap_write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-dpxfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-dpxutil.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-dvi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-dvipdfmx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-epdf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-fontmap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-jpegimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-mpost.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-otl_conf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfcolor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfdev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfdoc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfdraw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdffont.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfnames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfobj.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfresource.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pdfximage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pkfont.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pngimage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-pst.Po@am__quote@ @@ -1208,6 +1121,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_dvips.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_html.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_pdfm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_tpic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-spc_xtx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-specials.Po@am__quote@ @@ -1216,6 +1131,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tfm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-truetype.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tt_aux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tt_cmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tt_glyf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tt_gsub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-tt_post.Po@am__quote@ @@ -1223,40 +1139,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-type0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-type1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-vf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-cidtype0.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-dvi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-dvipdfmx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-epdf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-jpegimage.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfcolor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfdev.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfdoc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfdraw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfnames.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfobj.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-pdfximage.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-spc_pdfm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-spc_tpic.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-tt_cmap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-type1c.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dvipdfmx-xbb.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-dvi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-epdf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-type1c.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@xsrc/$(DEPDIR)/xdvipdfmx-xbb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdvipdfmx-xbb.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @@ -1450,6 +1333,48 @@ dvipdfmx-dpxutil.obj: dpxutil.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-dpxutil.obj `if test -f 'dpxutil.c'; then $(CYGPATH_W) 'dpxutil.c'; else $(CYGPATH_W) '$(srcdir)/dpxutil.c'; fi` +dvipdfmx-dvi.o: dvi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-dvi.o -MD -MP -MF $(DEPDIR)/dvipdfmx-dvi.Tpo -c -o dvipdfmx-dvi.o `test -f 'dvi.c' || echo '$(srcdir)/'`dvi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-dvi.Tpo $(DEPDIR)/dvipdfmx-dvi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvi.c' object='dvipdfmx-dvi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-dvi.o `test -f 'dvi.c' || echo '$(srcdir)/'`dvi.c + +dvipdfmx-dvi.obj: dvi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-dvi.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-dvi.Tpo -c -o dvipdfmx-dvi.obj `if test -f 'dvi.c'; then $(CYGPATH_W) 'dvi.c'; else $(CYGPATH_W) '$(srcdir)/dvi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-dvi.Tpo $(DEPDIR)/dvipdfmx-dvi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvi.c' object='dvipdfmx-dvi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-dvi.obj `if test -f 'dvi.c'; then $(CYGPATH_W) 'dvi.c'; else $(CYGPATH_W) '$(srcdir)/dvi.c'; fi` + +dvipdfmx-dvipdfmx.o: dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-dvipdfmx.o -MD -MP -MF $(DEPDIR)/dvipdfmx-dvipdfmx.Tpo -c -o dvipdfmx-dvipdfmx.o `test -f 'dvipdfmx.c' || echo '$(srcdir)/'`dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-dvipdfmx.Tpo $(DEPDIR)/dvipdfmx-dvipdfmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvipdfmx.c' object='dvipdfmx-dvipdfmx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-dvipdfmx.o `test -f 'dvipdfmx.c' || echo '$(srcdir)/'`dvipdfmx.c + +dvipdfmx-dvipdfmx.obj: dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-dvipdfmx.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-dvipdfmx.Tpo -c -o dvipdfmx-dvipdfmx.obj `if test -f 'dvipdfmx.c'; then $(CYGPATH_W) 'dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/dvipdfmx.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-dvipdfmx.Tpo $(DEPDIR)/dvipdfmx-dvipdfmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvipdfmx.c' object='dvipdfmx-dvipdfmx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-dvipdfmx.obj `if test -f 'dvipdfmx.c'; then $(CYGPATH_W) 'dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/dvipdfmx.c'; fi` + +dvipdfmx-epdf.o: epdf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-epdf.o -MD -MP -MF $(DEPDIR)/dvipdfmx-epdf.Tpo -c -o dvipdfmx-epdf.o `test -f 'epdf.c' || echo '$(srcdir)/'`epdf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-epdf.Tpo $(DEPDIR)/dvipdfmx-epdf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epdf.c' object='dvipdfmx-epdf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-epdf.o `test -f 'epdf.c' || echo '$(srcdir)/'`epdf.c + +dvipdfmx-epdf.obj: epdf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-epdf.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-epdf.Tpo -c -o dvipdfmx-epdf.obj `if test -f 'epdf.c'; then $(CYGPATH_W) 'epdf.c'; else $(CYGPATH_W) '$(srcdir)/epdf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-epdf.Tpo $(DEPDIR)/dvipdfmx-epdf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epdf.c' object='dvipdfmx-epdf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-epdf.obj `if test -f 'epdf.c'; then $(CYGPATH_W) 'epdf.c'; else $(CYGPATH_W) '$(srcdir)/epdf.c'; fi` + dvipdfmx-fontmap.o: fontmap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-fontmap.o -MD -MP -MF $(DEPDIR)/dvipdfmx-fontmap.Tpo -c -o dvipdfmx-fontmap.o `test -f 'fontmap.c' || echo '$(srcdir)/'`fontmap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-fontmap.Tpo $(DEPDIR)/dvipdfmx-fontmap.Po @@ -1464,6 +1389,20 @@ dvipdfmx-fontmap.obj: fontmap.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-fontmap.obj `if test -f 'fontmap.c'; then $(CYGPATH_W) 'fontmap.c'; else $(CYGPATH_W) '$(srcdir)/fontmap.c'; fi` +dvipdfmx-jpegimage.o: jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-jpegimage.o -MD -MP -MF $(DEPDIR)/dvipdfmx-jpegimage.Tpo -c -o dvipdfmx-jpegimage.o `test -f 'jpegimage.c' || echo '$(srcdir)/'`jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-jpegimage.Tpo $(DEPDIR)/dvipdfmx-jpegimage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpegimage.c' object='dvipdfmx-jpegimage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-jpegimage.o `test -f 'jpegimage.c' || echo '$(srcdir)/'`jpegimage.c + +dvipdfmx-jpegimage.obj: jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-jpegimage.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-jpegimage.Tpo -c -o dvipdfmx-jpegimage.obj `if test -f 'jpegimage.c'; then $(CYGPATH_W) 'jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/jpegimage.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-jpegimage.Tpo $(DEPDIR)/dvipdfmx-jpegimage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpegimage.c' object='dvipdfmx-jpegimage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-jpegimage.obj `if test -f 'jpegimage.c'; then $(CYGPATH_W) 'jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/jpegimage.c'; fi` + dvipdfmx-mpost.o: mpost.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-mpost.o -MD -MP -MF $(DEPDIR)/dvipdfmx-mpost.Tpo -c -o dvipdfmx-mpost.o `test -f 'mpost.c' || echo '$(srcdir)/'`mpost.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-mpost.Tpo $(DEPDIR)/dvipdfmx-mpost.Po @@ -1492,6 +1431,62 @@ dvipdfmx-otl_conf.obj: otl_conf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-otl_conf.obj `if test -f 'otl_conf.c'; then $(CYGPATH_W) 'otl_conf.c'; else $(CYGPATH_W) '$(srcdir)/otl_conf.c'; fi` +dvipdfmx-pdfcolor.o: pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfcolor.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfcolor.Tpo -c -o dvipdfmx-pdfcolor.o `test -f 'pdfcolor.c' || echo '$(srcdir)/'`pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfcolor.Tpo $(DEPDIR)/dvipdfmx-pdfcolor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfcolor.c' object='dvipdfmx-pdfcolor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfcolor.o `test -f 'pdfcolor.c' || echo '$(srcdir)/'`pdfcolor.c + +dvipdfmx-pdfcolor.obj: pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfcolor.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfcolor.Tpo -c -o dvipdfmx-pdfcolor.obj `if test -f 'pdfcolor.c'; then $(CYGPATH_W) 'pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/pdfcolor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfcolor.Tpo $(DEPDIR)/dvipdfmx-pdfcolor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfcolor.c' object='dvipdfmx-pdfcolor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfcolor.obj `if test -f 'pdfcolor.c'; then $(CYGPATH_W) 'pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/pdfcolor.c'; fi` + +dvipdfmx-pdfdev.o: pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdev.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdev.Tpo -c -o dvipdfmx-pdfdev.o `test -f 'pdfdev.c' || echo '$(srcdir)/'`pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdev.Tpo $(DEPDIR)/dvipdfmx-pdfdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdev.c' object='dvipdfmx-pdfdev.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdev.o `test -f 'pdfdev.c' || echo '$(srcdir)/'`pdfdev.c + +dvipdfmx-pdfdev.obj: pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdev.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdev.Tpo -c -o dvipdfmx-pdfdev.obj `if test -f 'pdfdev.c'; then $(CYGPATH_W) 'pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/pdfdev.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdev.Tpo $(DEPDIR)/dvipdfmx-pdfdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdev.c' object='dvipdfmx-pdfdev.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdev.obj `if test -f 'pdfdev.c'; then $(CYGPATH_W) 'pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/pdfdev.c'; fi` + +dvipdfmx-pdfdoc.o: pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdoc.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdoc.Tpo -c -o dvipdfmx-pdfdoc.o `test -f 'pdfdoc.c' || echo '$(srcdir)/'`pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdoc.Tpo $(DEPDIR)/dvipdfmx-pdfdoc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdoc.c' object='dvipdfmx-pdfdoc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdoc.o `test -f 'pdfdoc.c' || echo '$(srcdir)/'`pdfdoc.c + +dvipdfmx-pdfdoc.obj: pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdoc.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdoc.Tpo -c -o dvipdfmx-pdfdoc.obj `if test -f 'pdfdoc.c'; then $(CYGPATH_W) 'pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/pdfdoc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdoc.Tpo $(DEPDIR)/dvipdfmx-pdfdoc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdoc.c' object='dvipdfmx-pdfdoc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdoc.obj `if test -f 'pdfdoc.c'; then $(CYGPATH_W) 'pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/pdfdoc.c'; fi` + +dvipdfmx-pdfdraw.o: pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdraw.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdraw.Tpo -c -o dvipdfmx-pdfdraw.o `test -f 'pdfdraw.c' || echo '$(srcdir)/'`pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdraw.Tpo $(DEPDIR)/dvipdfmx-pdfdraw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdraw.c' object='dvipdfmx-pdfdraw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdraw.o `test -f 'pdfdraw.c' || echo '$(srcdir)/'`pdfdraw.c + +dvipdfmx-pdfdraw.obj: pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfdraw.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfdraw.Tpo -c -o dvipdfmx-pdfdraw.obj `if test -f 'pdfdraw.c'; then $(CYGPATH_W) 'pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/pdfdraw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfdraw.Tpo $(DEPDIR)/dvipdfmx-pdfdraw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdraw.c' object='dvipdfmx-pdfdraw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfdraw.obj `if test -f 'pdfdraw.c'; then $(CYGPATH_W) 'pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/pdfdraw.c'; fi` + dvipdfmx-pdffont.o: pdffont.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdffont.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdffont.Tpo -c -o dvipdfmx-pdffont.o `test -f 'pdffont.c' || echo '$(srcdir)/'`pdffont.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdffont.Tpo $(DEPDIR)/dvipdfmx-pdffont.Po @@ -1506,6 +1501,34 @@ dvipdfmx-pdffont.obj: pdffont.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdffont.obj `if test -f 'pdffont.c'; then $(CYGPATH_W) 'pdffont.c'; else $(CYGPATH_W) '$(srcdir)/pdffont.c'; fi` +dvipdfmx-pdfnames.o: pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfnames.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfnames.Tpo -c -o dvipdfmx-pdfnames.o `test -f 'pdfnames.c' || echo '$(srcdir)/'`pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfnames.Tpo $(DEPDIR)/dvipdfmx-pdfnames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfnames.c' object='dvipdfmx-pdfnames.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfnames.o `test -f 'pdfnames.c' || echo '$(srcdir)/'`pdfnames.c + +dvipdfmx-pdfnames.obj: pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfnames.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfnames.Tpo -c -o dvipdfmx-pdfnames.obj `if test -f 'pdfnames.c'; then $(CYGPATH_W) 'pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/pdfnames.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfnames.Tpo $(DEPDIR)/dvipdfmx-pdfnames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfnames.c' object='dvipdfmx-pdfnames.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfnames.obj `if test -f 'pdfnames.c'; then $(CYGPATH_W) 'pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/pdfnames.c'; fi` + +dvipdfmx-pdfobj.o: pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfobj.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfobj.Tpo -c -o dvipdfmx-pdfobj.o `test -f 'pdfobj.c' || echo '$(srcdir)/'`pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfobj.Tpo $(DEPDIR)/dvipdfmx-pdfobj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfobj.c' object='dvipdfmx-pdfobj.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfobj.o `test -f 'pdfobj.c' || echo '$(srcdir)/'`pdfobj.c + +dvipdfmx-pdfobj.obj: pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfobj.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfobj.Tpo -c -o dvipdfmx-pdfobj.obj `if test -f 'pdfobj.c'; then $(CYGPATH_W) 'pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/pdfobj.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfobj.Tpo $(DEPDIR)/dvipdfmx-pdfobj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfobj.c' object='dvipdfmx-pdfobj.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfobj.obj `if test -f 'pdfobj.c'; then $(CYGPATH_W) 'pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/pdfobj.c'; fi` + dvipdfmx-pdfparse.o: pdfparse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfparse.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfparse.Tpo -c -o dvipdfmx-pdfparse.o `test -f 'pdfparse.c' || echo '$(srcdir)/'`pdfparse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfparse.Tpo $(DEPDIR)/dvipdfmx-pdfparse.Po @@ -1534,6 +1557,20 @@ dvipdfmx-pdfresource.obj: pdfresource.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfresource.obj `if test -f 'pdfresource.c'; then $(CYGPATH_W) 'pdfresource.c'; else $(CYGPATH_W) '$(srcdir)/pdfresource.c'; fi` +dvipdfmx-pdfximage.o: pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfximage.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfximage.Tpo -c -o dvipdfmx-pdfximage.o `test -f 'pdfximage.c' || echo '$(srcdir)/'`pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfximage.Tpo $(DEPDIR)/dvipdfmx-pdfximage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfximage.c' object='dvipdfmx-pdfximage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfximage.o `test -f 'pdfximage.c' || echo '$(srcdir)/'`pdfximage.c + +dvipdfmx-pdfximage.obj: pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pdfximage.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-pdfximage.Tpo -c -o dvipdfmx-pdfximage.obj `if test -f 'pdfximage.c'; then $(CYGPATH_W) 'pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/pdfximage.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pdfximage.Tpo $(DEPDIR)/dvipdfmx-pdfximage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfximage.c' object='dvipdfmx-pdfximage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-pdfximage.obj `if test -f 'pdfximage.c'; then $(CYGPATH_W) 'pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/pdfximage.c'; fi` + dvipdfmx-pkfont.o: pkfont.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-pkfont.o -MD -MP -MF $(DEPDIR)/dvipdfmx-pkfont.Tpo -c -o dvipdfmx-pkfont.o `test -f 'pkfont.c' || echo '$(srcdir)/'`pkfont.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-pkfont.Tpo $(DEPDIR)/dvipdfmx-pkfont.Po @@ -1660,6 +1697,34 @@ dvipdfmx-spc_misc.obj: spc_misc.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_misc.obj `if test -f 'spc_misc.c'; then $(CYGPATH_W) 'spc_misc.c'; else $(CYGPATH_W) '$(srcdir)/spc_misc.c'; fi` +dvipdfmx-spc_pdfm.o: spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_pdfm.o -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_pdfm.Tpo -c -o dvipdfmx-spc_pdfm.o `test -f 'spc_pdfm.c' || echo '$(srcdir)/'`spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_pdfm.Tpo $(DEPDIR)/dvipdfmx-spc_pdfm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_pdfm.c' object='dvipdfmx-spc_pdfm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_pdfm.o `test -f 'spc_pdfm.c' || echo '$(srcdir)/'`spc_pdfm.c + +dvipdfmx-spc_pdfm.obj: spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_pdfm.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_pdfm.Tpo -c -o dvipdfmx-spc_pdfm.obj `if test -f 'spc_pdfm.c'; then $(CYGPATH_W) 'spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/spc_pdfm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_pdfm.Tpo $(DEPDIR)/dvipdfmx-spc_pdfm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_pdfm.c' object='dvipdfmx-spc_pdfm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_pdfm.obj `if test -f 'spc_pdfm.c'; then $(CYGPATH_W) 'spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/spc_pdfm.c'; fi` + +dvipdfmx-spc_tpic.o: spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_tpic.o -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_tpic.Tpo -c -o dvipdfmx-spc_tpic.o `test -f 'spc_tpic.c' || echo '$(srcdir)/'`spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_tpic.Tpo $(DEPDIR)/dvipdfmx-spc_tpic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_tpic.c' object='dvipdfmx-spc_tpic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_tpic.o `test -f 'spc_tpic.c' || echo '$(srcdir)/'`spc_tpic.c + +dvipdfmx-spc_tpic.obj: spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_tpic.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_tpic.Tpo -c -o dvipdfmx-spc_tpic.obj `if test -f 'spc_tpic.c'; then $(CYGPATH_W) 'spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/spc_tpic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_tpic.Tpo $(DEPDIR)/dvipdfmx-spc_tpic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_tpic.c' object='dvipdfmx-spc_tpic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_tpic.obj `if test -f 'spc_tpic.c'; then $(CYGPATH_W) 'spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/spc_tpic.c'; fi` + dvipdfmx-spc_util.o: spc_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_util.o -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_util.Tpo -c -o dvipdfmx-spc_util.o `test -f 'spc_util.c' || echo '$(srcdir)/'`spc_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_util.Tpo $(DEPDIR)/dvipdfmx-spc_util.Po @@ -1674,6 +1739,20 @@ dvipdfmx-spc_util.obj: spc_util.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_util.obj `if test -f 'spc_util.c'; then $(CYGPATH_W) 'spc_util.c'; else $(CYGPATH_W) '$(srcdir)/spc_util.c'; fi` +dvipdfmx-spc_xtx.o: spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_xtx.o -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_xtx.Tpo -c -o dvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_xtx.Tpo $(DEPDIR)/dvipdfmx-spc_xtx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='dvipdfmx-spc_xtx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c + +dvipdfmx-spc_xtx.obj: spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-spc_xtx.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-spc_xtx.Tpo -c -o dvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-spc_xtx.Tpo $(DEPDIR)/dvipdfmx-spc_xtx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='dvipdfmx-spc_xtx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` + dvipdfmx-specials.o: specials.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-specials.o -MD -MP -MF $(DEPDIR)/dvipdfmx-specials.Tpo -c -o dvipdfmx-specials.o `test -f 'specials.c' || echo '$(srcdir)/'`specials.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-specials.Tpo $(DEPDIR)/dvipdfmx-specials.Po @@ -1758,6 +1837,20 @@ dvipdfmx-tt_aux.obj: tt_aux.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-tt_aux.obj `if test -f 'tt_aux.c'; then $(CYGPATH_W) 'tt_aux.c'; else $(CYGPATH_W) '$(srcdir)/tt_aux.c'; fi` +dvipdfmx-tt_cmap.o: tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-tt_cmap.o -MD -MP -MF $(DEPDIR)/dvipdfmx-tt_cmap.Tpo -c -o dvipdfmx-tt_cmap.o `test -f 'tt_cmap.c' || echo '$(srcdir)/'`tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-tt_cmap.Tpo $(DEPDIR)/dvipdfmx-tt_cmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tt_cmap.c' object='dvipdfmx-tt_cmap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-tt_cmap.o `test -f 'tt_cmap.c' || echo '$(srcdir)/'`tt_cmap.c + +dvipdfmx-tt_cmap.obj: tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-tt_cmap.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-tt_cmap.Tpo -c -o dvipdfmx-tt_cmap.obj `if test -f 'tt_cmap.c'; then $(CYGPATH_W) 'tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/tt_cmap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-tt_cmap.Tpo $(DEPDIR)/dvipdfmx-tt_cmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tt_cmap.c' object='dvipdfmx-tt_cmap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-tt_cmap.obj `if test -f 'tt_cmap.c'; then $(CYGPATH_W) 'tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/tt_cmap.c'; fi` + dvipdfmx-tt_glyf.o: tt_glyf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-tt_glyf.o -MD -MP -MF $(DEPDIR)/dvipdfmx-tt_glyf.Tpo -c -o dvipdfmx-tt_glyf.o `test -f 'tt_glyf.c' || echo '$(srcdir)/'`tt_glyf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-tt_glyf.Tpo $(DEPDIR)/dvipdfmx-tt_glyf.Po @@ -1856,243 +1949,19 @@ dvipdfmx-vf.obj: vf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-vf.obj `if test -f 'vf.c'; then $(CYGPATH_W) 'vf.c'; else $(CYGPATH_W) '$(srcdir)/vf.c'; fi` -src/dvipdfmx-cidtype0.o: src/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-cidtype0.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-cidtype0.Tpo -c -o src/dvipdfmx-cidtype0.o `test -f 'src/cidtype0.c' || echo '$(srcdir)/'`src/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-cidtype0.Tpo src/$(DEPDIR)/dvipdfmx-cidtype0.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/cidtype0.c' object='src/dvipdfmx-cidtype0.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-cidtype0.o `test -f 'src/cidtype0.c' || echo '$(srcdir)/'`src/cidtype0.c - -src/dvipdfmx-cidtype0.obj: src/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-cidtype0.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-cidtype0.Tpo -c -o src/dvipdfmx-cidtype0.obj `if test -f 'src/cidtype0.c'; then $(CYGPATH_W) 'src/cidtype0.c'; else $(CYGPATH_W) '$(srcdir)/src/cidtype0.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-cidtype0.Tpo src/$(DEPDIR)/dvipdfmx-cidtype0.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/cidtype0.c' object='src/dvipdfmx-cidtype0.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-cidtype0.obj `if test -f 'src/cidtype0.c'; then $(CYGPATH_W) 'src/cidtype0.c'; else $(CYGPATH_W) '$(srcdir)/src/cidtype0.c'; fi` - -src/dvipdfmx-dvi.o: src/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-dvi.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-dvi.Tpo -c -o src/dvipdfmx-dvi.o `test -f 'src/dvi.c' || echo '$(srcdir)/'`src/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-dvi.Tpo src/$(DEPDIR)/dvipdfmx-dvi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/dvi.c' object='src/dvipdfmx-dvi.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-dvi.o `test -f 'src/dvi.c' || echo '$(srcdir)/'`src/dvi.c - -src/dvipdfmx-dvi.obj: src/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-dvi.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-dvi.Tpo -c -o src/dvipdfmx-dvi.obj `if test -f 'src/dvi.c'; then $(CYGPATH_W) 'src/dvi.c'; else $(CYGPATH_W) '$(srcdir)/src/dvi.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-dvi.Tpo src/$(DEPDIR)/dvipdfmx-dvi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/dvi.c' object='src/dvipdfmx-dvi.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-dvi.obj `if test -f 'src/dvi.c'; then $(CYGPATH_W) 'src/dvi.c'; else $(CYGPATH_W) '$(srcdir)/src/dvi.c'; fi` - -src/dvipdfmx-dvipdfmx.o: src/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-dvipdfmx.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-dvipdfmx.Tpo -c -o src/dvipdfmx-dvipdfmx.o `test -f 'src/dvipdfmx.c' || echo '$(srcdir)/'`src/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-dvipdfmx.Tpo src/$(DEPDIR)/dvipdfmx-dvipdfmx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/dvipdfmx.c' object='src/dvipdfmx-dvipdfmx.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-dvipdfmx.o `test -f 'src/dvipdfmx.c' || echo '$(srcdir)/'`src/dvipdfmx.c - -src/dvipdfmx-dvipdfmx.obj: src/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-dvipdfmx.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-dvipdfmx.Tpo -c -o src/dvipdfmx-dvipdfmx.obj `if test -f 'src/dvipdfmx.c'; then $(CYGPATH_W) 'src/dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/src/dvipdfmx.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-dvipdfmx.Tpo src/$(DEPDIR)/dvipdfmx-dvipdfmx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/dvipdfmx.c' object='src/dvipdfmx-dvipdfmx.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-dvipdfmx.obj `if test -f 'src/dvipdfmx.c'; then $(CYGPATH_W) 'src/dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/src/dvipdfmx.c'; fi` - -src/dvipdfmx-epdf.o: src/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-epdf.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-epdf.Tpo -c -o src/dvipdfmx-epdf.o `test -f 'src/epdf.c' || echo '$(srcdir)/'`src/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-epdf.Tpo src/$(DEPDIR)/dvipdfmx-epdf.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/epdf.c' object='src/dvipdfmx-epdf.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-epdf.o `test -f 'src/epdf.c' || echo '$(srcdir)/'`src/epdf.c - -src/dvipdfmx-epdf.obj: src/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-epdf.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-epdf.Tpo -c -o src/dvipdfmx-epdf.obj `if test -f 'src/epdf.c'; then $(CYGPATH_W) 'src/epdf.c'; else $(CYGPATH_W) '$(srcdir)/src/epdf.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-epdf.Tpo src/$(DEPDIR)/dvipdfmx-epdf.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/epdf.c' object='src/dvipdfmx-epdf.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-epdf.obj `if test -f 'src/epdf.c'; then $(CYGPATH_W) 'src/epdf.c'; else $(CYGPATH_W) '$(srcdir)/src/epdf.c'; fi` - -src/dvipdfmx-jpegimage.o: src/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-jpegimage.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-jpegimage.Tpo -c -o src/dvipdfmx-jpegimage.o `test -f 'src/jpegimage.c' || echo '$(srcdir)/'`src/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-jpegimage.Tpo src/$(DEPDIR)/dvipdfmx-jpegimage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/jpegimage.c' object='src/dvipdfmx-jpegimage.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-jpegimage.o `test -f 'src/jpegimage.c' || echo '$(srcdir)/'`src/jpegimage.c - -src/dvipdfmx-jpegimage.obj: src/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-jpegimage.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-jpegimage.Tpo -c -o src/dvipdfmx-jpegimage.obj `if test -f 'src/jpegimage.c'; then $(CYGPATH_W) 'src/jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/src/jpegimage.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-jpegimage.Tpo src/$(DEPDIR)/dvipdfmx-jpegimage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/jpegimage.c' object='src/dvipdfmx-jpegimage.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-jpegimage.obj `if test -f 'src/jpegimage.c'; then $(CYGPATH_W) 'src/jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/src/jpegimage.c'; fi` - -src/dvipdfmx-pdfcolor.o: src/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfcolor.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfcolor.Tpo -c -o src/dvipdfmx-pdfcolor.o `test -f 'src/pdfcolor.c' || echo '$(srcdir)/'`src/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfcolor.Tpo src/$(DEPDIR)/dvipdfmx-pdfcolor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfcolor.c' object='src/dvipdfmx-pdfcolor.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfcolor.o `test -f 'src/pdfcolor.c' || echo '$(srcdir)/'`src/pdfcolor.c - -src/dvipdfmx-pdfcolor.obj: src/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfcolor.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfcolor.Tpo -c -o src/dvipdfmx-pdfcolor.obj `if test -f 'src/pdfcolor.c'; then $(CYGPATH_W) 'src/pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfcolor.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfcolor.Tpo src/$(DEPDIR)/dvipdfmx-pdfcolor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfcolor.c' object='src/dvipdfmx-pdfcolor.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfcolor.obj `if test -f 'src/pdfcolor.c'; then $(CYGPATH_W) 'src/pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfcolor.c'; fi` - -src/dvipdfmx-pdfdev.o: src/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdev.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdev.Tpo -c -o src/dvipdfmx-pdfdev.o `test -f 'src/pdfdev.c' || echo '$(srcdir)/'`src/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdev.Tpo src/$(DEPDIR)/dvipdfmx-pdfdev.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdev.c' object='src/dvipdfmx-pdfdev.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdev.o `test -f 'src/pdfdev.c' || echo '$(srcdir)/'`src/pdfdev.c - -src/dvipdfmx-pdfdev.obj: src/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdev.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdev.Tpo -c -o src/dvipdfmx-pdfdev.obj `if test -f 'src/pdfdev.c'; then $(CYGPATH_W) 'src/pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdev.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdev.Tpo src/$(DEPDIR)/dvipdfmx-pdfdev.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdev.c' object='src/dvipdfmx-pdfdev.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdev.obj `if test -f 'src/pdfdev.c'; then $(CYGPATH_W) 'src/pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdev.c'; fi` - -src/dvipdfmx-pdfdoc.o: src/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdoc.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdoc.Tpo -c -o src/dvipdfmx-pdfdoc.o `test -f 'src/pdfdoc.c' || echo '$(srcdir)/'`src/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdoc.Tpo src/$(DEPDIR)/dvipdfmx-pdfdoc.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdoc.c' object='src/dvipdfmx-pdfdoc.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdoc.o `test -f 'src/pdfdoc.c' || echo '$(srcdir)/'`src/pdfdoc.c - -src/dvipdfmx-pdfdoc.obj: src/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdoc.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdoc.Tpo -c -o src/dvipdfmx-pdfdoc.obj `if test -f 'src/pdfdoc.c'; then $(CYGPATH_W) 'src/pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdoc.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdoc.Tpo src/$(DEPDIR)/dvipdfmx-pdfdoc.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdoc.c' object='src/dvipdfmx-pdfdoc.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdoc.obj `if test -f 'src/pdfdoc.c'; then $(CYGPATH_W) 'src/pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdoc.c'; fi` - -src/dvipdfmx-pdfdraw.o: src/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdraw.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdraw.Tpo -c -o src/dvipdfmx-pdfdraw.o `test -f 'src/pdfdraw.c' || echo '$(srcdir)/'`src/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdraw.Tpo src/$(DEPDIR)/dvipdfmx-pdfdraw.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdraw.c' object='src/dvipdfmx-pdfdraw.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdraw.o `test -f 'src/pdfdraw.c' || echo '$(srcdir)/'`src/pdfdraw.c - -src/dvipdfmx-pdfdraw.obj: src/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfdraw.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfdraw.Tpo -c -o src/dvipdfmx-pdfdraw.obj `if test -f 'src/pdfdraw.c'; then $(CYGPATH_W) 'src/pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdraw.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfdraw.Tpo src/$(DEPDIR)/dvipdfmx-pdfdraw.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfdraw.c' object='src/dvipdfmx-pdfdraw.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfdraw.obj `if test -f 'src/pdfdraw.c'; then $(CYGPATH_W) 'src/pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfdraw.c'; fi` - -src/dvipdfmx-pdfnames.o: src/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfnames.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfnames.Tpo -c -o src/dvipdfmx-pdfnames.o `test -f 'src/pdfnames.c' || echo '$(srcdir)/'`src/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfnames.Tpo src/$(DEPDIR)/dvipdfmx-pdfnames.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfnames.c' object='src/dvipdfmx-pdfnames.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfnames.o `test -f 'src/pdfnames.c' || echo '$(srcdir)/'`src/pdfnames.c - -src/dvipdfmx-pdfnames.obj: src/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfnames.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfnames.Tpo -c -o src/dvipdfmx-pdfnames.obj `if test -f 'src/pdfnames.c'; then $(CYGPATH_W) 'src/pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfnames.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfnames.Tpo src/$(DEPDIR)/dvipdfmx-pdfnames.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfnames.c' object='src/dvipdfmx-pdfnames.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfnames.obj `if test -f 'src/pdfnames.c'; then $(CYGPATH_W) 'src/pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfnames.c'; fi` - -src/dvipdfmx-pdfobj.o: src/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfobj.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfobj.Tpo -c -o src/dvipdfmx-pdfobj.o `test -f 'src/pdfobj.c' || echo '$(srcdir)/'`src/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfobj.Tpo src/$(DEPDIR)/dvipdfmx-pdfobj.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfobj.c' object='src/dvipdfmx-pdfobj.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfobj.o `test -f 'src/pdfobj.c' || echo '$(srcdir)/'`src/pdfobj.c - -src/dvipdfmx-pdfobj.obj: src/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfobj.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfobj.Tpo -c -o src/dvipdfmx-pdfobj.obj `if test -f 'src/pdfobj.c'; then $(CYGPATH_W) 'src/pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfobj.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfobj.Tpo src/$(DEPDIR)/dvipdfmx-pdfobj.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfobj.c' object='src/dvipdfmx-pdfobj.obj' libtool=no @AMDEPBACKSLASH@ +dvipdfmx-xbb.o: xbb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-xbb.o -MD -MP -MF $(DEPDIR)/dvipdfmx-xbb.Tpo -c -o dvipdfmx-xbb.o `test -f 'xbb.c' || echo '$(srcdir)/'`xbb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-xbb.Tpo $(DEPDIR)/dvipdfmx-xbb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xbb.c' object='dvipdfmx-xbb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfobj.obj `if test -f 'src/pdfobj.c'; then $(CYGPATH_W) 'src/pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfobj.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-xbb.o `test -f 'xbb.c' || echo '$(srcdir)/'`xbb.c -src/dvipdfmx-pdfximage.o: src/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfximage.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfximage.Tpo -c -o src/dvipdfmx-pdfximage.o `test -f 'src/pdfximage.c' || echo '$(srcdir)/'`src/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfximage.Tpo src/$(DEPDIR)/dvipdfmx-pdfximage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfximage.c' object='src/dvipdfmx-pdfximage.o' libtool=no @AMDEPBACKSLASH@ +dvipdfmx-xbb.obj: xbb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dvipdfmx-xbb.obj -MD -MP -MF $(DEPDIR)/dvipdfmx-xbb.Tpo -c -o dvipdfmx-xbb.obj `if test -f 'xbb.c'; then $(CYGPATH_W) 'xbb.c'; else $(CYGPATH_W) '$(srcdir)/xbb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/dvipdfmx-xbb.Tpo $(DEPDIR)/dvipdfmx-xbb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xbb.c' object='dvipdfmx-xbb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfximage.o `test -f 'src/pdfximage.c' || echo '$(srcdir)/'`src/pdfximage.c - -src/dvipdfmx-pdfximage.obj: src/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-pdfximage.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-pdfximage.Tpo -c -o src/dvipdfmx-pdfximage.obj `if test -f 'src/pdfximage.c'; then $(CYGPATH_W) 'src/pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfximage.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-pdfximage.Tpo src/$(DEPDIR)/dvipdfmx-pdfximage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pdfximage.c' object='src/dvipdfmx-pdfximage.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-pdfximage.obj `if test -f 'src/pdfximage.c'; then $(CYGPATH_W) 'src/pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/src/pdfximage.c'; fi` - -src/dvipdfmx-spc_pdfm.o: src/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-spc_pdfm.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-spc_pdfm.Tpo -c -o src/dvipdfmx-spc_pdfm.o `test -f 'src/spc_pdfm.c' || echo '$(srcdir)/'`src/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-spc_pdfm.Tpo src/$(DEPDIR)/dvipdfmx-spc_pdfm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/spc_pdfm.c' object='src/dvipdfmx-spc_pdfm.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-spc_pdfm.o `test -f 'src/spc_pdfm.c' || echo '$(srcdir)/'`src/spc_pdfm.c - -src/dvipdfmx-spc_pdfm.obj: src/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-spc_pdfm.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-spc_pdfm.Tpo -c -o src/dvipdfmx-spc_pdfm.obj `if test -f 'src/spc_pdfm.c'; then $(CYGPATH_W) 'src/spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/src/spc_pdfm.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-spc_pdfm.Tpo src/$(DEPDIR)/dvipdfmx-spc_pdfm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/spc_pdfm.c' object='src/dvipdfmx-spc_pdfm.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-spc_pdfm.obj `if test -f 'src/spc_pdfm.c'; then $(CYGPATH_W) 'src/spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/src/spc_pdfm.c'; fi` - -src/dvipdfmx-spc_tpic.o: src/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-spc_tpic.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-spc_tpic.Tpo -c -o src/dvipdfmx-spc_tpic.o `test -f 'src/spc_tpic.c' || echo '$(srcdir)/'`src/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-spc_tpic.Tpo src/$(DEPDIR)/dvipdfmx-spc_tpic.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/spc_tpic.c' object='src/dvipdfmx-spc_tpic.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-spc_tpic.o `test -f 'src/spc_tpic.c' || echo '$(srcdir)/'`src/spc_tpic.c - -src/dvipdfmx-spc_tpic.obj: src/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-spc_tpic.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-spc_tpic.Tpo -c -o src/dvipdfmx-spc_tpic.obj `if test -f 'src/spc_tpic.c'; then $(CYGPATH_W) 'src/spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/src/spc_tpic.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-spc_tpic.Tpo src/$(DEPDIR)/dvipdfmx-spc_tpic.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/spc_tpic.c' object='src/dvipdfmx-spc_tpic.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-spc_tpic.obj `if test -f 'src/spc_tpic.c'; then $(CYGPATH_W) 'src/spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/src/spc_tpic.c'; fi` - -src/dvipdfmx-tt_cmap.o: src/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-tt_cmap.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-tt_cmap.Tpo -c -o src/dvipdfmx-tt_cmap.o `test -f 'src/tt_cmap.c' || echo '$(srcdir)/'`src/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-tt_cmap.Tpo src/$(DEPDIR)/dvipdfmx-tt_cmap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tt_cmap.c' object='src/dvipdfmx-tt_cmap.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-tt_cmap.o `test -f 'src/tt_cmap.c' || echo '$(srcdir)/'`src/tt_cmap.c - -src/dvipdfmx-tt_cmap.obj: src/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-tt_cmap.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-tt_cmap.Tpo -c -o src/dvipdfmx-tt_cmap.obj `if test -f 'src/tt_cmap.c'; then $(CYGPATH_W) 'src/tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/src/tt_cmap.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-tt_cmap.Tpo src/$(DEPDIR)/dvipdfmx-tt_cmap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/tt_cmap.c' object='src/dvipdfmx-tt_cmap.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-tt_cmap.obj `if test -f 'src/tt_cmap.c'; then $(CYGPATH_W) 'src/tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/src/tt_cmap.c'; fi` - -src/dvipdfmx-type1c.o: src/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-type1c.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-type1c.Tpo -c -o src/dvipdfmx-type1c.o `test -f 'src/type1c.c' || echo '$(srcdir)/'`src/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-type1c.Tpo src/$(DEPDIR)/dvipdfmx-type1c.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/type1c.c' object='src/dvipdfmx-type1c.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-type1c.o `test -f 'src/type1c.c' || echo '$(srcdir)/'`src/type1c.c - -src/dvipdfmx-type1c.obj: src/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-type1c.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-type1c.Tpo -c -o src/dvipdfmx-type1c.obj `if test -f 'src/type1c.c'; then $(CYGPATH_W) 'src/type1c.c'; else $(CYGPATH_W) '$(srcdir)/src/type1c.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-type1c.Tpo src/$(DEPDIR)/dvipdfmx-type1c.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/type1c.c' object='src/dvipdfmx-type1c.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-type1c.obj `if test -f 'src/type1c.c'; then $(CYGPATH_W) 'src/type1c.c'; else $(CYGPATH_W) '$(srcdir)/src/type1c.c'; fi` - -src/dvipdfmx-xbb.o: src/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-xbb.o -MD -MP -MF src/$(DEPDIR)/dvipdfmx-xbb.Tpo -c -o src/dvipdfmx-xbb.o `test -f 'src/xbb.c' || echo '$(srcdir)/'`src/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-xbb.Tpo src/$(DEPDIR)/dvipdfmx-xbb.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xbb.c' object='src/dvipdfmx-xbb.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-xbb.o `test -f 'src/xbb.c' || echo '$(srcdir)/'`src/xbb.c - -src/dvipdfmx-xbb.obj: src/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/dvipdfmx-xbb.obj -MD -MP -MF src/$(DEPDIR)/dvipdfmx-xbb.Tpo -c -o src/dvipdfmx-xbb.obj `if test -f 'src/xbb.c'; then $(CYGPATH_W) 'src/xbb.c'; else $(CYGPATH_W) '$(srcdir)/src/xbb.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/dvipdfmx-xbb.Tpo src/$(DEPDIR)/dvipdfmx-xbb.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/xbb.c' object='src/dvipdfmx-xbb.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/dvipdfmx-xbb.obj `if test -f 'src/xbb.c'; then $(CYGPATH_W) 'src/xbb.c'; else $(CYGPATH_W) '$(srcdir)/src/xbb.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dvipdfmx-xbb.obj `if test -f 'xbb.c'; then $(CYGPATH_W) 'xbb.c'; else $(CYGPATH_W) '$(srcdir)/xbb.c'; fi` xdvipdfmx-agl.o: agl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-agl.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-agl.Tpo -c -o xdvipdfmx-agl.o `test -f 'agl.c' || echo '$(srcdir)/'`agl.c @@ -2248,6 +2117,48 @@ xdvipdfmx-dpxutil.obj: dpxutil.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-dpxutil.obj `if test -f 'dpxutil.c'; then $(CYGPATH_W) 'dpxutil.c'; else $(CYGPATH_W) '$(srcdir)/dpxutil.c'; fi` +xdvipdfmx-dvi.o: dvi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-dvi.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-dvi.Tpo -c -o xdvipdfmx-dvi.o `test -f 'dvi.c' || echo '$(srcdir)/'`dvi.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-dvi.Tpo $(DEPDIR)/xdvipdfmx-dvi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvi.c' object='xdvipdfmx-dvi.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-dvi.o `test -f 'dvi.c' || echo '$(srcdir)/'`dvi.c + +xdvipdfmx-dvi.obj: dvi.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-dvi.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-dvi.Tpo -c -o xdvipdfmx-dvi.obj `if test -f 'dvi.c'; then $(CYGPATH_W) 'dvi.c'; else $(CYGPATH_W) '$(srcdir)/dvi.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-dvi.Tpo $(DEPDIR)/xdvipdfmx-dvi.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvi.c' object='xdvipdfmx-dvi.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-dvi.obj `if test -f 'dvi.c'; then $(CYGPATH_W) 'dvi.c'; else $(CYGPATH_W) '$(srcdir)/dvi.c'; fi` + +xdvipdfmx-dvipdfmx.o: dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-dvipdfmx.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo -c -o xdvipdfmx-dvipdfmx.o `test -f 'dvipdfmx.c' || echo '$(srcdir)/'`dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo $(DEPDIR)/xdvipdfmx-dvipdfmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvipdfmx.c' object='xdvipdfmx-dvipdfmx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-dvipdfmx.o `test -f 'dvipdfmx.c' || echo '$(srcdir)/'`dvipdfmx.c + +xdvipdfmx-dvipdfmx.obj: dvipdfmx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-dvipdfmx.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo -c -o xdvipdfmx-dvipdfmx.obj `if test -f 'dvipdfmx.c'; then $(CYGPATH_W) 'dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/dvipdfmx.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo $(DEPDIR)/xdvipdfmx-dvipdfmx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dvipdfmx.c' object='xdvipdfmx-dvipdfmx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-dvipdfmx.obj `if test -f 'dvipdfmx.c'; then $(CYGPATH_W) 'dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/dvipdfmx.c'; fi` + +xdvipdfmx-epdf.o: epdf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-epdf.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-epdf.Tpo -c -o xdvipdfmx-epdf.o `test -f 'epdf.c' || echo '$(srcdir)/'`epdf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-epdf.Tpo $(DEPDIR)/xdvipdfmx-epdf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epdf.c' object='xdvipdfmx-epdf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-epdf.o `test -f 'epdf.c' || echo '$(srcdir)/'`epdf.c + +xdvipdfmx-epdf.obj: epdf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-epdf.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-epdf.Tpo -c -o xdvipdfmx-epdf.obj `if test -f 'epdf.c'; then $(CYGPATH_W) 'epdf.c'; else $(CYGPATH_W) '$(srcdir)/epdf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-epdf.Tpo $(DEPDIR)/xdvipdfmx-epdf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='epdf.c' object='xdvipdfmx-epdf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-epdf.obj `if test -f 'epdf.c'; then $(CYGPATH_W) 'epdf.c'; else $(CYGPATH_W) '$(srcdir)/epdf.c'; fi` + xdvipdfmx-fontmap.o: fontmap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-fontmap.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-fontmap.Tpo -c -o xdvipdfmx-fontmap.o `test -f 'fontmap.c' || echo '$(srcdir)/'`fontmap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-fontmap.Tpo $(DEPDIR)/xdvipdfmx-fontmap.Po @@ -2262,6 +2173,20 @@ xdvipdfmx-fontmap.obj: fontmap.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-fontmap.obj `if test -f 'fontmap.c'; then $(CYGPATH_W) 'fontmap.c'; else $(CYGPATH_W) '$(srcdir)/fontmap.c'; fi` +xdvipdfmx-jpegimage.o: jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-jpegimage.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-jpegimage.Tpo -c -o xdvipdfmx-jpegimage.o `test -f 'jpegimage.c' || echo '$(srcdir)/'`jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-jpegimage.Tpo $(DEPDIR)/xdvipdfmx-jpegimage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpegimage.c' object='xdvipdfmx-jpegimage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-jpegimage.o `test -f 'jpegimage.c' || echo '$(srcdir)/'`jpegimage.c + +xdvipdfmx-jpegimage.obj: jpegimage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-jpegimage.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-jpegimage.Tpo -c -o xdvipdfmx-jpegimage.obj `if test -f 'jpegimage.c'; then $(CYGPATH_W) 'jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/jpegimage.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-jpegimage.Tpo $(DEPDIR)/xdvipdfmx-jpegimage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jpegimage.c' object='xdvipdfmx-jpegimage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-jpegimage.obj `if test -f 'jpegimage.c'; then $(CYGPATH_W) 'jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/jpegimage.c'; fi` + xdvipdfmx-mpost.o: mpost.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-mpost.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-mpost.Tpo -c -o xdvipdfmx-mpost.o `test -f 'mpost.c' || echo '$(srcdir)/'`mpost.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-mpost.Tpo $(DEPDIR)/xdvipdfmx-mpost.Po @@ -2290,6 +2215,62 @@ xdvipdfmx-otl_conf.obj: otl_conf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-otl_conf.obj `if test -f 'otl_conf.c'; then $(CYGPATH_W) 'otl_conf.c'; else $(CYGPATH_W) '$(srcdir)/otl_conf.c'; fi` +xdvipdfmx-pdfcolor.o: pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfcolor.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfcolor.Tpo -c -o xdvipdfmx-pdfcolor.o `test -f 'pdfcolor.c' || echo '$(srcdir)/'`pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfcolor.Tpo $(DEPDIR)/xdvipdfmx-pdfcolor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfcolor.c' object='xdvipdfmx-pdfcolor.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfcolor.o `test -f 'pdfcolor.c' || echo '$(srcdir)/'`pdfcolor.c + +xdvipdfmx-pdfcolor.obj: pdfcolor.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfcolor.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfcolor.Tpo -c -o xdvipdfmx-pdfcolor.obj `if test -f 'pdfcolor.c'; then $(CYGPATH_W) 'pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/pdfcolor.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfcolor.Tpo $(DEPDIR)/xdvipdfmx-pdfcolor.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfcolor.c' object='xdvipdfmx-pdfcolor.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfcolor.obj `if test -f 'pdfcolor.c'; then $(CYGPATH_W) 'pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/pdfcolor.c'; fi` + +xdvipdfmx-pdfdev.o: pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdev.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdev.Tpo -c -o xdvipdfmx-pdfdev.o `test -f 'pdfdev.c' || echo '$(srcdir)/'`pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdev.Tpo $(DEPDIR)/xdvipdfmx-pdfdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdev.c' object='xdvipdfmx-pdfdev.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdev.o `test -f 'pdfdev.c' || echo '$(srcdir)/'`pdfdev.c + +xdvipdfmx-pdfdev.obj: pdfdev.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdev.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdev.Tpo -c -o xdvipdfmx-pdfdev.obj `if test -f 'pdfdev.c'; then $(CYGPATH_W) 'pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/pdfdev.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdev.Tpo $(DEPDIR)/xdvipdfmx-pdfdev.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdev.c' object='xdvipdfmx-pdfdev.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdev.obj `if test -f 'pdfdev.c'; then $(CYGPATH_W) 'pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/pdfdev.c'; fi` + +xdvipdfmx-pdfdoc.o: pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdoc.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdoc.Tpo -c -o xdvipdfmx-pdfdoc.o `test -f 'pdfdoc.c' || echo '$(srcdir)/'`pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdoc.Tpo $(DEPDIR)/xdvipdfmx-pdfdoc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdoc.c' object='xdvipdfmx-pdfdoc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdoc.o `test -f 'pdfdoc.c' || echo '$(srcdir)/'`pdfdoc.c + +xdvipdfmx-pdfdoc.obj: pdfdoc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdoc.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdoc.Tpo -c -o xdvipdfmx-pdfdoc.obj `if test -f 'pdfdoc.c'; then $(CYGPATH_W) 'pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/pdfdoc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdoc.Tpo $(DEPDIR)/xdvipdfmx-pdfdoc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdoc.c' object='xdvipdfmx-pdfdoc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdoc.obj `if test -f 'pdfdoc.c'; then $(CYGPATH_W) 'pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/pdfdoc.c'; fi` + +xdvipdfmx-pdfdraw.o: pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdraw.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdraw.Tpo -c -o xdvipdfmx-pdfdraw.o `test -f 'pdfdraw.c' || echo '$(srcdir)/'`pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdraw.Tpo $(DEPDIR)/xdvipdfmx-pdfdraw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdraw.c' object='xdvipdfmx-pdfdraw.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdraw.o `test -f 'pdfdraw.c' || echo '$(srcdir)/'`pdfdraw.c + +xdvipdfmx-pdfdraw.obj: pdfdraw.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfdraw.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfdraw.Tpo -c -o xdvipdfmx-pdfdraw.obj `if test -f 'pdfdraw.c'; then $(CYGPATH_W) 'pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/pdfdraw.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfdraw.Tpo $(DEPDIR)/xdvipdfmx-pdfdraw.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfdraw.c' object='xdvipdfmx-pdfdraw.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfdraw.obj `if test -f 'pdfdraw.c'; then $(CYGPATH_W) 'pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/pdfdraw.c'; fi` + xdvipdfmx-pdffont.o: pdffont.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdffont.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdffont.Tpo -c -o xdvipdfmx-pdffont.o `test -f 'pdffont.c' || echo '$(srcdir)/'`pdffont.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdffont.Tpo $(DEPDIR)/xdvipdfmx-pdffont.Po @@ -2304,6 +2285,34 @@ xdvipdfmx-pdffont.obj: pdffont.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdffont.obj `if test -f 'pdffont.c'; then $(CYGPATH_W) 'pdffont.c'; else $(CYGPATH_W) '$(srcdir)/pdffont.c'; fi` +xdvipdfmx-pdfnames.o: pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfnames.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfnames.Tpo -c -o xdvipdfmx-pdfnames.o `test -f 'pdfnames.c' || echo '$(srcdir)/'`pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfnames.Tpo $(DEPDIR)/xdvipdfmx-pdfnames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfnames.c' object='xdvipdfmx-pdfnames.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfnames.o `test -f 'pdfnames.c' || echo '$(srcdir)/'`pdfnames.c + +xdvipdfmx-pdfnames.obj: pdfnames.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfnames.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfnames.Tpo -c -o xdvipdfmx-pdfnames.obj `if test -f 'pdfnames.c'; then $(CYGPATH_W) 'pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/pdfnames.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfnames.Tpo $(DEPDIR)/xdvipdfmx-pdfnames.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfnames.c' object='xdvipdfmx-pdfnames.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfnames.obj `if test -f 'pdfnames.c'; then $(CYGPATH_W) 'pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/pdfnames.c'; fi` + +xdvipdfmx-pdfobj.o: pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfobj.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfobj.Tpo -c -o xdvipdfmx-pdfobj.o `test -f 'pdfobj.c' || echo '$(srcdir)/'`pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfobj.Tpo $(DEPDIR)/xdvipdfmx-pdfobj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfobj.c' object='xdvipdfmx-pdfobj.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfobj.o `test -f 'pdfobj.c' || echo '$(srcdir)/'`pdfobj.c + +xdvipdfmx-pdfobj.obj: pdfobj.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfobj.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfobj.Tpo -c -o xdvipdfmx-pdfobj.obj `if test -f 'pdfobj.c'; then $(CYGPATH_W) 'pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/pdfobj.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfobj.Tpo $(DEPDIR)/xdvipdfmx-pdfobj.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfobj.c' object='xdvipdfmx-pdfobj.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfobj.obj `if test -f 'pdfobj.c'; then $(CYGPATH_W) 'pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/pdfobj.c'; fi` + xdvipdfmx-pdfparse.o: pdfparse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfparse.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfparse.Tpo -c -o xdvipdfmx-pdfparse.o `test -f 'pdfparse.c' || echo '$(srcdir)/'`pdfparse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfparse.Tpo $(DEPDIR)/xdvipdfmx-pdfparse.Po @@ -2332,6 +2341,20 @@ xdvipdfmx-pdfresource.obj: pdfresource.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfresource.obj `if test -f 'pdfresource.c'; then $(CYGPATH_W) 'pdfresource.c'; else $(CYGPATH_W) '$(srcdir)/pdfresource.c'; fi` +xdvipdfmx-pdfximage.o: pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfximage.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfximage.Tpo -c -o xdvipdfmx-pdfximage.o `test -f 'pdfximage.c' || echo '$(srcdir)/'`pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfximage.Tpo $(DEPDIR)/xdvipdfmx-pdfximage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfximage.c' object='xdvipdfmx-pdfximage.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfximage.o `test -f 'pdfximage.c' || echo '$(srcdir)/'`pdfximage.c + +xdvipdfmx-pdfximage.obj: pdfximage.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pdfximage.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-pdfximage.Tpo -c -o xdvipdfmx-pdfximage.obj `if test -f 'pdfximage.c'; then $(CYGPATH_W) 'pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/pdfximage.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pdfximage.Tpo $(DEPDIR)/xdvipdfmx-pdfximage.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pdfximage.c' object='xdvipdfmx-pdfximage.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-pdfximage.obj `if test -f 'pdfximage.c'; then $(CYGPATH_W) 'pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/pdfximage.c'; fi` + xdvipdfmx-pkfont.o: pkfont.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-pkfont.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-pkfont.Tpo -c -o xdvipdfmx-pkfont.o `test -f 'pkfont.c' || echo '$(srcdir)/'`pkfont.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-pkfont.Tpo $(DEPDIR)/xdvipdfmx-pkfont.Po @@ -2458,6 +2481,34 @@ xdvipdfmx-spc_misc.obj: spc_misc.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_misc.obj `if test -f 'spc_misc.c'; then $(CYGPATH_W) 'spc_misc.c'; else $(CYGPATH_W) '$(srcdir)/spc_misc.c'; fi` +xdvipdfmx-spc_pdfm.o: spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_pdfm.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo -c -o xdvipdfmx-spc_pdfm.o `test -f 'spc_pdfm.c' || echo '$(srcdir)/'`spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo $(DEPDIR)/xdvipdfmx-spc_pdfm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_pdfm.c' object='xdvipdfmx-spc_pdfm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_pdfm.o `test -f 'spc_pdfm.c' || echo '$(srcdir)/'`spc_pdfm.c + +xdvipdfmx-spc_pdfm.obj: spc_pdfm.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_pdfm.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo -c -o xdvipdfmx-spc_pdfm.obj `if test -f 'spc_pdfm.c'; then $(CYGPATH_W) 'spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/spc_pdfm.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo $(DEPDIR)/xdvipdfmx-spc_pdfm.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_pdfm.c' object='xdvipdfmx-spc_pdfm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_pdfm.obj `if test -f 'spc_pdfm.c'; then $(CYGPATH_W) 'spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/spc_pdfm.c'; fi` + +xdvipdfmx-spc_tpic.o: spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_tpic.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_tpic.Tpo -c -o xdvipdfmx-spc_tpic.o `test -f 'spc_tpic.c' || echo '$(srcdir)/'`spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_tpic.Tpo $(DEPDIR)/xdvipdfmx-spc_tpic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_tpic.c' object='xdvipdfmx-spc_tpic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_tpic.o `test -f 'spc_tpic.c' || echo '$(srcdir)/'`spc_tpic.c + +xdvipdfmx-spc_tpic.obj: spc_tpic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_tpic.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_tpic.Tpo -c -o xdvipdfmx-spc_tpic.obj `if test -f 'spc_tpic.c'; then $(CYGPATH_W) 'spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/spc_tpic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_tpic.Tpo $(DEPDIR)/xdvipdfmx-spc_tpic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_tpic.c' object='xdvipdfmx-spc_tpic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_tpic.obj `if test -f 'spc_tpic.c'; then $(CYGPATH_W) 'spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/spc_tpic.c'; fi` + xdvipdfmx-spc_util.o: spc_util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_util.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_util.Tpo -c -o xdvipdfmx-spc_util.o `test -f 'spc_util.c' || echo '$(srcdir)/'`spc_util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_util.Tpo $(DEPDIR)/xdvipdfmx-spc_util.Po @@ -2472,6 +2523,20 @@ xdvipdfmx-spc_util.obj: spc_util.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_util.obj `if test -f 'spc_util.c'; then $(CYGPATH_W) 'spc_util.c'; else $(CYGPATH_W) '$(srcdir)/spc_util.c'; fi` +xdvipdfmx-spc_xtx.o: spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_xtx.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo -c -o xdvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo $(DEPDIR)/xdvipdfmx-spc_xtx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='xdvipdfmx-spc_xtx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c + +xdvipdfmx-spc_xtx.obj: spc_xtx.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_xtx.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo -c -o xdvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo $(DEPDIR)/xdvipdfmx-spc_xtx.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='xdvipdfmx-spc_xtx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` + xdvipdfmx-specials.o: specials.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-specials.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-specials.Tpo -c -o xdvipdfmx-specials.o `test -f 'specials.c' || echo '$(srcdir)/'`specials.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-specials.Tpo $(DEPDIR)/xdvipdfmx-specials.Po @@ -2556,6 +2621,20 @@ xdvipdfmx-tt_aux.obj: tt_aux.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-tt_aux.obj `if test -f 'tt_aux.c'; then $(CYGPATH_W) 'tt_aux.c'; else $(CYGPATH_W) '$(srcdir)/tt_aux.c'; fi` +xdvipdfmx-tt_cmap.o: tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-tt_cmap.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-tt_cmap.Tpo -c -o xdvipdfmx-tt_cmap.o `test -f 'tt_cmap.c' || echo '$(srcdir)/'`tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-tt_cmap.Tpo $(DEPDIR)/xdvipdfmx-tt_cmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tt_cmap.c' object='xdvipdfmx-tt_cmap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-tt_cmap.o `test -f 'tt_cmap.c' || echo '$(srcdir)/'`tt_cmap.c + +xdvipdfmx-tt_cmap.obj: tt_cmap.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-tt_cmap.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-tt_cmap.Tpo -c -o xdvipdfmx-tt_cmap.obj `if test -f 'tt_cmap.c'; then $(CYGPATH_W) 'tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/tt_cmap.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-tt_cmap.Tpo $(DEPDIR)/xdvipdfmx-tt_cmap.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tt_cmap.c' object='xdvipdfmx-tt_cmap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-tt_cmap.obj `if test -f 'tt_cmap.c'; then $(CYGPATH_W) 'tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/tt_cmap.c'; fi` + xdvipdfmx-tt_glyf.o: tt_glyf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-tt_glyf.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-tt_glyf.Tpo -c -o xdvipdfmx-tt_glyf.o `test -f 'tt_glyf.c' || echo '$(srcdir)/'`tt_glyf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-tt_glyf.Tpo $(DEPDIR)/xdvipdfmx-tt_glyf.Po @@ -2654,257 +2733,19 @@ xdvipdfmx-vf.obj: vf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-vf.obj `if test -f 'vf.c'; then $(CYGPATH_W) 'vf.c'; else $(CYGPATH_W) '$(srcdir)/vf.c'; fi` -xsrc/xdvipdfmx-cidtype0.o: xsrc/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-cidtype0.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Tpo -c -o xsrc/xdvipdfmx-cidtype0.o `test -f 'xsrc/cidtype0.c' || echo '$(srcdir)/'`xsrc/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Tpo xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/cidtype0.c' object='xsrc/xdvipdfmx-cidtype0.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-cidtype0.o `test -f 'xsrc/cidtype0.c' || echo '$(srcdir)/'`xsrc/cidtype0.c - -xsrc/xdvipdfmx-cidtype0.obj: xsrc/cidtype0.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-cidtype0.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Tpo -c -o xsrc/xdvipdfmx-cidtype0.obj `if test -f 'xsrc/cidtype0.c'; then $(CYGPATH_W) 'xsrc/cidtype0.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/cidtype0.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Tpo xsrc/$(DEPDIR)/xdvipdfmx-cidtype0.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/cidtype0.c' object='xsrc/xdvipdfmx-cidtype0.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-cidtype0.obj `if test -f 'xsrc/cidtype0.c'; then $(CYGPATH_W) 'xsrc/cidtype0.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/cidtype0.c'; fi` - -xsrc/xdvipdfmx-dvi.o: xsrc/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-dvi.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-dvi.Tpo -c -o xsrc/xdvipdfmx-dvi.o `test -f 'xsrc/dvi.c' || echo '$(srcdir)/'`xsrc/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-dvi.Tpo xsrc/$(DEPDIR)/xdvipdfmx-dvi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/dvi.c' object='xsrc/xdvipdfmx-dvi.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-dvi.o `test -f 'xsrc/dvi.c' || echo '$(srcdir)/'`xsrc/dvi.c - -xsrc/xdvipdfmx-dvi.obj: xsrc/dvi.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-dvi.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-dvi.Tpo -c -o xsrc/xdvipdfmx-dvi.obj `if test -f 'xsrc/dvi.c'; then $(CYGPATH_W) 'xsrc/dvi.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/dvi.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-dvi.Tpo xsrc/$(DEPDIR)/xdvipdfmx-dvi.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/dvi.c' object='xsrc/xdvipdfmx-dvi.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-dvi.obj `if test -f 'xsrc/dvi.c'; then $(CYGPATH_W) 'xsrc/dvi.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/dvi.c'; fi` - -xsrc/xdvipdfmx-dvipdfmx.o: xsrc/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-dvipdfmx.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo -c -o xsrc/xdvipdfmx-dvipdfmx.o `test -f 'xsrc/dvipdfmx.c' || echo '$(srcdir)/'`xsrc/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/dvipdfmx.c' object='xsrc/xdvipdfmx-dvipdfmx.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-dvipdfmx.o `test -f 'xsrc/dvipdfmx.c' || echo '$(srcdir)/'`xsrc/dvipdfmx.c - -xsrc/xdvipdfmx-dvipdfmx.obj: xsrc/dvipdfmx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-dvipdfmx.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo -c -o xsrc/xdvipdfmx-dvipdfmx.obj `if test -f 'xsrc/dvipdfmx.c'; then $(CYGPATH_W) 'xsrc/dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/dvipdfmx.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Tpo xsrc/$(DEPDIR)/xdvipdfmx-dvipdfmx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/dvipdfmx.c' object='xsrc/xdvipdfmx-dvipdfmx.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-dvipdfmx.obj `if test -f 'xsrc/dvipdfmx.c'; then $(CYGPATH_W) 'xsrc/dvipdfmx.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/dvipdfmx.c'; fi` - -xsrc/xdvipdfmx-epdf.o: xsrc/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-epdf.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-epdf.Tpo -c -o xsrc/xdvipdfmx-epdf.o `test -f 'xsrc/epdf.c' || echo '$(srcdir)/'`xsrc/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-epdf.Tpo xsrc/$(DEPDIR)/xdvipdfmx-epdf.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/epdf.c' object='xsrc/xdvipdfmx-epdf.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-epdf.o `test -f 'xsrc/epdf.c' || echo '$(srcdir)/'`xsrc/epdf.c - -xsrc/xdvipdfmx-epdf.obj: xsrc/epdf.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-epdf.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-epdf.Tpo -c -o xsrc/xdvipdfmx-epdf.obj `if test -f 'xsrc/epdf.c'; then $(CYGPATH_W) 'xsrc/epdf.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/epdf.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-epdf.Tpo xsrc/$(DEPDIR)/xdvipdfmx-epdf.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/epdf.c' object='xsrc/xdvipdfmx-epdf.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-epdf.obj `if test -f 'xsrc/epdf.c'; then $(CYGPATH_W) 'xsrc/epdf.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/epdf.c'; fi` - -xsrc/xdvipdfmx-jpegimage.o: xsrc/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-jpegimage.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Tpo -c -o xsrc/xdvipdfmx-jpegimage.o `test -f 'xsrc/jpegimage.c' || echo '$(srcdir)/'`xsrc/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Tpo xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/jpegimage.c' object='xsrc/xdvipdfmx-jpegimage.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-jpegimage.o `test -f 'xsrc/jpegimage.c' || echo '$(srcdir)/'`xsrc/jpegimage.c - -xsrc/xdvipdfmx-jpegimage.obj: xsrc/jpegimage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-jpegimage.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Tpo -c -o xsrc/xdvipdfmx-jpegimage.obj `if test -f 'xsrc/jpegimage.c'; then $(CYGPATH_W) 'xsrc/jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/jpegimage.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Tpo xsrc/$(DEPDIR)/xdvipdfmx-jpegimage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/jpegimage.c' object='xsrc/xdvipdfmx-jpegimage.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-jpegimage.obj `if test -f 'xsrc/jpegimage.c'; then $(CYGPATH_W) 'xsrc/jpegimage.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/jpegimage.c'; fi` - -xsrc/xdvipdfmx-pdfcolor.o: xsrc/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfcolor.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Tpo -c -o xsrc/xdvipdfmx-pdfcolor.o `test -f 'xsrc/pdfcolor.c' || echo '$(srcdir)/'`xsrc/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfcolor.c' object='xsrc/xdvipdfmx-pdfcolor.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfcolor.o `test -f 'xsrc/pdfcolor.c' || echo '$(srcdir)/'`xsrc/pdfcolor.c - -xsrc/xdvipdfmx-pdfcolor.obj: xsrc/pdfcolor.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfcolor.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Tpo -c -o xsrc/xdvipdfmx-pdfcolor.obj `if test -f 'xsrc/pdfcolor.c'; then $(CYGPATH_W) 'xsrc/pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfcolor.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfcolor.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfcolor.c' object='xsrc/xdvipdfmx-pdfcolor.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfcolor.obj `if test -f 'xsrc/pdfcolor.c'; then $(CYGPATH_W) 'xsrc/pdfcolor.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfcolor.c'; fi` - -xsrc/xdvipdfmx-pdfdev.o: xsrc/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdev.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Tpo -c -o xsrc/xdvipdfmx-pdfdev.o `test -f 'xsrc/pdfdev.c' || echo '$(srcdir)/'`xsrc/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdev.c' object='xsrc/xdvipdfmx-pdfdev.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdev.o `test -f 'xsrc/pdfdev.c' || echo '$(srcdir)/'`xsrc/pdfdev.c - -xsrc/xdvipdfmx-pdfdev.obj: xsrc/pdfdev.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdev.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Tpo -c -o xsrc/xdvipdfmx-pdfdev.obj `if test -f 'xsrc/pdfdev.c'; then $(CYGPATH_W) 'xsrc/pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdev.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdev.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdev.c' object='xsrc/xdvipdfmx-pdfdev.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdev.obj `if test -f 'xsrc/pdfdev.c'; then $(CYGPATH_W) 'xsrc/pdfdev.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdev.c'; fi` - -xsrc/xdvipdfmx-pdfdoc.o: xsrc/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdoc.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Tpo -c -o xsrc/xdvipdfmx-pdfdoc.o `test -f 'xsrc/pdfdoc.c' || echo '$(srcdir)/'`xsrc/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdoc.c' object='xsrc/xdvipdfmx-pdfdoc.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdoc.o `test -f 'xsrc/pdfdoc.c' || echo '$(srcdir)/'`xsrc/pdfdoc.c - -xsrc/xdvipdfmx-pdfdoc.obj: xsrc/pdfdoc.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdoc.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Tpo -c -o xsrc/xdvipdfmx-pdfdoc.obj `if test -f 'xsrc/pdfdoc.c'; then $(CYGPATH_W) 'xsrc/pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdoc.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdoc.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdoc.c' object='xsrc/xdvipdfmx-pdfdoc.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdoc.obj `if test -f 'xsrc/pdfdoc.c'; then $(CYGPATH_W) 'xsrc/pdfdoc.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdoc.c'; fi` - -xsrc/xdvipdfmx-pdfdraw.o: xsrc/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdraw.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Tpo -c -o xsrc/xdvipdfmx-pdfdraw.o `test -f 'xsrc/pdfdraw.c' || echo '$(srcdir)/'`xsrc/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdraw.c' object='xsrc/xdvipdfmx-pdfdraw.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdraw.o `test -f 'xsrc/pdfdraw.c' || echo '$(srcdir)/'`xsrc/pdfdraw.c - -xsrc/xdvipdfmx-pdfdraw.obj: xsrc/pdfdraw.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfdraw.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Tpo -c -o xsrc/xdvipdfmx-pdfdraw.obj `if test -f 'xsrc/pdfdraw.c'; then $(CYGPATH_W) 'xsrc/pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdraw.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfdraw.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfdraw.c' object='xsrc/xdvipdfmx-pdfdraw.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfdraw.obj `if test -f 'xsrc/pdfdraw.c'; then $(CYGPATH_W) 'xsrc/pdfdraw.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfdraw.c'; fi` - -xsrc/xdvipdfmx-pdfnames.o: xsrc/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfnames.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Tpo -c -o xsrc/xdvipdfmx-pdfnames.o `test -f 'xsrc/pdfnames.c' || echo '$(srcdir)/'`xsrc/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfnames.c' object='xsrc/xdvipdfmx-pdfnames.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfnames.o `test -f 'xsrc/pdfnames.c' || echo '$(srcdir)/'`xsrc/pdfnames.c - -xsrc/xdvipdfmx-pdfnames.obj: xsrc/pdfnames.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfnames.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Tpo -c -o xsrc/xdvipdfmx-pdfnames.obj `if test -f 'xsrc/pdfnames.c'; then $(CYGPATH_W) 'xsrc/pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfnames.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfnames.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfnames.c' object='xsrc/xdvipdfmx-pdfnames.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfnames.obj `if test -f 'xsrc/pdfnames.c'; then $(CYGPATH_W) 'xsrc/pdfnames.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfnames.c'; fi` - -xsrc/xdvipdfmx-pdfobj.o: xsrc/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfobj.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Tpo -c -o xsrc/xdvipdfmx-pdfobj.o `test -f 'xsrc/pdfobj.c' || echo '$(srcdir)/'`xsrc/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfobj.c' object='xsrc/xdvipdfmx-pdfobj.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfobj.o `test -f 'xsrc/pdfobj.c' || echo '$(srcdir)/'`xsrc/pdfobj.c - -xsrc/xdvipdfmx-pdfobj.obj: xsrc/pdfobj.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfobj.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Tpo -c -o xsrc/xdvipdfmx-pdfobj.obj `if test -f 'xsrc/pdfobj.c'; then $(CYGPATH_W) 'xsrc/pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfobj.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfobj.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfobj.c' object='xsrc/xdvipdfmx-pdfobj.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfobj.obj `if test -f 'xsrc/pdfobj.c'; then $(CYGPATH_W) 'xsrc/pdfobj.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfobj.c'; fi` - -xsrc/xdvipdfmx-pdfximage.o: xsrc/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfximage.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Tpo -c -o xsrc/xdvipdfmx-pdfximage.o `test -f 'xsrc/pdfximage.c' || echo '$(srcdir)/'`xsrc/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfximage.c' object='xsrc/xdvipdfmx-pdfximage.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfximage.o `test -f 'xsrc/pdfximage.c' || echo '$(srcdir)/'`xsrc/pdfximage.c - -xsrc/xdvipdfmx-pdfximage.obj: xsrc/pdfximage.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-pdfximage.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Tpo -c -o xsrc/xdvipdfmx-pdfximage.obj `if test -f 'xsrc/pdfximage.c'; then $(CYGPATH_W) 'xsrc/pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfximage.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Tpo xsrc/$(DEPDIR)/xdvipdfmx-pdfximage.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/pdfximage.c' object='xsrc/xdvipdfmx-pdfximage.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-pdfximage.obj `if test -f 'xsrc/pdfximage.c'; then $(CYGPATH_W) 'xsrc/pdfximage.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/pdfximage.c'; fi` - -xsrc/xdvipdfmx-spc_pdfm.o: xsrc/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-spc_pdfm.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo -c -o xsrc/xdvipdfmx-spc_pdfm.o `test -f 'xsrc/spc_pdfm.c' || echo '$(srcdir)/'`xsrc/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/spc_pdfm.c' object='xsrc/xdvipdfmx-spc_pdfm.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-spc_pdfm.o `test -f 'xsrc/spc_pdfm.c' || echo '$(srcdir)/'`xsrc/spc_pdfm.c - -xsrc/xdvipdfmx-spc_pdfm.obj: xsrc/spc_pdfm.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-spc_pdfm.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo -c -o xsrc/xdvipdfmx-spc_pdfm.obj `if test -f 'xsrc/spc_pdfm.c'; then $(CYGPATH_W) 'xsrc/spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/spc_pdfm.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Tpo xsrc/$(DEPDIR)/xdvipdfmx-spc_pdfm.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/spc_pdfm.c' object='xsrc/xdvipdfmx-spc_pdfm.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-spc_pdfm.obj `if test -f 'xsrc/spc_pdfm.c'; then $(CYGPATH_W) 'xsrc/spc_pdfm.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/spc_pdfm.c'; fi` - -xsrc/xdvipdfmx-spc_tpic.o: xsrc/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-spc_tpic.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Tpo -c -o xsrc/xdvipdfmx-spc_tpic.o `test -f 'xsrc/spc_tpic.c' || echo '$(srcdir)/'`xsrc/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Tpo xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/spc_tpic.c' object='xsrc/xdvipdfmx-spc_tpic.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-spc_tpic.o `test -f 'xsrc/spc_tpic.c' || echo '$(srcdir)/'`xsrc/spc_tpic.c - -xsrc/xdvipdfmx-spc_tpic.obj: xsrc/spc_tpic.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-spc_tpic.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Tpo -c -o xsrc/xdvipdfmx-spc_tpic.obj `if test -f 'xsrc/spc_tpic.c'; then $(CYGPATH_W) 'xsrc/spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/spc_tpic.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Tpo xsrc/$(DEPDIR)/xdvipdfmx-spc_tpic.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/spc_tpic.c' object='xsrc/xdvipdfmx-spc_tpic.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-spc_tpic.obj `if test -f 'xsrc/spc_tpic.c'; then $(CYGPATH_W) 'xsrc/spc_tpic.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/spc_tpic.c'; fi` - -xdvipdfmx-spc_xtx.o: spc_xtx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_xtx.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo -c -o xdvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo $(DEPDIR)/xdvipdfmx-spc_xtx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='xdvipdfmx-spc_xtx.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_xtx.o `test -f 'spc_xtx.c' || echo '$(srcdir)/'`spc_xtx.c - -xdvipdfmx-spc_xtx.obj: spc_xtx.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-spc_xtx.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo -c -o xdvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-spc_xtx.Tpo $(DEPDIR)/xdvipdfmx-spc_xtx.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='spc_xtx.c' object='xdvipdfmx-spc_xtx.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-spc_xtx.obj `if test -f 'spc_xtx.c'; then $(CYGPATH_W) 'spc_xtx.c'; else $(CYGPATH_W) '$(srcdir)/spc_xtx.c'; fi` - -xsrc/xdvipdfmx-tt_cmap.o: xsrc/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-tt_cmap.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Tpo -c -o xsrc/xdvipdfmx-tt_cmap.o `test -f 'xsrc/tt_cmap.c' || echo '$(srcdir)/'`xsrc/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Tpo xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/tt_cmap.c' object='xsrc/xdvipdfmx-tt_cmap.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-tt_cmap.o `test -f 'xsrc/tt_cmap.c' || echo '$(srcdir)/'`xsrc/tt_cmap.c - -xsrc/xdvipdfmx-tt_cmap.obj: xsrc/tt_cmap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-tt_cmap.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Tpo -c -o xsrc/xdvipdfmx-tt_cmap.obj `if test -f 'xsrc/tt_cmap.c'; then $(CYGPATH_W) 'xsrc/tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/tt_cmap.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Tpo xsrc/$(DEPDIR)/xdvipdfmx-tt_cmap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/tt_cmap.c' object='xsrc/xdvipdfmx-tt_cmap.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-tt_cmap.obj `if test -f 'xsrc/tt_cmap.c'; then $(CYGPATH_W) 'xsrc/tt_cmap.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/tt_cmap.c'; fi` - -xsrc/xdvipdfmx-type1c.o: xsrc/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-type1c.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-type1c.Tpo -c -o xsrc/xdvipdfmx-type1c.o `test -f 'xsrc/type1c.c' || echo '$(srcdir)/'`xsrc/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-type1c.Tpo xsrc/$(DEPDIR)/xdvipdfmx-type1c.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/type1c.c' object='xsrc/xdvipdfmx-type1c.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-type1c.o `test -f 'xsrc/type1c.c' || echo '$(srcdir)/'`xsrc/type1c.c - -xsrc/xdvipdfmx-type1c.obj: xsrc/type1c.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-type1c.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-type1c.Tpo -c -o xsrc/xdvipdfmx-type1c.obj `if test -f 'xsrc/type1c.c'; then $(CYGPATH_W) 'xsrc/type1c.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/type1c.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-type1c.Tpo xsrc/$(DEPDIR)/xdvipdfmx-type1c.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/type1c.c' object='xsrc/xdvipdfmx-type1c.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-type1c.obj `if test -f 'xsrc/type1c.c'; then $(CYGPATH_W) 'xsrc/type1c.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/type1c.c'; fi` - -xsrc/xdvipdfmx-xbb.o: xsrc/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-xbb.o -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-xbb.Tpo -c -o xsrc/xdvipdfmx-xbb.o `test -f 'xsrc/xbb.c' || echo '$(srcdir)/'`xsrc/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-xbb.Tpo xsrc/$(DEPDIR)/xdvipdfmx-xbb.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/xbb.c' object='xsrc/xdvipdfmx-xbb.o' libtool=no @AMDEPBACKSLASH@ +xdvipdfmx-xbb.o: xbb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-xbb.o -MD -MP -MF $(DEPDIR)/xdvipdfmx-xbb.Tpo -c -o xdvipdfmx-xbb.o `test -f 'xbb.c' || echo '$(srcdir)/'`xbb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-xbb.Tpo $(DEPDIR)/xdvipdfmx-xbb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xbb.c' object='xdvipdfmx-xbb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-xbb.o `test -f 'xsrc/xbb.c' || echo '$(srcdir)/'`xsrc/xbb.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-xbb.o `test -f 'xbb.c' || echo '$(srcdir)/'`xbb.c -xsrc/xdvipdfmx-xbb.obj: xsrc/xbb.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xsrc/xdvipdfmx-xbb.obj -MD -MP -MF xsrc/$(DEPDIR)/xdvipdfmx-xbb.Tpo -c -o xsrc/xdvipdfmx-xbb.obj `if test -f 'xsrc/xbb.c'; then $(CYGPATH_W) 'xsrc/xbb.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/xbb.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) xsrc/$(DEPDIR)/xdvipdfmx-xbb.Tpo xsrc/$(DEPDIR)/xdvipdfmx-xbb.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xsrc/xbb.c' object='xsrc/xdvipdfmx-xbb.obj' libtool=no @AMDEPBACKSLASH@ +xdvipdfmx-xbb.obj: xbb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xdvipdfmx-xbb.obj -MD -MP -MF $(DEPDIR)/xdvipdfmx-xbb.Tpo -c -o xdvipdfmx-xbb.obj `if test -f 'xbb.c'; then $(CYGPATH_W) 'xbb.c'; else $(CYGPATH_W) '$(srcdir)/xbb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xdvipdfmx-xbb.Tpo $(DEPDIR)/xdvipdfmx-xbb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xbb.c' object='xdvipdfmx-xbb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xsrc/xdvipdfmx-xbb.obj `if test -f 'xsrc/xbb.c'; then $(CYGPATH_W) 'xsrc/xbb.c'; else $(CYGPATH_W) '$(srcdir)/xsrc/xbb.c'; fi` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xdvipdfmx_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xdvipdfmx-xbb.obj `if test -f 'xbb.c'; then $(CYGPATH_W) 'xbb.c'; else $(CYGPATH_W) '$(srcdir)/xbb.c'; fi` mostlyclean-libtool: -rm -f *.lo @@ -3455,10 +3296,6 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -rm -f src/$(DEPDIR)/$(am__dirstamp) - -rm -f src/$(am__dirstamp) - -rm -f xsrc/$(DEPDIR)/$(am__dirstamp) - -rm -f xsrc/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @@ -3471,7 +3308,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool \ distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) src/$(DEPDIR) xsrc/$(DEPDIR) + -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags @@ -3523,7 +3360,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) src/$(DEPDIR) xsrc/$(DEPDIR) + -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/Build/source/texk/dvipdfm-x/cff.c b/Build/source/texk/dvipdfm-x/cff.c index 2b8201d985c..c9ee6b80b94 100644 --- a/Build/source/texk/dvipdfm-x/cff.c +++ b/Build/source/texk/dvipdfm-x/cff.c @@ -47,13 +47,11 @@ #define SFONT_OR_STREAM sfont #define get_card8(s) sfnt_get_byte((s)) #define get_card16(s) sfnt_get_ushort((s)) -#define cff_read(d, l) sfnt_read(d, l, cff->sfont) #else #define SFNT_OR_FILE FILE #define SFONT_OR_STREAM stream #define get_card8(s) get_unsigned_byte((s)) #define get_card16(s) get_unsigned_pair((s)) -#define cff_read(d, l) fread(d, 1, l, cff->stream) #endif static unsigned long get_unsigned (SFNT_OR_FILE *SFONT_OR_STREAM, int n) @@ -375,7 +373,7 @@ cff_get_index (cff_font *cff) idx->data = NEW(length, card8); offset = 0; while (length > 0) { - nb_read = cff_read(idx->data + offset, length); + nb_read = cff_read_data(idx->data + offset, length, cff); offset += nb_read; length -= nb_read; } @@ -1468,7 +1466,7 @@ long cff_read_private (cff_font *cff) offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1); cff_seek_set(cff, offset); data = NEW(size, card8); - if (cff_read(data, size) != size) + if (cff_read_data(data, size, cff) != size) ERROR("reading file failed"); (cff->private)[i] = cff_dict_unpack(data, data+size); RELEASE(data); @@ -1485,7 +1483,7 @@ long cff_read_private (cff_font *cff) offset = (long) cff_dict_get(cff->topdict, "Private", 1); cff_seek_set(cff, offset); data = NEW(size, card8); - if (cff_read(data, size) != size) + if (cff_read_data(data, size, cff) != size) ERROR("reading file failed"); cff->private[0] = cff_dict_unpack(data, data+size); RELEASE(data); diff --git a/Build/source/texk/dvipdfm-x/cff.h b/Build/source/texk/dvipdfm-x/cff.h index e7598b9ff48..4765c6e337e 100644 --- a/Build/source/texk/dvipdfm-x/cff.h +++ b/Build/source/texk/dvipdfm-x/cff.h @@ -93,9 +93,15 @@ typedef struct #ifdef XETEX extern cff_font *cff_open (sfnt *sfont, long offset, int idx); #define cff_seek_set(c, p) sfnt_seek_set (((c)->sfont), ((c)->offset) + (p)); +#define cff_read_data(d, l, c) sfnt_read(d, l, (c)->sfont) +#define cff_tell(c) (c)->sfont->loc +#define cff_seek(c, p) sfnt_seek_set((c)->sfont, p) #else extern cff_font *cff_open (FILE *file, long offset, int idx); #define cff_seek_set(c, p) seek_absolute (((c)->stream), ((c)->offset) + (p)); +#define cff_read_data(d, l, c) fread(d, 1, l, (c)->stream) +#define cff_tell(c) ftell((c)->stream) +#define cff_seek(c, p) seek_absolute((c)->stream, p) #endif extern void cff_close (cff_font *cff); diff --git a/Build/source/texk/dvipdfm-x/cidtype0.c b/Build/source/texk/dvipdfm-x/cidtype0.c new file mode 100644 index 00000000000..b292fe78d26 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/cidtype0.c @@ -0,0 +1,2092 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team. + + 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. +*/ + +/* + * CID-Keyed Font support: + * + * Only CFF/OpenType CID-Keyed Font with Type 2 charstrings is supported. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "numbers.h" +#include "mem.h" +#include "error.h" + +#include "dpxfile.h" + +#include "pdfobj.h" +/* pseudo unique tag */ +#include "pdffont.h" + +/* Font info. from OpenType tables */ +#include "sfnt.h" +#include "tt_aux.h" +/* Metrics */ +#include "tt_table.h" + +#include "cff_types.h" +#include "cff_limits.h" +#include "cff.h" +#include "cff_dict.h" +#include "cs_type2.h" + +/* typedef CID in cmap.h */ +#include "cmap.h" +#include "type0.h" +#include "cid.h" +#include "cid_p.h" +#include "cidtype0.h" + +static int verbose = 0; +static long opt_flags = 0; + +void +CIDFont_type0_set_verbose (void) +{ + verbose++; +} + +void +CIDFont_type0_set_flags (long flags) +{ + opt_flags = flags; +} + +/* + * PDF Reference 3rd. ed., p.340, "Glyph Metrics in CID Fonts". + */ +#ifndef PDFUNIT +#define PDFUNIT(v) (ROUND((1000.0*(v))/(head->unitsPerEm),1)) +#endif + +static void +add_CIDHMetrics (sfnt *sfont, pdf_obj *fontdict, + unsigned char *CIDToGIDMap, unsigned short last_cid, + struct tt_maxp_table *maxp, + struct tt_head_table *head, struct tt_longMetrics *hmtx) +{ + pdf_obj *w_array, *an_array = NULL; + long cid, start = 0, prev = 0; + double defaultAdvanceWidth; + int empty = 1; + + defaultAdvanceWidth = PDFUNIT(hmtx[0].advance); + /* + * We alway use format: + * c [w_1 w_2 ... w_n] + */ + w_array = pdf_new_array(); + for (cid = 0; cid <= last_cid; cid++) { + USHORT gid; + double advanceWidth; + gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; + if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) + continue; + advanceWidth = PDFUNIT(hmtx[gid].advance); + if (advanceWidth == defaultAdvanceWidth) { + if (an_array) { + pdf_add_array(w_array, pdf_new_number(start)); + pdf_add_array(w_array, an_array); + an_array = NULL; + empty = 0; + } + } else { + if (cid != prev + 1 && an_array) { + pdf_add_array(w_array, pdf_new_number(start)); + pdf_add_array(w_array, an_array); + an_array = NULL; + empty = 0; + } + if (an_array == NULL) { + an_array = pdf_new_array(); + start = cid; + } + pdf_add_array(an_array, pdf_new_number(advanceWidth)); + prev = cid; + } + } + + if (an_array) { + pdf_add_array(w_array, pdf_new_number(start)); + pdf_add_array(w_array, an_array); + empty = 0; + } + + /* + * We always write DW for older MacOS X's preview app. + * PDF Reference 2nd. ed, wrongly described default value of DW as 0, and + * MacOS X's (up to 10.2.8) preview app. implements this wrong description. + */ + pdf_add_dict(fontdict, + pdf_new_name("DW"), + pdf_new_number(defaultAdvanceWidth)); + if (!empty) { + pdf_add_dict(fontdict, + pdf_new_name("W"), + pdf_ref_obj(w_array)); + } + pdf_release_obj(w_array); + + return; +} + +static void +add_CIDVMetrics (sfnt *sfont, pdf_obj *fontdict, + unsigned char *CIDToGIDMap, unsigned short last_cid, + struct tt_maxp_table *maxp, + struct tt_head_table *head, struct tt_longMetrics *hmtx) +{ + pdf_obj *w2_array, *an_array = NULL; + long cid; +#if 0 + long prev = 0, start = 0; +#endif + struct tt_VORG_table *vorg; + struct tt_vhea_table *vhea = NULL; + struct tt_longMetrics *vmtx = NULL; + double defaultAdvanceHeight, defaultVertOriginY; + int empty = 1; + + /* + * No accurate vertical metrics can be obtained by simple way if the + * font does not have VORG table. Only CJK fonts may have VORG. + */ + if (sfnt_find_table_pos(sfont, "VORG") <= 0) + return; + + vorg = tt_read_VORG_table(sfont); + defaultVertOriginY = PDFUNIT(vorg->defaultVertOriginY); + if (sfnt_find_table_pos(sfont, "vhea") > 0) + 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, vhea->numOfExSideBearings); + } + + if (sfnt_find_table_pos(sfont, "OS/2") <= 0) { + struct tt_os2__table *os2; + /* OpenType font must have OS/2 table. */ + os2 = tt_read_os2__table(sfont); + defaultVertOriginY = PDFUNIT(os2->sTypoAscender); + defaultAdvanceHeight = PDFUNIT(os2->sTypoAscender - os2->sTypoDescender); + RELEASE(os2); + } else { + /* Some TrueType fonts used in Macintosh does not have OS/2 table. */ + defaultAdvanceHeight = 1000; + } + + w2_array = pdf_new_array(); + for (cid = 0; cid <= last_cid; cid++) { + USHORT i, gid; + double advanceHeight, vertOriginX, vertOriginY; + gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; + if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) + continue; + advanceHeight = vmtx ? PDFUNIT(vmtx[gid].advance) : defaultAdvanceHeight; + vertOriginX = PDFUNIT(hmtx[gid].advance*0.5); + vertOriginY = defaultVertOriginY; + for (i = 0; + i < vorg->numVertOriginYMetrics && gid > vorg->vertOriginYMetrics[i].glyphIndex; + i++) { + if (gid == vorg->vertOriginYMetrics[i].glyphIndex) + vertOriginY = PDFUNIT(vorg->vertOriginYMetrics[i].vertOriginY); + } +#if 0 + /* + * c [w1_1y v_1x v_1y w1_2y v_2x v_2y ...] + * Not working... Why? + * Acrobat Reader: + * Wrong rendering, interpretation of position vector is wrong. + * Xpdf and gs: ignores W2? + */ + if (vertOriginY == defaultVertOriginY && + advanceHeight == defaultAdvanceHeight) { + if (an_array) { + pdf_add_array(w2_array, pdf_new_number(start)); + pdf_add_array(w2_array, an_array); + an_array = NULL; + empty = 0; + } + } else { + if (cid != prev + 1 && an_array) { + pdf_add_array(w2_array, pdf_new_number(start)); + pdf_add_array(w2_array, an_array); + an_array = NULL; + empty = 0; + } + if (an_array == NULL) { + an_array = pdf_new_array(); + start = cid; + } + pdf_add_array(an_array, pdf_new_number(-advanceHeight)); + pdf_add_array(an_array, pdf_new_number(vertOriginX)); + pdf_add_array(an_array, pdf_new_number(vertOriginY)); + prev = cid; + } +#else + /* + * c_first c_last w1_y v_x v_y + * This form may hit Acrobat's implementation limit of array element size, 8192. + * AFPL GhostScript 8.11 stops with rangecheck error with this. Maybe GS's bug? + */ + if (vertOriginY != defaultVertOriginY || + advanceHeight != defaultAdvanceHeight) { + pdf_add_array(w2_array, pdf_new_number(cid)); + pdf_add_array(w2_array, pdf_new_number(cid)); + pdf_add_array(w2_array, pdf_new_number(-advanceHeight)); + pdf_add_array(w2_array, pdf_new_number(vertOriginX)); + pdf_add_array(w2_array, pdf_new_number(vertOriginY)); + empty = 0; + } +#endif + } + +#if 0 + if (an_array) { + pdf_add_array(w2_array, pdf_new_number(start)); + pdf_add_array(w2_array, an_array); + empty = 0; + } +#endif + + if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) { + an_array = pdf_new_array(); + pdf_add_array(an_array, pdf_new_number(defaultVertOriginY)); + pdf_add_array(an_array, pdf_new_number(-defaultAdvanceHeight)); + pdf_add_dict(fontdict, pdf_new_name ("DW2"), an_array); + } + if (!empty) { + pdf_add_dict(fontdict, + pdf_new_name("W2"), pdf_ref_obj(w2_array)); + } + pdf_release_obj(w2_array); + + if (vorg->vertOriginYMetrics) + RELEASE(vorg->vertOriginYMetrics); + RELEASE(vorg); + + if (vmtx) + RELEASE(vmtx); + if (vhea) + RELEASE(vhea); + + return; +} + +static void +add_CIDMetrics (sfnt *sfont, pdf_obj *fontdict, + unsigned char *CIDToGIDMap, unsigned short last_cid, int need_vmetrics) +{ + struct tt_longMetrics *hmtx; + struct tt_head_table *head; + struct tt_hhea_table *hhea; + struct tt_maxp_table *maxp; + + /* + * Read head, hhea, maxp: + * + * unitsPerEm --> head + * numHMetrics --> hhea + * numGlyphs --> maxp + */ + head = tt_read_head_table(sfont); + maxp = tt_read_maxp_table(sfont); + hhea = tt_read_hhea_table(sfont); + + sfnt_locate_table(sfont, "hmtx"); + hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); + + add_CIDHMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); + if (need_vmetrics) + add_CIDVMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); + + RELEASE(hmtx); + RELEASE(hhea); + RELEASE(maxp); + RELEASE(head); + + return; +} + +/* + * Create an instance of embeddable font. + */ +static long +write_fontfile (CIDFont *font, cff_font *cffont) +{ + cff_index *topdict, *fdarray, *private; + unsigned char *dest; + long destlen = 0, i, size; + long offset, topdict_offset, fdarray_offset; + + /* DICT sizes (offset set to long int) */ + topdict = cff_new_index(1); + fdarray = cff_new_index(cffont->num_fds); + private = cff_new_index(cffont->num_fds); + + cff_dict_remove(cffont->topdict, "UniqueID"); + cff_dict_remove(cffont->topdict, "XUID"); + cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */ + cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */ + + topdict->offset[1] = cff_dict_pack(cffont->topdict, + (card8 *) work_buffer, + WORK_BUFFER_SIZE) + 1; + for (i = 0;i < cffont->num_fds; i++) { + size = 0; + if (cffont->private && cffont->private[i]) { + size = cff_dict_pack(cffont->private[i], + (card8 *) work_buffer, WORK_BUFFER_SIZE); + if (size < 1) { /* Private had contained only Subr */ + cff_dict_remove(cffont->fdarray[i], "Private"); + } + } + (private->offset)[i+1] = (private->offset)[i] + size; + (fdarray->offset)[i+1] = (fdarray->offset)[i] + + cff_dict_pack(cffont->fdarray[i], + (card8 *) work_buffer, WORK_BUFFER_SIZE); + } + + destlen = 4; /* header size */ + destlen += cff_set_name(cffont, font->fontname); + destlen += cff_index_size(topdict); + destlen += cff_index_size(cffont->string); + destlen += cff_index_size(cffont->gsubr); + destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */ + destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */ + destlen += cff_index_size(cffont->cstrings); + destlen += cff_index_size(fdarray); + destlen += private->offset[private->count] - 1; /* Private is not INDEX */ + + dest = NEW(destlen, card8); + + offset = 0; + /* Header */ + offset += cff_put_header(cffont, dest + offset, destlen - offset); + /* Name */ + offset += cff_pack_index(cffont->name, dest + offset, destlen - offset); + /* Top DICT */ + topdict_offset = offset; + offset += cff_index_size(topdict); + /* Strings */ + offset += cff_pack_index(cffont->string, dest + offset, destlen - offset); + /* Global Subrs */ + offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset); + + /* charset */ + cff_dict_set(cffont->topdict, "charset", 0, offset); + offset += cff_pack_charsets(cffont, dest + offset, destlen - offset); + + /* FDSelect */ + cff_dict_set(cffont->topdict, "FDSelect", 0, offset); + offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset); + + /* CharStrings */ + cff_dict_set(cffont->topdict, "CharStrings", 0, offset); + offset += cff_pack_index(cffont->cstrings, + dest + offset, cff_index_size(cffont->cstrings)); + cff_release_index(cffont->cstrings); + cffont->cstrings = NULL; /* Charstrings cosumes huge memory */ + + /* FDArray and Private */ + cff_dict_set(cffont->topdict, "FDArray", 0, offset); + fdarray_offset = offset; + offset += cff_index_size(fdarray); + + fdarray->data = NEW(fdarray->offset[fdarray->count] - 1, card8); + for (i = 0; i < cffont->num_fds; i++) { + size = private->offset[i+1] - private->offset[i]; + if (cffont->private[i] && size > 0) { + cff_dict_pack(cffont->private[i], dest + offset, size); + cff_dict_set(cffont->fdarray[i], "Private", 0, size); + cff_dict_set(cffont->fdarray[i], "Private", 1, offset); + } + cff_dict_pack(cffont->fdarray[i], + fdarray->data + (fdarray->offset)[i] - 1, + fdarray->offset[fdarray->count] - 1); + offset += size; + } + + cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray)); + cff_release_index(fdarray); + cff_release_index(private); + + /* Finally Top DICT */ + topdict->data = NEW(topdict->offset[topdict->count] - 1, card8); + cff_dict_pack(cffont->topdict, + topdict->data, topdict->offset[topdict->count] - 1); + cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict)); + cff_release_index(topdict); + + /* + * FontFile + */ + { + pdf_obj *fontfile, *stream_dict; + + fontfile = pdf_new_stream(STREAM_COMPRESS); + stream_dict = pdf_stream_dict(fontfile); + pdf_add_dict(font->descriptor, + pdf_new_name("FontFile3"), + pdf_ref_obj (fontfile)); + pdf_add_dict(stream_dict, + pdf_new_name("Subtype"), + pdf_new_name("CIDFontType0C")); + pdf_add_stream(fontfile, (char *) dest, offset); + pdf_release_obj(fontfile); + RELEASE(dest); + } + + return destlen; +} + +void +CIDFont_type0_dofont (CIDFont *font) +{ + sfnt *sfont; + cff_font *cffont; + FILE *fp = NULL; + cff_index *charstrings, *idx; + cff_charsets *charset = NULL; + cff_fdselect *fdselect = NULL; + long charstring_len, max_len; + long destlen = 0; + long size, offset = 0; + card8 *data; + card16 num_glyphs, gid; + long cid, cid_count; + card16 cs_count, last_cid; + int fd, prev_fd, parent_id; + char *used_chars; + unsigned char *CIDToGIDMap = NULL; + + ASSERT(font); + + if (!font->indirect) + return; + + pdf_add_dict(font->fontdict, + pdf_new_name("FontDescriptor"), + pdf_ref_obj (font->descriptor)); + + if (CIDFont_is_BaseFont(font)) + return; + else if (!CIDFont_get_embedding(font) && + (opt_flags & CIDFONT_FORCE_FIXEDPITCH)) { + /* No metrics needed. */ + pdf_add_dict(font->fontdict, + pdf_new_name("DW"), pdf_new_number(1000.0)); + return; + } + + if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && + (parent_id = CIDFont_get_parent_id(font, 1)) < 0) + ERROR("No parent Type 0 font !"); + + used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); + if (!used_chars) + ERROR("Unexpected error: Font not actually used???"); + +#ifdef XETEX + sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); +#else + fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); + if (!fp) + ERROR("Could not open OpenType font file: %s", font->ident); + sfont = sfnt_open(fp); +#endif + if (!sfont) + ERROR("Could not open OpenType font file: %s", font->ident); + + if (sfnt_read_table_directory(sfont, 0) < 0 || + sfont->type != SFNT_TYPE_POSTSCRIPT) + ERROR("Not a CFF/OpenType font ?"); + offset = sfnt_find_table_pos(sfont, "CFF "); + if (offset == 0) + ERROR("Not a CFF/OpenType font ?"); + +#ifdef XETEX + cffont = cff_open(sfont, offset, font->options->index); +#else + cffont = cff_open(fp, offset, font->options->index); +#endif + if (!cffont) + ERROR("Could not open CFF font."); + if (!(cffont->flag & FONTTYPE_CIDFONT)) + ERROR("Not a CIDFont."); + + if (cff_dict_known(cffont->topdict, "CIDCount")) { + cid_count = (long) cff_dict_get(cffont->topdict, "CIDCount", 0); + } else { + cid_count = CID_MAX + 1; + } + + cff_read_charsets(cffont); + CIDToGIDMap = NEW(2*cid_count, unsigned char); + memset(CIDToGIDMap, 0, 2*cid_count); + add_to_used_chars2(used_chars, 0); /* .notdef */ + cid = 0; last_cid = 0; num_glyphs = 0; + for (cid = 0; cid <= CID_MAX; cid++) { + if (is_used_char2(used_chars, cid)) { + gid = cff_charsets_lookup(cffont, (card16)cid); + if (cid != 0 && gid == 0) { + WARN("Glyph for CID %u missing in font \"%s\".", (CID) cid, font->ident); + used_chars[cid/8] &= ~(1 << (7 - (cid % 8))); + continue; + } + CIDToGIDMap[2*cid] = (gid >> 8) & 0xff; + CIDToGIDMap[2*cid+1] = gid & 0xff; + last_cid = cid; + num_glyphs++; + } + } + + /* + * DW, W, DW2 and W2: + * Those values are obtained from OpenType table (not TFM). + */ + if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) { + pdf_add_dict(font->fontdict, + pdf_new_name("DW"), pdf_new_number(1000.0)); + } else { + add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, + ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); + } + + if (!CIDFont_get_embedding(font)) { + RELEASE(CIDToGIDMap); + cff_close(cffont); + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return; + } + + /* + * Embed font subset. + */ + cff_read_fdselect(cffont); + cff_read_fdarray(cffont); + cff_read_private(cffont); + + cff_read_subrs(cffont); + + offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); + cff_seek_set(cffont, offset); + idx = cff_get_index_header(cffont); + /* offset is now absolute offset ... bad */ + offset = cff_tell(cffont); + + if ((cs_count = idx->count) < 2) { + ERROR("No valid charstring data found."); + } + + /* New Charsets data */ + charset = NEW(1, cff_charsets); + charset->format = 0; + charset->num_entries = 0; + charset->data.glyphs = NEW(num_glyphs, s_SID); + + /* New FDSelect data */ + fdselect = NEW(1, cff_fdselect); + fdselect->format = 3; + fdselect->num_entries = 0; + fdselect->data.ranges = NEW(num_glyphs, cff_range3); + + /* New CharStrings INDEX */ + charstrings = cff_new_index((card16)(num_glyphs+1)); + max_len = 2 * CS_STR_LEN_MAX; + charstrings->data = NEW(max_len, card8); + charstring_len = 0; + + /* + * TODO: Re-assign FD number. + */ + prev_fd = -1; gid = 0; + data = NEW(CS_STR_LEN_MAX, card8); + for (cid = 0; cid <= last_cid; cid++) { + unsigned short gid_org; + + if (!is_used_char2(used_chars, cid)) + continue; + + gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]); + if ((size = (idx->offset)[gid_org+1] - (idx->offset)[gid_org]) + > CS_STR_LEN_MAX) + ERROR("Charstring too long: gid=%u", gid_org); + if (charstring_len + CS_STR_LEN_MAX >= max_len) { + max_len = charstring_len + 2 * CS_STR_LEN_MAX; + charstrings->data = RENEW(charstrings->data, max_len, card8); + } + (charstrings->offset)[gid] = charstring_len + 1; + cff_seek(cffont, offset + (idx->offset)[gid_org] - 1); + cff_read_data(data, size, cffont); + fd = cff_fdselect_lookup(cffont, gid_org); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, (cffont->subrs)[fd], 0, 0, NULL); + if (cid > 0 && gid_org > 0) { + charset->data.glyphs[charset->num_entries] = cid; + charset->num_entries += 1; + } + if (fd != prev_fd) { + fdselect->data.ranges[fdselect->num_entries].first = gid; + fdselect->data.ranges[fdselect->num_entries].fd = fd; + fdselect->num_entries += 1; + prev_fd = fd; + } + gid++; + } + if (gid != num_glyphs) + ERROR("Unexpeced error: ?????"); + RELEASE(data); + cff_release_index(idx); + + RELEASE(CIDToGIDMap); + + (charstrings->offset)[num_glyphs] = charstring_len + 1; + charstrings->count = num_glyphs; + cffont->num_glyphs = num_glyphs; + cffont->cstrings = charstrings; + + /* discard old one, set new data */ + cff_release_charsets(cffont->charsets); + cffont->charsets = charset; + cff_release_fdselect(cffont->fdselect); + cffont->fdselect = fdselect; + + /* no Global subr */ + if (cffont->gsubr) + cff_release_index(cffont->gsubr); + cffont->gsubr = cff_new_index(0); + + for (fd = 0; fd < cffont->num_fds; fd++) { + if (cffont->subrs && cffont->subrs[fd]) { + cff_release_index(cffont->subrs[fd]); + cffont->subrs[fd] = NULL; + } + if (cffont->private && (cffont->private)[fd]) { + cff_dict_remove((cffont->private)[fd], "Subrs"); /* no Subrs */ + } + } + + destlen = write_fontfile(font, cffont); + + cff_close(cffont); + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + if (verbose > 1) + MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, destlen); + + /* + * CIDSet: + * Length of CIDSet stream is not clear. Must be 8192 bytes long? + */ + { + pdf_obj *cidset; + + cidset = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(cidset, used_chars, (last_cid/8)+1); + pdf_add_dict(font->descriptor, + pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); + pdf_release_obj(cidset); + } + + return; +} + +int +CIDFont_type0_open (CIDFont *font, const char *name, + CIDSysInfo *cmap_csi, cid_opt *opt) +{ + CIDSysInfo *csi; + char *fontname; + sfnt *sfont; + cff_font *cffont; + FILE *fp = NULL; + unsigned long offset = 0; + + ASSERT(font); + +#ifdef XETEX + sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); + if (!sfont) + return -1; +#else + fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); + if (!fp) + return -1; + + sfont = sfnt_open(fp); + if (!sfont) { + ERROR("Not a CFF/OpenType font?"); + } +#endif + if (sfont->type != SFNT_TYPE_POSTSCRIPT || + sfnt_read_table_directory(sfont, 0) < 0 || + (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { + ERROR("Not a CFF/OpenType font?"); + } + +#ifdef XETEX + cffont = cff_open(sfont, offset, opt->index); +#else + cffont = cff_open(sfont->stream, offset, opt->index); +#endif + if (!cffont) { + ERROR("Cannot read CFF font data"); + } + + if (!(cffont->flag & FONTTYPE_CIDFONT)) { + cff_close(cffont); + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + return -1; + } + + csi = NEW(1, CIDSysInfo); + csi->registry = + cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 0)); + csi->ordering = + cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 1)); + csi->supplement = (int)cff_dict_get(cffont->topdict, "ROS", 2); + + if (cmap_csi) { + if (strcmp(csi->registry, cmap_csi->registry) != 0 || + strcmp(csi->ordering, cmap_csi->ordering) != 0) { + MESG("\nCharacter collection mismatched:\n"); + MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); + MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); + ERROR("Inconsistent CMap specified for this font."); + } + if (csi->supplement < cmap_csi->supplement) { + WARN("CMap have higher supplmement number."); + WARN("Some characters may not be displayed or printed."); + } + } + + { + char *shortname; + + shortname = cff_get_name(cffont); + if (!shortname) + ERROR("No valid FontName found."); + /* + * Mangled name requires more 7 bytes. + * Style requires more 11 bytes. + */ + fontname = NEW(strlen(shortname)+19, char); + memset(fontname, 0, strlen(shortname)+19); + strcpy(fontname, shortname); + RELEASE(shortname); + } + cff_close(cffont); + + if (opt->embed && opt->style != FONT_STYLE_NONE) { + WARN("Embedding disabled due to style option for %s.", name); + opt->embed = 0; + } + switch (opt->style) { + case FONT_STYLE_BOLD: + strcat(fontname, ",Bold"); + break; + case FONT_STYLE_ITALIC: + strcat(fontname, ",Italic"); + break; + case FONT_STYLE_BOLDITALIC: + strcat(fontname, ",BoldItalic"); + break; + } + + font->fontname = fontname; + font->subtype = CIDFONT_TYPE0; + font->csi = csi; + + font->fontdict = pdf_new_dict(); + pdf_add_dict(font->fontdict, + pdf_new_name("Type"), + pdf_new_name("Font")); + pdf_add_dict(font->fontdict, + pdf_new_name("Subtype"), + pdf_new_name("CIDFontType0")); + + /* getting font info. from TrueType tables */ + if ((font->descriptor + = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) + ERROR("Could not obtain necessary font info."); + + if (opt->embed) { + memmove(fontname + 7, fontname, strlen(fontname) + 1); + pdf_font_make_uniqueTag(fontname); + fontname[6] = '+'; + } + + pdf_add_dict(font->descriptor, + pdf_new_name("FontName"), + pdf_new_name(fontname)); + pdf_add_dict(font->fontdict, + pdf_new_name("BaseFont"), + pdf_new_name(fontname)); + { + pdf_obj *csi_dict = pdf_new_dict(); + pdf_add_dict(csi_dict, + pdf_new_name("Registry"), + pdf_new_string(csi->registry, strlen(csi->registry))); + pdf_add_dict(csi_dict, + pdf_new_name("Ordering"), + pdf_new_string(csi->ordering, strlen(csi->ordering))); + pdf_add_dict(csi_dict, + pdf_new_name("Supplement"), + pdf_new_number(csi->supplement)); + pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); + } + pdf_add_dict(font->fontdict, + pdf_new_name("DW"), + pdf_new_number(1000)); /* not sure */ + + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return 0; +} + +void +CIDFont_type0_t1cdofont (CIDFont *font) +{ + sfnt *sfont; + cff_font *cffont; + cff_index *charstrings, *idx; + long charstring_len, max_len; + long destlen = 0; + long size, offset = 0; + card8 *data; + card16 num_glyphs, gid, last_cid; + long i, cid; + int parent_id; + char *used_chars; + double default_width, nominal_width; + FILE *fp = NULL; + + ASSERT(font); + + if (!font->indirect) + return; + + pdf_add_dict(font->fontdict, + pdf_new_name("FontDescriptor"), + pdf_ref_obj (font->descriptor)); + + if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && + (parent_id = CIDFont_get_parent_id(font, 1)) < 0) + ERROR("No parent Type 0 font !"); + + used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); + if (!used_chars) + ERROR("Unexpected error: Font not actually used???"); + +#ifdef XETEX + sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); +#else + fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); + if (!fp) + ERROR("Could not open OpenType font file: %s", font->ident); + + sfont = sfnt_open(fp); +#endif + if (!sfont) + ERROR("Could not open OpenType font file: %s", font->ident); + + if (sfnt_read_table_directory(sfont, 0) < 0 || + sfont->type != SFNT_TYPE_POSTSCRIPT) + ERROR("Not a CFF/OpenType font ?"); + offset = sfnt_find_table_pos(sfont, "CFF "); + if (offset == 0) + ERROR("Not a CFF/OpenType font ?"); + +#ifdef XETEX + cffont = cff_open(sfont, offset, font->options->index); +#else + cffont = cff_open(fp, offset, font->options->index); +#endif + if (!cffont) + ERROR("Could not open CFF font."); + if (cffont->flag & FONTTYPE_CIDFONT) + ERROR("This is CIDFont..."); + + cff_read_private(cffont); + cff_read_subrs (cffont); + + if (cffont->private[0] && cff_dict_known(cffont->private[0], "StdVW")) { + double stemv; + stemv = cff_dict_get(cffont->private[0], "StdVW", 0); + pdf_add_dict(font->descriptor, + pdf_new_name("StemV"), pdf_new_number(stemv)); + } + if (cffont->private[0] && cff_dict_known(cffont->private[0], "defaultWidthX")) { + default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); + } else { + default_width = CFF_DEFAULTWIDTHX_DEFAULT; + } + if (cffont->private[0] && cff_dict_known(cffont->private[0], "nominalWidthX")) { + nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); + } else { + nominal_width = CFF_NOMINALWIDTHX_DEFAULT; + } + + num_glyphs = 0; last_cid = 0; + add_to_used_chars2(used_chars, 0); /* .notdef */ + for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { + int c, j; + + c = used_chars[i]; + for (j = 7; j >= 0; j--) { + if (c & (1 << j)) { + num_glyphs++; + last_cid = (i + 1) * 8 - j - 1; + } + } + } + + { + cff_fdselect *fdselect; + + fdselect = NEW(1, cff_fdselect); + fdselect->format = 3; + fdselect->num_entries = 1; + fdselect->data.ranges = NEW(1, cff_range3); + fdselect->data.ranges[0].first = 0; + fdselect->data.ranges[0].fd = 0; + cffont->fdselect = fdselect; + } + + { + cff_charsets *charset; + + charset = NEW(1, cff_charsets); + charset->format = 0; + charset->num_entries = num_glyphs-1; + charset->data.glyphs = NEW(num_glyphs-1, s_SID); + + for (gid = 0, cid = 0; cid <= last_cid; cid++) { + if (is_used_char2(used_chars, cid)) { + if (gid > 0) + charset->data.glyphs[gid-1] = cid; + gid++; + } + } + /* cff_release_charsets(cffont->charsets); */ + cffont->charsets = charset; + } + + cff_dict_add(cffont->topdict, "CIDCount", 1); + cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); + + cffont->fdarray = NEW(1, cff_dict *); + cffont->fdarray[0] = cff_new_dict(); + cff_dict_add(cffont->fdarray[0], "FontName", 1); + cff_dict_set(cffont->fdarray[0], "FontName", 0, + (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ + cff_dict_add(cffont->fdarray[0], "Private", 2); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + /* FDArray - index offset, not known yet */ + cff_dict_add(cffont->topdict, "FDArray", 1); + cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); + /* FDSelect - offset, not known yet */ + cff_dict_add(cffont->topdict, "FDSelect", 1); + cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); + + cff_dict_remove(cffont->topdict, "UniqueID"); + cff_dict_remove(cffont->topdict, "XUID"); + cff_dict_remove(cffont->topdict, "Private"); + cff_dict_remove(cffont->topdict, "Encoding"); + + + /* */ + offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); + cff_seek_set(cffont, offset); + idx = cff_get_index_header(cffont); + /* offset is now absolute offset ... bad */ + offset = cff_tell(cffont); + + if (idx->count < 2) + ERROR("No valid charstring data found."); + + /* New CharStrings INDEX */ + charstrings = cff_new_index((card16)(num_glyphs+1)); + max_len = 2 * CS_STR_LEN_MAX; + charstrings->data = NEW(max_len, card8); + charstring_len = 0; + + gid = 0; + data = NEW(CS_STR_LEN_MAX, card8); + for (cid = 0; cid <= last_cid; cid++) { + if (!is_used_char2(used_chars, cid)) + continue; + + if ((size = (idx->offset)[cid+1] - (idx->offset)[cid]) + > CS_STR_LEN_MAX) + ERROR("Charstring too long: gid=%u", cid); + if (charstring_len + CS_STR_LEN_MAX >= max_len) { + max_len = charstring_len + 2 * CS_STR_LEN_MAX; + charstrings->data = RENEW(charstrings->data, max_len, card8); + } + (charstrings->offset)[gid] = charstring_len + 1; + cff_seek(cffont, offset + (idx->offset)[cid] - 1); + cff_read_data(data, size, cffont); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, (cffont->subrs)[0], + default_width, nominal_width, NULL); + gid++; + } + if (gid != num_glyphs) + ERROR("Unexpeced error: ?????"); + RELEASE(data); + cff_release_index(idx); + + (charstrings->offset)[num_glyphs] = charstring_len + 1; + charstrings->count = num_glyphs; + cffont->num_glyphs = num_glyphs; + cffont->cstrings = charstrings; + + /* no Global subr */ + if (cffont->gsubr) + cff_release_index(cffont->gsubr); + cffont->gsubr = cff_new_index(0); + + if (cffont->subrs && cffont->subrs[0]) { + cff_release_index(cffont->subrs[0]); + cffont->subrs[0] = NULL; + } + if (cffont->private && (cffont->private)[0]) { + cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */ + } + + cff_add_string(cffont, "Adobe", 1); + cff_add_string(cffont, "Identity", 1); + + cff_dict_update(cffont->topdict, cffont); + cff_dict_update(cffont->private[0], cffont); + cff_update_string(cffont); + + /* CFF code need to be rewrote... */ + cff_dict_add(cffont->topdict, "ROS", 3); + cff_dict_set(cffont->topdict, "ROS", 0, + (double) cff_get_sid(cffont, "Adobe")); + cff_dict_set(cffont->topdict, "ROS", 1, + (double) cff_get_sid(cffont, "Identity")); + cff_dict_set(cffont->topdict, "ROS", 2, 0.0); + + destlen = write_fontfile(font, cffont); + + cff_close(cffont); + + /* + * DW, W, DW2 and W2: + * Those values are obtained from OpenType table (not TFM). + */ + { + unsigned char *CIDToGIDMap; + + CIDToGIDMap = NEW(2 * (last_cid+1), unsigned char); + memset(CIDToGIDMap, 0, 2 * (last_cid + 1)); + for (cid = 0; cid <= last_cid; cid++) { + if (is_used_char2(used_chars, cid)) { + CIDToGIDMap[2*cid ] = (cid >> 8) & 0xff; + CIDToGIDMap[2*cid+1] = cid & 0xff; + } + } + add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, + ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); + RELEASE(CIDToGIDMap); + } + + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + if (verbose > 1) + MESG("[%u glyphs][%ld bytes]", num_glyphs, destlen); + + /* + * CIDSet: + * Length of CIDSet stream is not clear. Must be 8192 bytes long? + */ + { + pdf_obj *cidset; + + cidset = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(cidset, used_chars, (last_cid/8)+1); + pdf_add_dict(font->descriptor, + pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); + pdf_release_obj(cidset); + } + + return; +} + +int +CIDFont_type0_t1copen (CIDFont *font, const char *name, + CIDSysInfo *cmap_csi, cid_opt *opt) +{ + CIDSysInfo *csi; + char *fontname; + sfnt *sfont; + cff_font *cffont; + unsigned long offset = 0; + FILE *fp = NULL; + + ASSERT(font); + +#ifdef XETEX + sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); + if (!sfont) + return -1; +#else + fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); + if (!fp) + return -1; + + sfont = sfnt_open(fp); +#endif + if (!sfont) { + ERROR("Not a CFF/OpenType font?"); + } + if (sfont->type != SFNT_TYPE_POSTSCRIPT || + sfnt_read_table_directory(sfont, 0) < 0 || + (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { + ERROR("Not a CFF/OpenType font?"); + } + +#ifdef XETEX + cffont = cff_open(sfont, offset, opt->index); +#else + cffont = cff_open(fp, offset, opt->index); +#endif + if (!cffont) { + ERROR("Cannot read CFF font data"); + } + + if (cffont->flag & FONTTYPE_CIDFONT) { + cff_close(cffont); + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return -1; + } + + csi = NEW(1, CIDSysInfo); + csi->registry = NEW(strlen("Adobe")+1, char); + strcpy(csi->registry, "Adobe"); + csi->ordering = NEW(strlen("Identity")+1, char); + strcpy(csi->ordering, "Identity"); + csi->supplement = 0; + + if (cmap_csi) { + if (strcmp(csi->registry, cmap_csi->registry) != 0 || + strcmp(csi->ordering, cmap_csi->ordering) != 0) { + MESG("\nCharacter collection mismatched:\n"); + MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); + MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); + ERROR("Inconsistent CMap specified for this font."); + } + if (csi->supplement < cmap_csi->supplement) { + WARN("CMap have higher supplmement number."); + WARN("Some characters may not be displayed or printed."); + } + } + + { + char *shortname; + + shortname = cff_get_name(cffont); + if (!shortname) + ERROR("No valid FontName found."); + /* Mangled name requires more 7 bytes. */ + + fontname = NEW(strlen(shortname) + 8, char); + memset(fontname, 0, strlen(shortname) + 8); + strcpy(fontname, shortname); + RELEASE(shortname); + } + cff_close(cffont); + + opt->embed = 1; + + font->fontname = fontname; + font->subtype = CIDFONT_TYPE0; + font->csi = csi; + font->flags |= CIDFONT_FLAG_TYPE1C; + + font->fontdict = pdf_new_dict(); + pdf_add_dict(font->fontdict, + pdf_new_name("Type"), + pdf_new_name("Font")); + pdf_add_dict(font->fontdict, + pdf_new_name("Subtype"), + pdf_new_name("CIDFontType0")); + + /* getting font info. from TrueType tables */ + if ((font->descriptor + = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) + ERROR("Could not obtain necessary font info."); + + if (opt->embed) { + memmove(fontname + 7, fontname, strlen(fontname) + 1); + pdf_font_make_uniqueTag(fontname); + fontname[6] = '+'; + } + + pdf_add_dict(font->descriptor, + pdf_new_name("FontName"), + pdf_new_name(fontname)); + pdf_add_dict(font->fontdict, + pdf_new_name("BaseFont"), + pdf_new_name(fontname)); + { + pdf_obj *csi_dict = pdf_new_dict(); + pdf_add_dict(csi_dict, + pdf_new_name("Registry"), + pdf_new_string(csi->registry, strlen(csi->registry))); + pdf_add_dict(csi_dict, + pdf_new_name("Ordering"), + pdf_new_string(csi->ordering, strlen(csi->ordering))); + pdf_add_dict(csi_dict, + pdf_new_name("Supplement"), + pdf_new_number(csi->supplement)); + pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); + } + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return 0; +} + + +/* Type1 --> CFF CIDFont */ +#include "unicode.h" +#include "t1_load.h" +#include "t1_char.h" + +#include "agl.h" + +#include "cmap.h" +#include "cmap_write.h" +#include "fontmap.h" + +static int +load_base_CMap (const char *font_name, int wmode, cff_font *cffont) +{ + int cmap_id = -1; + CMap *cmap; + char *cmap_name; + card16 gid; + unsigned char range_min[4] = {0x00, 0x00, 0x00, 0x00}; + unsigned char range_max[4] = {0x7f, 0xff, 0xff, 0xff}; + + cmap_name = NEW(strlen(font_name)+strlen("-UCS4-H")+1, char); + if (wmode) { + sprintf(cmap_name, "%s-UCS4-V", font_name); + } else { + sprintf(cmap_name, "%s-UCS4-H", font_name); + } + + cmap_id = CMap_cache_find(cmap_name); + if (cmap_id >= 0) { + RELEASE(cmap_name); + return cmap_id; + } + + cmap = CMap_new(); + CMap_set_name (cmap, cmap_name); + CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); + CMap_set_wmode(cmap, wmode); + CMap_add_codespacerange(cmap, range_min, range_max, 4); + CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); + RELEASE(cmap_name); + + for (gid = 1; gid < cffont->num_glyphs; gid++) { + long ucv; + s_SID sid; + char *glyph, *name, *suffix; + unsigned char srcCode[4]; + + sid = cff_charsets_lookup_inverse(cffont, gid); + glyph = cff_get_string (cffont, sid); + + name = agl_chop_suffix(glyph, &suffix); + if (!name) { + if (suffix) + RELEASE(suffix); + RELEASE(glyph); + continue; + } + + if (suffix) { + RELEASE(name); + RELEASE(suffix); + RELEASE(glyph); + continue; + } + + if (agl_name_is_unicode(name)) { + ucv = agl_name_convert_unicode(name); + srcCode[0] = (ucv >> 24) & 0xff; + srcCode[1] = (ucv >> 16) & 0xff; + srcCode[2] = (ucv >> 8) & 0xff; + srcCode[3] = ucv & 0xff; + CMap_add_cidchar(cmap, srcCode, 4, gid); + } else { + agl_name *agln; + + agln = agl_lookup_list(name); + if (!agln) + WARN("Glyph \"%s\" inaccessible (no Unicode mapping)", glyph); + while (agln) { + if (agln->n_components > 1) { + WARN("Glyph \"%s\" inaccessible (composite character)", glyph); + } else if (agln->n_components == 1) { + ucv = agln->unicodes[0]; + srcCode[0] = (ucv >> 24) & 0xff; + srcCode[1] = (ucv >> 16) & 0xff; + srcCode[2] = (ucv >> 8) & 0xff; + srcCode[3] = ucv & 0xff; + CMap_add_cidchar(cmap, srcCode, 4, gid); + } + agln = agln->alternate; + } + } + RELEASE(name); + if (suffix) + RELEASE(suffix); + RELEASE(glyph); + } + cmap_id = CMap_cache_add(cmap); + + return cmap_id; +} + +int +t1_load_UnicodeCMap (const char *font_name, + const char *otl_tags, /* not supported yet */ + int wmode) +{ + int cmap_id = -1; + cff_font *cffont; + FILE *fp; + + if (!font_name) + return -1; + + fp = DPXFOPEN(font_name, DPX_RES_TYPE_T1FONT); + if (!fp) + return -1; + + cffont = t1_load_font(NULL, 1, fp); + DPXFCLOSE(fp); + if (!cffont) + return -1; + + cmap_id = load_base_CMap(font_name, wmode, cffont); + + cff_close(cffont); + + if (cmap_id < 0) { + ERROR("Failed to create Unicode charmap for font \"%s\".", font_name); + return -1; + } + + if (otl_tags) { + WARN("Glyph substitution not supported for Type1 font yet..."); + } + + return cmap_id; +} + + +/* + * ToUnicode CMap + */ + +static pdf_obj * +create_ToUnicode_stream (cff_font *cffont, + const char *font_name, const char *used_glyphs) +{ + pdf_obj *stream = NULL; + CMap *cmap; + CID cid; + card16 gid; + long glyph_count, total_fail_count; + char *cmap_name; +#define WBUF_SIZE 1024 + unsigned char wbuf[WBUF_SIZE]; + unsigned char *p, *endptr; + static unsigned char range_min[2] = {0x00, 0x00}; + static unsigned char range_max[2] = {0xff, 0xff}; + + if (!font_name || !used_glyphs) + return NULL; + + cmap = CMap_new(); + + cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+1, char); + strcpy(cmap_name, font_name); + strcat(cmap_name, "-UTF16"); + CMap_set_name (cmap, cmap_name); + RELEASE(cmap_name); + + CMap_set_wmode(cmap, 0); + CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); + CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); + + CMap_add_codespacerange(cmap, range_min, range_max, 2); + + glyph_count = total_fail_count = 0; + p = wbuf; + endptr = wbuf + WBUF_SIZE; + for (cid = 1; cid < cffont->num_glyphs; cid++) { /* Skip .notdef */ + if (is_used_char2(used_glyphs, cid)) { + char *glyph; + long len; + int fail_count; + + wbuf[0] = (cid >> 8) & 0xff; + wbuf[1] = (cid & 0xff); + + p = wbuf + 2; + gid = cff_charsets_lookup_inverse(cffont, cid); + if (gid == 0) + continue; + glyph = cff_get_string(cffont, gid); + if (glyph) { + len = agl_sput_UTF16BE(glyph, &p, endptr, &fail_count); + if (len < 1 || fail_count) { + total_fail_count += fail_count; + } else { + CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); + } + RELEASE(glyph); + } + glyph_count++; + } + } + + if (total_fail_count != 0 && + total_fail_count >= glyph_count/10) { + WARN("%d glyph names (out of %d) missing Unicode mapping.", + total_fail_count, glyph_count); + WARN("ToUnicode CMap \"%s-UTF16\" removed.", font_name); + } else { + stream = CMap_create_stream(cmap, 0); + } + CMap_release(cmap); + + return stream; +} + + +int +CIDFont_type0_t1open (CIDFont *font, const char *name, + CIDSysInfo *cmap_csi, cid_opt *opt) +{ + FILE *fp; + char *fontname, *shortname; + cff_font *cffont; + + ASSERT(font); + + if (cmap_csi && + (strcmp(cmap_csi->registry, "Adobe") != 0 || + strcmp(cmap_csi->ordering, "Identity") != 0)) { + return -1; + } + fp = DPXFOPEN(name, DPX_RES_TYPE_T1FONT); + if (!fp) + return -1; + + cffont = t1_load_font(NULL, 1, fp); + if (!cffont) { + DPXFCLOSE(fp); + return -1; + } + DPXFCLOSE(fp); + + shortname = cff_get_name(cffont); + if (!shortname) + ERROR("No valid FontName found."); + fontname = NEW(strlen(shortname) + 8, char); + memset(fontname, 0, strlen(shortname) + 8); + strcpy(fontname, shortname); + RELEASE(shortname); + +#ifdef XETEX + font->ft_to_gid = cff_get_ft_to_gid(cffont); + cffont->ft_to_gid = NULL; +#endif + + cff_close(cffont); + + if (opt->style != FONT_STYLE_NONE) { + WARN(",Bold, ,Italic, ... not supported for this type of font..."); + opt->style = FONT_STYLE_NONE; + } + + font->fontname = fontname; + font->subtype = CIDFONT_TYPE0; + font->csi = NEW(1, CIDSysInfo); + font->csi->registry = NEW(strlen("Adobe")+1, char); + strcpy(font->csi->registry, "Adobe"); + font->csi->ordering = NEW(strlen("Identity")+1, char); + strcpy(font->csi->ordering, "Identity"); + font->csi->supplement = 0; + font->flags |= CIDFONT_FLAG_TYPE1; + + font->fontdict = pdf_new_dict(); + pdf_add_dict(font->fontdict, + pdf_new_name("Type"), + pdf_new_name("Font")); + pdf_add_dict(font->fontdict, + pdf_new_name("Subtype"), + pdf_new_name("CIDFontType0")); + + memmove(fontname + 7, fontname, strlen(fontname) + 1); + pdf_font_make_uniqueTag(fontname); + fontname[6] = '+'; + + font->descriptor = pdf_new_dict(); + pdf_add_dict(font->descriptor, + pdf_new_name("FontName"), + pdf_new_name(fontname)); + pdf_add_dict(font->fontdict, + pdf_new_name("BaseFont"), + pdf_new_name(fontname)); + { + pdf_obj *csi_dict; + + csi_dict = pdf_new_dict(); + pdf_add_dict(csi_dict, + pdf_new_name("Registry"), + pdf_new_string("Adobe", strlen("Adobe"))); + pdf_add_dict(csi_dict, + pdf_new_name("Ordering"), + pdf_new_string("Identity", strlen("Identity"))); + pdf_add_dict(csi_dict, + pdf_new_name("Supplement"), + pdf_new_number(0.0)); + pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); + } + + + return 0; +} + +/* Duplicate from type1.c */ +#define TYPE1_NAME_LEN_MAX 127 + +#define FONT_FLAG_FIXEDPITCH (1 << 0) /* Fixed-width font */ +#define FONT_FLAG_SERIF (1 << 1) /* Serif font */ +#define FONT_FLAG_SYMBOLIC (1 << 2) /* Symbolic font */ +#define FONT_FLAG_SCRIPT (1 << 3) /* Script font */ +#define FONT_FLAG_STANDARD (1 << 5) /* Adobe Standard Character Set */ +#define FONT_FLAG_ITALIC (1 << 6) /* Italic */ +#define FONT_FLAG_ALLCAP (1 << 16) /* All-cap font */ +#define FONT_FLAG_SMALLCAP (1 << 17) /* Small-cap font */ +#define FONT_FLAG_FORCEBOLD (1 << 18) /* Force bold at small text sizes */ + +/* pdf_font --> CIDFont */ +static void +get_font_attr (CIDFont *font, cff_font *cffont) +{ + double capheight, ascent, descent; + double italicangle, stemv; + double defaultwidth, nominalwidth; + long flags = 0; + long gid; + int i; + static const char *L_c[] = { + "H", "P", "Pi", "Rho", NULL + }; + static const char *L_d[] = { + "p", "q", "mu", "eta", NULL + }; + static const char *L_a[] = { + "b", "h", "lambda", NULL + }; + t1_ginfo gm; + + defaultwidth = 500.0; + nominalwidth = 0.0; + + /* + * CapHeight, Ascent, and Descent is meaningfull only for Latin/Greek/Cyrillic. + * The BlueValues and OtherBlues also have those information. + */ + if (cff_dict_known(cffont->topdict, "FontBBox")) { + /* Default values */ + capheight = ascent = cff_dict_get(cffont->topdict, "FontBBox", 3); + descent = cff_dict_get(cffont->topdict, "FontBBox", 1); + } else { + capheight = 680.0; + ascent = 690.0; + descent = -190.0; + } + if (cff_dict_known(cffont->private[0], "StdVW")) { + stemv = cff_dict_get(cffont->private[0], "StdVW", 0); + } else { + /* + * We may use the following values for StemV: + * Thin - ExtraLight: <= 50 + * Light: 71 + * Regular(Normal): 88 + * Medium: 109 + * SemiBold(DemiBold): 135 + * Bold - Heavy: >= 166 + */ + stemv = 88.0; + } + if (cff_dict_known(cffont->topdict, "ItalicAngle")) { + italicangle = cff_dict_get(cffont->topdict, "ItalicAngle", 0); + if (italicangle != 0.0) + flags |= FONT_FLAG_ITALIC; + } else { + italicangle = 0.0; + } + + /* + * Use "space", "H", "p", and "b" for various values. + * Those characters should not "seac". (no accent) + */ + gid = cff_glyph_lookup(cffont, "space"); + if (gid >= 0 && gid < cffont->cstrings->count) { + t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, + cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], + cffont->subrs[0], &gm); + defaultwidth = gm.wx; + } + + for (i = 0; L_c[i] != NULL; i++) { + gid = cff_glyph_lookup(cffont, L_c[i]); + if (gid >= 0 && gid < cffont->cstrings->count) { + t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, + cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], + cffont->subrs[0], &gm); + capheight = gm.bbox.ury; + break; + } + } + + for (i = 0; L_d[i] != NULL; i++) { + gid = cff_glyph_lookup(cffont, L_d[i]); + if (gid >= 0 && gid < cffont->cstrings->count) { + t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, + cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], + cffont->subrs[0], &gm); + descent = gm.bbox.lly; + break; + } + } + + for (i = 0; L_a[i] != NULL; i++) { + gid = cff_glyph_lookup(cffont, L_a[i]); + if (gid >= 0 && gid < cffont->cstrings->count) { + t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, + cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], + cffont->subrs[0], &gm); + ascent = gm.bbox.ury; + break; + } + } + + if (defaultwidth != 0.0) { + cff_dict_add(cffont->private[0], "defaultWidthX", 1); + cff_dict_set(cffont->private[0], "defaultWidthX", 0, defaultwidth); + } + if (nominalwidth != 0.0) { + cff_dict_add(cffont->private[0], "nominalWidthX", 1); + cff_dict_set(cffont->private[0], "nominalWidthX", 0, nominalwidth); + } + if (cff_dict_known(cffont->private[0], "ForceBold") && + cff_dict_get(cffont->private[0], "ForceBold", 0)) { + flags |= FONT_FLAG_FORCEBOLD; + } + if (cff_dict_known(cffont->private[0], "IsFixedPitch") && + cff_dict_get(cffont->private[0], "IsFixedPitch", 0)) { + flags |= FONT_FLAG_FIXEDPITCH; + } + if (font->fontname && + !strstr(font->fontname, "Sans")) { + flags |= FONT_FLAG_SERIF; + } + flags |= FONT_FLAG_SYMBOLIC; + + pdf_add_dict(font->descriptor, + pdf_new_name("CapHeight"), pdf_new_number(capheight)); + pdf_add_dict(font->descriptor, + pdf_new_name("Ascent"), pdf_new_number(ascent)); + pdf_add_dict(font->descriptor, + pdf_new_name("Descent"), pdf_new_number(descent)); + pdf_add_dict(font->descriptor, + pdf_new_name("ItalicAngle"), pdf_new_number(italicangle)); + pdf_add_dict(font->descriptor, + pdf_new_name("StemV"), pdf_new_number(stemv)); + pdf_add_dict(font->descriptor, + pdf_new_name("Flags"), pdf_new_number(flags)); +} + +static void +add_metrics (CIDFont *font, cff_font *cffont, + unsigned char *CIDToGIDMap, + double *widths, double default_width, CID last_cid) +{ + pdf_obj *tmp; + double val; + card16 cid, gid; + char *used_chars; + int i, parent_id; + + /* + * The original FontBBox of the font is preserved, instead + * of replacing it with tight bounding box calculated from + * charstrings, to prevent Acrobat 4 from greeking text as + * much as possible. + */ + if (!cff_dict_known(cffont->topdict, "FontBBox")) { + ERROR("No FontBBox?"); + } + tmp = pdf_new_array(); + for (i = 0; i < 4; i++) { + val = cff_dict_get(cffont->topdict, "FontBBox", i); + pdf_add_array(tmp, pdf_new_number(ROUND(val, 1.0))); + } + pdf_add_dict(font->descriptor, pdf_new_name("FontBBox"), tmp); + + if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && + (parent_id = CIDFont_get_parent_id(font, 1)) < 0) + ERROR("No parent Type 0 font !"); + + used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); + if (!used_chars) { + ERROR("Unexpected error: Font not actually used???"); + } + + /* FIXME: + * This writes "CID CID width". + * I think it's better to handle each 8 char block + * and to use "CID_start [ w0 w1 ...]". + */ + tmp = pdf_new_array(); + for (cid = 0; cid <= last_cid; cid++) { + if (is_used_char2(used_chars, cid)) { + gid = (CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]; + if (widths[gid] != default_width) { + pdf_add_array(tmp, pdf_new_number(cid)); + pdf_add_array(tmp, pdf_new_number(cid)); + pdf_add_array(tmp, pdf_new_number(ROUND(widths[gid], 1.0))); + } + } + } + pdf_add_dict(font->fontdict, + pdf_new_name("DW"), pdf_new_number(default_width)); + if (pdf_array_length(tmp) > 0) { + pdf_add_dict(font->fontdict, pdf_new_name("W"), pdf_ref_obj(tmp)); + } + pdf_release_obj(tmp); +} + +void +CIDFont_type0_t1dofont (CIDFont *font) +{ + cff_font *cffont; + double defaultwidth, nominalwidth; + long num_glyphs = 0; + FILE *fp; + long i, offset; + char *used_chars = NULL; + card16 last_cid, gid, cid; + unsigned char *CIDToGIDMap; + + ASSERT(font); + + if (!font->indirect) { + return; + } + + pdf_add_dict(font->fontdict, + pdf_new_name("FontDescriptor"), + pdf_ref_obj (font->descriptor)); + + fp = DPXFOPEN(font->ident, DPX_RES_TYPE_T1FONT); + if (!fp) { + ERROR("Type1: Could not open Type1 font."); + } + + cffont = t1_load_font(NULL, 0, fp); + if (!cffont) + ERROR("Could not read Type 1 font..."); + DPXFCLOSE(fp); + + if (!font->fontname) + ERROR("Fontname undefined..."); + + { + Type0Font *hparent, *vparent; + pdf_obj *tounicode; + int vparent_id, hparent_id; + + hparent_id = CIDFont_get_parent_id(font, 0); + vparent_id = CIDFont_get_parent_id(font, 1); + if (hparent_id < 0 && vparent_id < 0) + ERROR("No parent Type 0 font !"); + + /* usedchars is same for h and v */ + if (hparent_id < 0) + hparent = NULL; + else { + hparent = Type0Font_cache_get(hparent_id); + used_chars = Type0Font_get_usedchars(hparent); + } + if (vparent_id < 0) + vparent = NULL; + else { + vparent = Type0Font_cache_get(vparent_id); + used_chars = Type0Font_get_usedchars(vparent); + } + if (!used_chars) + ERROR("Unexpected error: Font not actually used???"); + + tounicode = create_ToUnicode_stream(cffont, font->fontname, used_chars); + + if (hparent) + Type0Font_set_ToUnicode(hparent, pdf_ref_obj(tounicode)); + if (vparent) + Type0Font_set_ToUnicode(vparent, pdf_ref_obj(tounicode)); + pdf_release_obj(tounicode); + } + + cff_set_name(cffont, font->fontname); + + /* defaultWidthX, CapHeight, etc. */ + get_font_attr(font, cffont); + if (cff_dict_known(cffont->private[0], "defaultWidthX")) { + defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0); + } else { + defaultwidth = 0.0; + } + if (cff_dict_known(cffont->private[0], "nominalWidthX")) { + nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0); + } else { + nominalwidth = 0.0; + } + + num_glyphs = 0; last_cid = 0; + add_to_used_chars2(used_chars, 0); /* .notdef */ + for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { + int c, j; + + c = used_chars[i]; + for (j = 7; j >= 0; j--) { + if (c & (1 << j)) { + num_glyphs++; + last_cid = (i + 1) * 8 - j - 1; + } + } + } + + { + cff_fdselect *fdselect; + + fdselect = NEW(1, cff_fdselect); + fdselect->format = 3; + fdselect->num_entries = 1; + fdselect->data.ranges = NEW(1, cff_range3); + fdselect->data.ranges[0].first = 0; + fdselect->data.ranges[0].fd = 0; + cffont->fdselect = fdselect; + } + + CIDToGIDMap = NEW(2*(last_cid+1), unsigned char); + memset(CIDToGIDMap, 0, 2*(last_cid+1)); + { + cff_charsets *charset; + + charset = NEW(1, cff_charsets); + charset->format = 0; + charset->num_entries = num_glyphs-1; + charset->data.glyphs = NEW(num_glyphs-1, s_SID); + + for (gid = 0, cid = 0; cid <= last_cid; cid++) { + if (is_used_char2(used_chars, cid)) { + if (gid > 0) + charset->data.glyphs[gid-1] = cid; + CIDToGIDMap[2*cid ] = (gid >> 8) & 0xff; + CIDToGIDMap[2*cid+1] = gid & 0xff; + gid++; + } + } + + cff_release_charsets(cffont->charsets); + cffont->charsets = charset; + } + + cff_dict_add(cffont->topdict, "CIDCount", 1); + cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); + + cffont->fdarray = NEW(1, cff_dict *); + cffont->fdarray[0] = cff_new_dict(); + cff_dict_add(cffont->fdarray[0], "FontName", 1); + cff_dict_set(cffont->fdarray[0], "FontName", 0, + (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ + cff_dict_add(cffont->fdarray[0], "Private", 2); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); + + /* FDArray - index offset, not known yet */ + cff_dict_add(cffont->topdict, "FDArray", 1); + cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); + /* FDSelect - offset, not known yet */ + cff_dict_add(cffont->topdict, "FDSelect", 1); + cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); + + cff_dict_add(cffont->topdict, "charset", 1); + cff_dict_set(cffont->topdict, "charset", 0, 0.0); + + cff_dict_add(cffont->topdict, "CharStrings", 1); + cff_dict_set(cffont->topdict, "CharStrings", 0, 0.0); + + { + cff_index *cstring; + t1_ginfo gm; + long max = 0; + double *widths; + int w_stat[1001], max_count, dw; + + widths = NEW(num_glyphs, double); + memset(w_stat, 0, sizeof(int)*1001); + offset = 0L; + cstring = cff_new_index((card16)num_glyphs); + cstring->data = NULL; + cstring->offset[0] = 1; + gid = 0; + for (cid = 0; cid <= last_cid; cid++) { + if (!is_used_char2(used_chars, cid)) + continue; + + if (offset + CS_STR_LEN_MAX >= max) { + max += CS_STR_LEN_MAX*2; + cstring->data = RENEW(cstring->data, max, card8); + } + offset += t1char_convert_charstring(cstring->data + cstring->offset[gid] - 1, CS_STR_LEN_MAX, + cffont->cstrings->data + cffont->cstrings->offset[cid] - 1, + cffont->cstrings->offset[cid+1] - cffont->cstrings->offset[cid], + cffont->subrs[0], defaultwidth, nominalwidth, &gm); + cstring->offset[gid+1] = offset + 1; + if (gm.use_seac) { + ERROR("This font using the \"seac\" command for accented characters..."); + } + widths[gid] = gm.wx; + if (gm.wx >= 0.0 && gm.wx <= 1000.0) { + w_stat[((int) gm.wx)] += 1; + } + gid++; + } + + cff_release_index(cffont->cstrings); + cffont->cstrings = cstring; + + max_count = 0; dw = -1; + for (i = 0; i <= 1000; i++) { + if (w_stat[i] > max_count) { + dw = i; + max_count = w_stat[i]; + } + } + if (dw >= 0) { + add_metrics(font, cffont, CIDToGIDMap, widths, dw, last_cid); + } else { + add_metrics(font, cffont, CIDToGIDMap, widths, defaultwidth, last_cid); + } + RELEASE(widths); + } + cff_release_index(cffont->subrs[0]); + cffont->subrs[0] = NULL; + + RELEASE(CIDToGIDMap); + + cff_add_string(cffont, "Adobe", 1); + cff_add_string(cffont, "Identity", 1); + + cff_dict_update(cffont->topdict, cffont); + cff_dict_update(cffont->private[0], cffont); + + cff_update_string(cffont); + + /* CFF code need to be rewrote... */ + cff_dict_add(cffont->topdict, "ROS", 3); + cff_dict_set(cffont->topdict, "ROS", 0, + (double) cff_get_sid(cffont, "Adobe")); + cff_dict_set(cffont->topdict, "ROS", 1, + (double) cff_get_sid(cffont, "Identity")); + cff_dict_set(cffont->topdict, "ROS", 2, 0.0); + + cffont->num_glyphs = num_glyphs; + offset = write_fontfile(font, cffont); + + cff_close(cffont); + + { + pdf_obj *cidset; + + cidset = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(cidset, used_chars, (last_cid/8)+1); + pdf_add_dict(font->descriptor, + pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); + pdf_release_obj(cidset); + } + + + return; +} + +void +CIDFont_type0_release(CIDFont *font) +{ +#ifdef XETEX + if (font->ft_to_gid) + RELEASE(font->ft_to_gid); +#endif + return; +} diff --git a/Build/source/texk/dvipdfm-x/dvi.c b/Build/source/texk/dvipdfm-x/dvi.c new file mode 100644 index 00000000000..a0a271591ea --- /dev/null +++ b/Build/source/texk/dvipdfm-x/dvi.c @@ -0,0 +1,2801 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2013 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#endif + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" +#include "numbers.h" + +#include "pdfdev.h" +#include "pdfdoc.h" +#include "pdfparse.h" +#include "pdfencrypt.h" + +#include "fontmap.h" + +#include "dvicodes.h" +#include "tfm.h" +#include "vf.h" +#include "subfont.h" + +#include "spc_util.h" +#include "specials.h" + +#include "dvi.h" +#include "dvipdfmx.h" + +#ifdef XETEX +#include "pdfximage.h" +#include FT_ADVANCES_H +#endif + +#define DVI_STACK_DEPTH_MAX 256u +#define TEX_FONTS_ALLOC_SIZE 16u +#define VF_NESTING_MAX 16u + +/* UTF-32 over U+FFFF -> UTF-16 surrogate pair */ +#define UTF32toUTF16HS(x) (0xd800 + (((x-0x10000) >> 10) & 0x3ff)) +#define UTF32toUTF16LS(x) (0xdc00 + ( x & 0x3ff)) + +/* Interal Variables */ +static FILE *dvi_file = NULL; +static char linear = 0; /* set to 1 for strict linear processing of the input */ + +static unsigned long *page_loc = NULL; +static unsigned long num_pages = 0; + +static unsigned long dvi_file_size = 0; + +static struct dvi_header +{ + UNSIGNED_QUAD unit_num; + UNSIGNED_QUAD unit_den; + UNSIGNED_QUAD mag; + UNSIGNED_QUAD media_width, media_height; + UNSIGNED_PAIR stackdepth; + char comment[257]; +} dvi_info = { + 25400000 , /* num */ + 473628672, /* den */ + 1000, /* mag */ + 0, 0, /* media width and height */ + 0, /* stackdepth */ + {'\0'} /* comment */ +}; + +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 +#define NATIVE 4 +#define DVI 1 +#define VF 2 + +static struct loaded_font +{ + int type; /* Type is physical or virtual */ + int font_id; /* id returned by dev (for PHYSICAL fonts) + * or by vf module for (VIRTUAL fonts) + */ + int subfont_id; /* id returned by subfont_locate_font() */ + int tfm_id; + spt_t size; + int source; /* Source is either DVI or VF */ +#ifdef XETEX + unsigned long rgba_color; + FT_Face ft_face; + int layout_dir; + float extend; + float slant; + float embolden; +#endif +} *loaded_fonts = NULL; +static int num_loaded_fonts = 0, max_loaded_fonts = 0; + +static void +need_more_fonts (unsigned n) +{ + if (num_loaded_fonts + n > max_loaded_fonts) { + max_loaded_fonts += TEX_FONTS_ALLOC_SIZE; + loaded_fonts = RENEW (loaded_fonts, max_loaded_fonts, struct loaded_font); + } +} + +static struct font_def +{ + long tex_id; + spt_t point_size; + spt_t design_size; + char *font_name; + int font_id; /* index of _loaded_ font in loaded_fonts array */ + int used; +#ifdef XETEX + int native; /* boolean */ + 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; + +#ifdef XETEX +#define XDV_FLAG_VERTICAL 0x0100 +#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; +static int compute_boxes = 0, link_annot = 1; +static int verbose = 0; + +#define DVI_PAGE_BUF_CHUNK 0x10000UL /* 64K should be plenty for most pages */ + +static unsigned char* dvi_page_buffer; +static unsigned long dvi_page_buf_size; +static unsigned long dvi_page_buf_index; + +#ifdef XETEX +/* functions to read numbers from the dvi file and store them in dvi_page_buffer */ +static UNSIGNED_BYTE get_and_buffer_unsigned_byte (FILE *file) +{ + int ch; + if ((ch = fgetc (file)) < 0) + ERROR ("File ended prematurely\n"); + if (dvi_page_buf_index >= dvi_page_buf_size) { + dvi_page_buf_size += DVI_PAGE_BUF_CHUNK; + dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); + } + dvi_page_buffer[dvi_page_buf_index++] = ch; + return (UNSIGNED_BYTE) ch; +} + +#if 0 +/* Not used */ +static SIGNED_BYTE get_and_buffer_signed_byte (FILE *file) +{ + int byte; + byte = get_and_buffer_unsigned_byte(file); + if (byte >= 0x80) + byte -= 0x100; + return (SIGNED_BYTE) byte; +} +#endif + +static UNSIGNED_PAIR get_and_buffer_unsigned_pair (FILE *file) +{ + int i; + UNSIGNED_BYTE byte; + UNSIGNED_PAIR pair = 0; + for (i=0; i<2; i++) { + byte = get_and_buffer_unsigned_byte(file); + pair = pair*0x100u + byte; + } + return pair; +} + +static SIGNED_PAIR get_and_buffer_signed_pair (FILE *file) +{ + int i; + long pair = 0; + for (i=0; i<2; i++) { + pair = pair*0x100 + get_and_buffer_unsigned_byte(file); + } + if (pair >= 0x8000) { + pair -= 0x10000l; + } + return (SIGNED_PAIR) pair; +} + +static UNSIGNED_TRIPLE get_and_buffer_unsigned_triple(FILE *file) +{ + int i; + long triple = 0; + for (i=0; i<3; i++) { + triple = triple*0x100u + get_and_buffer_unsigned_byte(file); + } + return (UNSIGNED_TRIPLE) triple; +} + +static SIGNED_TRIPLE get_and_buffer_signed_triple(FILE *file) +{ + int i; + long triple = 0; + for (i=0; i<3; i++) { + triple = triple*0x100 + get_and_buffer_unsigned_byte(file); + } + if (triple >= 0x800000l) + triple -= 0x1000000l; + return (SIGNED_TRIPLE) triple; +} + +static SIGNED_QUAD get_and_buffer_signed_quad(FILE *file) +{ + int byte, i; + long quad = 0; + + /* Check sign on first byte before reading others */ + byte = get_and_buffer_unsigned_byte(file); + quad = byte; + if (quad >= 0x80) + quad = byte - 0x100; + for (i=0; i<3; i++) { + quad = quad*0x100 + get_and_buffer_unsigned_byte(file); + } + return (SIGNED_QUAD) quad; +} + +static UNSIGNED_QUAD get_and_buffer_unsigned_quad(FILE *file) +{ + int i; + unsigned long quad = 0; + for (i=0; i<4; i++) { + quad = quad*0x100u + get_and_buffer_unsigned_byte(file); + } + return (UNSIGNED_QUAD) quad; +} + +static void get_and_buffer_bytes(FILE *file, unsigned int count) +{ + if (dvi_page_buf_index + count >= dvi_page_buf_size) { + dvi_page_buf_size = dvi_page_buf_index + count + DVI_PAGE_BUF_CHUNK; + dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); + } + if (fread(dvi_page_buffer + dvi_page_buf_index, 1, count, file) != count) + ERROR ("File ended prematurely\n"); + dvi_page_buf_index += count; +} + +/* functions to fetch values from dvi_page_buffer */ + +static UNSIGNED_BYTE get_buffered_unsigned_byte (void) +{ + return dvi_page_buffer[dvi_page_buf_index++]; +} + +static SIGNED_BYTE get_buffered_signed_byte (void) +{ + int byte; + byte = dvi_page_buffer[dvi_page_buf_index++]; + if (byte >= 0x80) + byte -= 0x100; + return (SIGNED_BYTE) byte; +} + +static UNSIGNED_PAIR get_buffered_unsigned_pair (void) +{ + int i; + UNSIGNED_BYTE byte; + UNSIGNED_PAIR pair = 0; + for (i=0; i<2; i++) { + byte = dvi_page_buffer[dvi_page_buf_index++]; + pair = pair*0x100u + byte; + } + return pair; +} + +static SIGNED_PAIR get_buffered_signed_pair (void) +{ + int i; + long pair = 0; + for (i=0; i<2; i++) { + pair = pair*0x100 + dvi_page_buffer[dvi_page_buf_index++]; + } + if (pair >= 0x8000) { + pair -= 0x10000l; + } + return (SIGNED_PAIR) pair; +} + +static UNSIGNED_TRIPLE get_buffered_unsigned_triple(void) +{ + int i; + long triple = 0; + for (i=0; i<3; i++) { + triple = triple*0x100u + dvi_page_buffer[dvi_page_buf_index++]; + } + return (UNSIGNED_TRIPLE) triple; +} + +static SIGNED_TRIPLE get_buffered_signed_triple(void) +{ + int i; + long triple = 0; + for (i=0; i<3; i++) { + triple = triple*0x100 + dvi_page_buffer[dvi_page_buf_index++]; + } + if (triple >= 0x800000l) + triple -= 0x1000000l; + return (SIGNED_TRIPLE) triple; +} + +static SIGNED_QUAD get_buffered_signed_quad(void) +{ + int byte, i; + long quad = 0; + + /* Check sign on first byte before reading others */ + byte = dvi_page_buffer[dvi_page_buf_index++]; + quad = byte; + if (quad >= 0x80) + quad = byte - 0x100; + for (i=0; i<3; i++) { + quad = quad*0x100 + dvi_page_buffer[dvi_page_buf_index++]; + } + return (SIGNED_QUAD) quad; +} + +static UNSIGNED_QUAD get_buffered_unsigned_quad(void) +{ + int i; + unsigned long quad = 0; + for (i=0; i<4; i++) { + quad = quad*0x100u + dvi_page_buffer[dvi_page_buf_index++]; + } + return (UNSIGNED_QUAD) quad; +} +#else +#define get_and_buffer_unsigned_byte(fp) get_unsigned_byte(fp) +#if 0 +#define get_and_buffer_signed_byte(fp) get_signed_byte(fp) +#endif +#define get_and_buffer_unsigned_pair(fp) get_unsigned_pair(fp) +#define get_and_buffer_signed_pair(fp) get_signed_pair(fp) +#define get_and_buffer_unsigned_triple(fp) get_unsigned_triple(fp) +#define get_and_buffer_signed_triple(fp) get_signed_triple(fp) +#define get_and_buffer_signed_quad(fp) get_unsigned_quad(fp) +#define get_and_buffer_unsigned_quad(fp) get_unsigned_quad(fp) +#define get_and_buffer_bytes(fp, ct) seek_relative(fp, ct) + +#define get_buffered_unsigned_byte() get_unsigned_byte(dvi_file) +#define get_buffered_signed_byte() get_signed_byte(dvi_file) +#define get_buffered_unsigned_pair() get_unsigned_pair(dvi_file) +#define get_buffered_signed_pair() get_signed_pair(dvi_file) +#define get_buffered_unsigned_triple() get_unsigned_triple(dvi_file) +#define get_buffered_signed_triple() get_signed_triple(dvi_file) +#define get_buffered_signed_quad() get_signed_quad(dvi_file) +#define get_buffered_unsigned_quad() get_unsigned_quad(dvi_file) +#endif + +void +dvi_set_verbose (void) +{ + verbose++; + subfont_set_verbose(); + tfm_set_verbose(); + vf_set_verbose (); + spc_set_verbose(); +} + +unsigned +dvi_npages (void) +{ + return num_pages; +} + +static const char invalid_signature[] = +"Something is wrong. Are you sure this is a DVI file?"; + +#define range_check_loc(loc) \ + if ((loc) > dvi_file_size) {\ + ERROR(invalid_signature); \ + } + +static long +find_post (void) +{ + long current; + int ch; + + /* First find end of file */ + dvi_file_size = file_size(dvi_file); + current = dvi_file_size; + + /* Scan backwards through PADDING */ + do { + current--; + seek_absolute(dvi_file, current); + } while ((ch = fgetc(dvi_file)) == PADDING && + current > 0); + + /* file_position now points to last non padding character or + * beginning of file */ + if (dvi_file_size - current < 4 || current == 0 || + !(ch == DVI_ID || ch == DVIV_ID || (is_xetex && ch == XDVI_ID))) { + MESG("DVI ID = %d\n", ch); + ERROR(invalid_signature); + } + + /* Make sure post_post is really there */ + current = current - 5; + seek_absolute(dvi_file, current); + if ((ch = fgetc(dvi_file)) != POST_POST) { + MESG("Found %d where post_post opcode should be\n", ch); + ERROR(invalid_signature); + } + current = get_signed_quad(dvi_file); + seek_absolute(dvi_file, current); + if ((ch = fgetc(dvi_file)) != POST) { + MESG("Found %d where post_post opcode should be\n", ch); + ERROR(invalid_signature); + } + + return current; +} + +static void +get_page_info (long post_location) +{ + int i; + + seek_absolute(dvi_file, post_location + 27); + num_pages = get_unsigned_pair(dvi_file); + if (num_pages == 0) { + ERROR("Page count is 0!"); + } + if (verbose > 2) { + MESG("Page count:\t %4d\n", num_pages); + } + + page_loc = NEW(num_pages, unsigned long); + + seek_absolute(dvi_file, post_location + 1); + page_loc[num_pages-1] = get_unsigned_quad(dvi_file); + range_check_loc(page_loc[num_pages-1] + 41); + for (i = num_pages - 2; i >= 0; i--) { + seek_absolute(dvi_file, page_loc[i+1] + 41); + page_loc[i] = get_unsigned_quad(dvi_file); + range_check_loc(page_loc[num_pages-1] + 41); + } +} + +/* Following are computed "constants" used for unit conversion */ +static double dvi2pts = 1.52018, total_mag = 1.0; + +double +dvi_tell_mag (void) +{ + return total_mag; +} + +static void +do_scales (double mag) +{ + total_mag = (double) dvi_info.mag / 1000.0 * mag; + dvi2pts = (double) dvi_info.unit_num / (double) dvi_info.unit_den; + dvi2pts *= (72.0 / 254000.0); +} + +static void +get_dvi_info (long post_location) +{ + seek_absolute(dvi_file, post_location + 5); + + dvi_info.unit_num = get_unsigned_quad(dvi_file); + dvi_info.unit_den = get_unsigned_quad(dvi_file); + dvi_info.mag = get_unsigned_quad(dvi_file); + + dvi_info.media_height = get_unsigned_quad(dvi_file); + dvi_info.media_width = get_unsigned_quad(dvi_file); + + dvi_info.stackdepth = get_unsigned_pair(dvi_file); + + if (dvi_info.stackdepth > DVI_STACK_DEPTH_MAX) { + WARN("DVI need stack depth of %d,", dvi_info.stackdepth); + WARN("but DVI_STACK_DEPTH_MAX is %d.", DVI_STACK_DEPTH_MAX); + ERROR("Capacity exceeded."); + } + + if (verbose > 2) { + MESG("DVI File Info\n"); + MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den); + MESG("Magnification: %ld\n", dvi_info.mag); + MESG("Media Height: %ld\n", dvi_info.media_height); + MESG("Media Width: %ld\n", dvi_info.media_width); + MESG("Stack Depth: %d\n", dvi_info.stackdepth); + } +} + +#ifdef XETEX +static void +get_preamble_dvi_info (void) +{ + UNSIGNED_BYTE ch; + + ch = get_unsigned_byte(dvi_file); + if (ch != PRE) { + MESG("Found %d where PRE was expected\n", ch); + ERROR(invalid_signature); + } + + ch = get_unsigned_byte(dvi_file); + if (!(ch == DVI_ID || ch == DVIV_ID || (is_xetex && ch == XDVI_ID))) { + MESG("DVI ID = %d\n", ch); + ERROR(invalid_signature); + } + + dvi_info.unit_num = get_unsigned_quad(dvi_file); + dvi_info.unit_den = get_unsigned_quad(dvi_file); + dvi_info.mag = get_unsigned_quad(dvi_file); + + ch = get_unsigned_byte(dvi_file); + if (fread(dvi_info.comment, + 1, ch, dvi_file) != ch) { + ERROR(invalid_signature); + } + dvi_info.comment[ch] = '\0'; + + if (verbose > 2) { + MESG("DVI File Info\n"); + MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den); + MESG("Magnification: %ld\n", dvi_info.mag); + } + + if (verbose) { + MESG("DVI Comment: %s\n", dvi_info.comment); + } + + num_pages = 0x7FFFFFFUL; /* for linear processing: we just keep going! */ +} +#endif + +const char * +dvi_comment (void) +{ + return dvi_info.comment; +} + +static void +read_font_record (SIGNED_QUAD tex_id) +{ + UNSIGNED_BYTE dir_length, name_length; + UNSIGNED_QUAD point_size, design_size; + char *directory, *font_name; + + if (num_def_fonts >= max_def_fonts) { + max_def_fonts += TEX_FONTS_ALLOC_SIZE; + def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def); + } + get_unsigned_quad(dvi_file); + point_size = get_unsigned_quad(dvi_file); + design_size = get_unsigned_quad(dvi_file); + dir_length = get_unsigned_byte(dvi_file); + name_length = get_unsigned_byte(dvi_file); + + directory = NEW(dir_length + 1, char); + if (fread(directory, 1, dir_length, dvi_file) != dir_length) { + ERROR(invalid_signature); + } + directory[dir_length] = '\0'; + RELEASE(directory); /* unused */ + + font_name = NEW(name_length + 1, char); + if (fread(font_name, 1, name_length, dvi_file) != name_length) { + ERROR(invalid_signature); + } + font_name[name_length] = '\0'; + def_fonts[num_def_fonts].tex_id = tex_id; + def_fonts[num_def_fonts].font_name = font_name; + def_fonts[num_def_fonts].point_size = point_size; + def_fonts[num_def_fonts].design_size = design_size; + def_fonts[num_def_fonts].used = 0; +#ifdef XETEX + def_fonts[num_def_fonts].native = 0; + 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++; + + return; +} + +#ifdef XETEX +static void +read_native_font_record (SIGNED_QUAD tex_id) +{ + UNSIGNED_PAIR flags; + UNSIGNED_QUAD point_size; + char *font_name; + int plen, flen, slen, i; + + if (num_def_fonts >= max_def_fonts) { + max_def_fonts += TEX_FONTS_ALLOC_SIZE; + def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def); + } + point_size = get_unsigned_quad(dvi_file); + flags = get_unsigned_pair(dvi_file); + + plen = (int) get_unsigned_byte(dvi_file); /* PS name length */ + flen = (int) get_unsigned_byte(dvi_file); /* family name length */ + slen = (int) get_unsigned_byte(dvi_file); /* style name length */ + font_name = NEW(plen + 1, char); + if (fread(font_name, 1, plen, dvi_file) != plen) { + ERROR(invalid_signature); + } + font_name[plen] = '\0'; + + /* ignore family and style names */ + for (i = 0; i < flen + slen; ++i) + get_unsigned_byte(dvi_file); + + def_fonts[num_def_fonts].tex_id = tex_id; + def_fonts[num_def_fonts].font_name = font_name; + def_fonts[num_def_fonts].point_size = point_size; + def_fonts[num_def_fonts].design_size = 655360; /* hard-code as 10pt for now, not used anyway */ + def_fonts[num_def_fonts].used = 0; + def_fonts[num_def_fonts].native = 1; + + def_fonts[num_def_fonts].layout_dir = 0; + def_fonts[num_def_fonts].rgba_color = 0xffffffff; + def_fonts[num_def_fonts].extend = 0x00010000; + def_fonts[num_def_fonts].slant = 0; + def_fonts[num_def_fonts].embolden = 0; + + if (flags & XDV_FLAG_VERTICAL) + def_fonts[num_def_fonts].layout_dir = 1; + + if (flags & XDV_FLAG_COLORED) + def_fonts[num_def_fonts].rgba_color = get_unsigned_quad(dvi_file); + + if (flags & XDV_FLAG_EXTEND) + def_fonts[num_def_fonts].extend = get_signed_quad(dvi_file); + + if (flags & XDV_FLAG_SLANT) + def_fonts[num_def_fonts].slant = get_signed_quad(dvi_file); + + if (flags & XDV_FLAG_EMBOLDEN) + def_fonts[num_def_fonts].embolden = get_signed_quad(dvi_file); + + if (flags & XDV_FLAG_VARIATIONS) { + int v, nvars = get_unsigned_pair(dvi_file); + for (v = 0; v < nvars * 2; ++v) + (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); + } + + num_def_fonts++; + + return; +} +#endif + +static void +get_dvi_fonts (long post_location) +{ + UNSIGNED_BYTE code; + SIGNED_QUAD tex_id = 0; + + seek_absolute(dvi_file, post_location + 29); + while ((code = get_unsigned_byte(dvi_file)) != POST_POST) { + switch (code) { + case FNT_DEF1: + tex_id = get_unsigned_byte(dvi_file); + break; + case FNT_DEF2: + tex_id = get_unsigned_pair(dvi_file); + break; + case FNT_DEF3: + tex_id = get_unsigned_triple(dvi_file); + break; + case FNT_DEF4: +#ifdef XETEX + case XDV_NATIVE_FONT_DEF: +#endif + tex_id = get_signed_quad(dvi_file); + break; + default: + MESG("Unexpected op code: %3d\n", code); + ERROR(invalid_signature); + } +#ifdef XETEX + if (code == XDV_NATIVE_FONT_DEF) + read_native_font_record(tex_id); + else +#endif + read_font_record(tex_id); + } + if (verbose > 2) { + unsigned i; + + MESG("\n"); + MESG("DVI file font info\n"); + for (i = 0; i < num_def_fonts; i++) { + MESG("TeX Font: %10s loaded at ID=%5ld, ", + def_fonts[i].font_name, def_fonts[i].tex_id); + MESG("size=%5.2fpt (scaled %4.1f%%)", + def_fonts[i].point_size * dvi2pts, + 100.0 * ((double) def_fonts[i].point_size / def_fonts[i].design_size)); + MESG("\n"); + } + } +} + +static void get_comment (void) +{ + UNSIGNED_BYTE length; + + seek_absolute(dvi_file, 14); + length = get_unsigned_byte(dvi_file); + if (fread(dvi_info.comment, + 1, length, dvi_file) != length) { + ERROR(invalid_signature); + } + dvi_info.comment[length] = '\0'; + if (verbose) { + MESG("DVI Comment: %s\n", dvi_info.comment); + } +} + +/* + * The section below this line deals with the actual processing of the + * dvi file. + * + * The dvi file processor state is contained in the following variables: + */ + +struct dvi_registers +{ + SIGNED_QUAD h, v, w, x, y, z, d; +}; + +static struct dvi_registers dvi_state; +static struct dvi_registers dvi_stack[DVI_STACK_DEPTH_MAX]; +static unsigned dvi_stack_depth = 0 ; +static int current_font = -1; +static int processing_page = 0 ; + +static void +clear_state (void) +{ + dvi_state.h = 0; dvi_state.v = 0; dvi_state.w = 0; + dvi_state.x = 0; dvi_state.y = 0; dvi_state.z = 0; + dvi_state.d = 0; /* direction */ + dvi_stack_depth = 0; + current_font = -1; +} + +/* Migrated from pdfdev.c: + * The following codes are originally put into pdfdev.c. + * But they are moved to here to make PDF output independent + * from DVI input. + * pdfdoc, pdfspecial and htex are also modified. pdfspecial + * and htex does tag/untag depth. pdfdev and pdfdoc now does + * not care about line-breaking at all. + */ +static unsigned marked_depth = 0; +static int tagged_depth = -1; + +static void +dvi_mark_depth (void) +{ + /* If decreasing below tagged_depth */ + if (link_annot && + marked_depth == tagged_depth && + dvi_stack_depth == tagged_depth - 1) { + /* + * See if this appears to be the end of a "logical unit" + * that's been broken. If so, flush the logical unit. + */ + pdf_doc_break_annot(); + } + marked_depth = dvi_stack_depth; +} + +/* + * The following routines setup and tear down a callback at a + * certain stack depth. This is used to handle broken (linewise) + * links. + */ +void +dvi_tag_depth (void) +{ + tagged_depth = marked_depth; + dvi_compute_boxes(1); +} + +void +dvi_untag_depth (void) +{ + tagged_depth = -1; + dvi_compute_boxes(0); +} + +void +dvi_compute_boxes (int flag) +{ + compute_boxes = flag; +} + +void +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) +{ + double x_user, y_user, mag; + const char *p; + + if (size > 0x7fffffffUL) { + WARN("Special more than %ul bytes???", size); + return; + } + + graphics_mode(); + + p = (const char *) buffer; + + x_user = dvi_state.h * dvi2pts; + y_user = -dvi_state.v * dvi2pts; + mag = dvi_tell_mag(); + + if (spc_exec_special(p, (long) size, x_user, y_user, mag) < 0) { + if (verbose) { + dump(p, p + size); + } + } + + return; +} + +double +dvi_unit_size (void) +{ + return dvi2pts; +} + + +int +dvi_locate_font (const char *tfm_name, spt_t ptsize) +{ + int cur_id = -1; + const char *name = tfm_name; + int subfont_id = -1, font_id; /* VF or device font ID */ + fontmap_rec *mrec; + + if (verbose) + MESG("<%s@%.2fpt", tfm_name, ptsize * dvi2pts); + + need_more_fonts(1); + + /* This routine needs to be recursive/reentrant. Load current high water + * mark into an automatic variable. + */ + cur_id = num_loaded_fonts++; + + mrec = pdf_lookup_fontmap_record(tfm_name); + /* Load subfont mapping table */ + if (mrec && mrec->charmap.sfd_name && mrec->charmap.subfont_id) { + subfont_id = sfd_load_record(mrec->charmap.sfd_name, mrec->charmap.subfont_id); + } + + /* TFM must exist here. */ + loaded_fonts[cur_id].tfm_id = tfm_open(tfm_name, 1); + loaded_fonts[cur_id].subfont_id = subfont_id; + loaded_fonts[cur_id].size = ptsize; + /* This will be reset later if it was really generated by the dvi file. */ + loaded_fonts[cur_id].source = VF; + + /* The order of searching fonts is as follows: + * + * 1. If mrec is null, that is, there is no map entry matching + * with tfm_name, then search a virtual font matching with + * tfm_name at first. If no virtual font is found, search a + * PK font matching with tfm_name. + * + * 2. If mrec is non-null, search a physical scalable font. + * + * 3. Notice that every subfont gets non-null mrec. In this case, + * enc_name corresponding to mrec will be used instead of mrec. + * That is enc_name is NULL, search a virtual font for Omega (.ovf) + * matching with the base name of the subfont. If no virtual font + * for Omega is found, it is a fatal error because there is no PK font + * for Omega. + */ + if (!mrec) { + font_id = vf_locate_font(tfm_name, ptsize); + if (font_id >= 0) { + loaded_fonts[cur_id].type = VIRTUAL; + loaded_fonts[cur_id].font_id = font_id; + if (verbose) + MESG("(VF)>"); + return cur_id; + } + } +#if 1 + /* Sorry, I don't understand this well... Please fix. + * The purpose of this seems to be: + * + * Map 8-bit char codes in subfont to 16-bit code with SFD mapping + * and map subfonts to single OVF font. + * + * But it apparently only does TFM -> OVF mapping but no character + * code mapping. Please see dvi_set(), you can't have both font->type + * VIRTUAL and font->subfont_id >= 0. Am I missing something? + */ + else if (subfont_id >= 0 && mrec->map_name) + { + fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); + /* enc_name=NULL should be used only for 'built-in' encoding. + * Please fix this! + */ + if (mrec1 && !mrec1->enc_name) { + font_id = vf_locate_font(mrec1->font_name, ptsize); + if (font_id < 0) + WARN("Could not locate Omega Virtual Font \"%s\" for \"%s\".", + mrec1->font_name, tfm_name); + else { + loaded_fonts[cur_id].type = VIRTUAL; + loaded_fonts[cur_id].font_id = font_id; + if (verbose) + MESG("(OVF)>"); + return cur_id; + } + } + } +#endif /* 1 */ + + /* Failed to load a virtual font so we try to load a physical font. */ + + /* If mrec->map_name is not NULL, font name identified in PDF output + * is different than tfm_name, this can happen for subfonts grouped + * into a single "intermediate" font foo@SFD@. + * This is necessary for optimal output; to avoid unnecessary creation + * of multiple instances of a same font, to avoid frequent font selection + * and break of string_mode. + */ + if (mrec && mrec->map_name) { + name = mrec->map_name; + } else { + name = tfm_name; + } + + /* We need ptsize for PK font creation. */ + font_id = pdf_dev_locate_font(name, ptsize); + if (font_id < 0) { + WARN("Could not locate a virtual/physical font for TFM \"%s\".", tfm_name); + if (mrec && mrec->map_name) { /* has map_name */ + fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); + WARN(">> This font is mapped to an intermediate 16-bit font \"%s\" with SFD charmap=<%s,%s>,", + mrec->map_name, mrec->charmap.sfd_name, mrec->charmap.subfont_id); + if (!mrec1) + WARN(">> but I couldn't find font mapping for \"%s\".", mrec->map_name); + else { + WARN(">> and then mapped to a physical font \"%s\" by fontmap.", mrec1->font_name); + WARN(">> Please check if kpathsea library can find this font: %s", mrec1->font_name); + } + } else if (mrec && !mrec->map_name) { + WARN(">> This font is mapped to a physical font \"%s\".", mrec->font_name); + WARN(">> Please check if kpathsea library can find this font: %s", mrec->font_name); + } else { + WARN(">> There are no valid font mapping entry for this font."); + WARN(">> Font file name \"%s\" was assumed but failed to locate that font.", tfm_name); + } + ERROR("Cannot proceed without .vf or \"physical\" font for PDF output..."); + } + loaded_fonts[cur_id].type = PHYSICAL; + loaded_fonts[cur_id].font_id = font_id; + + if (verbose) + MESG(">"); + + return cur_id; +} + +#ifdef XETEX +static int +dvi_locate_native_font (const char *ps_name, + spt_t ptsize, int layout_dir, int extend, int slant, int embolden) +{ + int cur_id = -1; + fontmap_rec *mrec; + char *fontmap_key = malloc(strlen(ps_name) + 40); // CHECK this is enough + + if (verbose) + MESG("<%s@%.2fpt", ps_name, ptsize * dvi2pts); + + need_more_fonts(1); + + cur_id = num_loaded_fonts++; + + 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, layout_dir, extend, slant, embolden) == -1) { + ERROR("Cannot proceed without the \"native\" font: %s", ps_name); + } + mrec = pdf_lookup_fontmap_record(fontmap_key); + /* FIXME: would be more efficient if pdf_load_native_font returned the mrec ptr (or NULL for error) + so we could avoid doing a second lookup for the item we just inserted */ + } + loaded_fonts[cur_id].font_id = pdf_dev_locate_font(fontmap_key, ptsize); + loaded_fonts[cur_id].size = ptsize; + loaded_fonts[cur_id].type = NATIVE; + free(fontmap_key); + + loaded_fonts[cur_id].ft_face = mrec->opt.ft_face; + 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(">"); + + return cur_id; +} +#endif + +double +dvi_dev_xpos (void) +{ + return dvi_state.h * dvi2pts; +} + +double +dvi_dev_ypos (void) +{ + return -(dvi_state.v * dvi2pts); +} + +static void do_moveto (SIGNED_QUAD x, SIGNED_QUAD y) +{ + dvi_state.h = x; + dvi_state.v = y; +} + +void dvi_right (SIGNED_QUAD x) +{ + switch (dvi_state.d) { + case 0: + dvi_state.h += x; break; + case 1: + dvi_state.v += x; break; + case 3: + dvi_state.v -= x; break; + } +} + +void dvi_down (SIGNED_QUAD y) +{ + switch (dvi_state.d) { + case 0: + dvi_state.v += y; break; + case 1: + dvi_state.h -= y; break; + case 3: + dvi_state.h += y; break; + } +} + +/* Please remove this. + * Optimization for 8-bit encodings. + */ +static void +do_string (unsigned char *s, int len) +{ + struct loaded_font *font; + spt_t width, height, depth; + int i; + + if (current_font < 0) + ERROR("No font selected!"); + + font = &loaded_fonts[current_font]; + + width = tfm_string_width(font->tfm_id, s, len); + width = sqxfw(font->size, width); + + switch (font->type) { + case PHYSICAL: + if (font->subfont_id < 0) { + pdf_dev_set_string(dvi_state.h, -dvi_state.v, s, len, + width, font->font_id, 1); + if (compute_boxes && link_annot && + marked_depth >= tagged_depth) { + pdf_rect rect; + + height = tfm_string_height(font->tfm_id, s, len); + depth = tfm_string_depth (font->tfm_id, s, len); + height = sqxfw(font->size, height); + depth = sqxfw(font->size, depth); + + pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, + width, height, depth); + pdf_doc_expand_box(&rect); + } + } else { /* Subfonts */ + dvi_push(); + for (i = 0; i < len; i++) { + dvi_set(s[i]); + } + dvi_pop(); + } + break; + case VIRTUAL: + dvi_push(); + for (i = 0; i < len; i++) { + dvi_set(s[i]); + } + dvi_pop(); + } + switch (dvi_state.d) { + case 0: + dvi_state.h += width; break; + case 1: + dvi_state.v += width; break; + case 3: + dvi_state.v -= width; break; + } +} + +/* _FIXME_ + * CMap decoder wants multibyte strings as input but + * how DVI char codes are converted to multibyte sting + * is not clear. + */ +void +dvi_set (SIGNED_QUAD ch) +{ + struct loaded_font *font; + spt_t width, height, depth; + unsigned char wbuf[4]; + + if (current_font < 0) { + ERROR("No font selected!"); + } + /* The division by dvi2pts seems strange since we actually know the + * "dvi" size of the fonts contained in the DVI file. In other + * words, we converted from DVI units to pts and back again! + * The problem comes from fonts defined in VF files where we don't know + * the DVI size. It's keeping me sane to keep *point sizes* of *all* + * fonts in the dev.c file and convert them back if necessary. + */ + font = &loaded_fonts[current_font]; + + width = tfm_get_fw_width(font->tfm_id, ch); + width = sqxfw(font->size, width); + + switch (font->type) { + case PHYSICAL: + if (!is_xetex && ch > 65535) { /* _FIXME_ */ + wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff; + wbuf[1] = UTF32toUTF16HS(ch) & 0xff; + wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff; + wbuf[3] = UTF32toUTF16LS(ch) & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4, + width, font->font_id, 2); + } else if (ch > 255) { /* _FIXME_ */ + wbuf[0] = (ch >> 8) & 0xff; + wbuf[1] = ch & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, + width, font->font_id, 2); + } else if (font->subfont_id >= 0) { + unsigned short uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); + wbuf[0] = (uch >> 8) & 0xff; + wbuf[1] = uch & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, + width, font->font_id, 2); + } else { + wbuf[0] = (unsigned char) ch; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, + width, font->font_id, 1); + } + if (compute_boxes && link_annot && + marked_depth >= tagged_depth) { + pdf_rect rect; + + height = tfm_get_fw_height(font->tfm_id, ch); + depth = tfm_get_fw_depth (font->tfm_id, ch); + height = sqxfw(font->size, height); + depth = sqxfw(font->size, depth); + + pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, + width, height, depth); + pdf_doc_expand_box(&rect); + } + break; + case VIRTUAL: +#if 0 + /* See comment in locate_font() */ + if (font->subfont_id >= 0) + ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); +#endif /* 0 */ + vf_set_char(ch, font->font_id); /* push/pop invoked */ + break; + } + switch (dvi_state.d) { + case 0: + dvi_state.h += width; break; + case 1: + dvi_state.v += width; break; + case 3: + dvi_state.v -= width; break; + } +} + +void +dvi_put (SIGNED_QUAD ch) +{ + struct loaded_font *font; + spt_t width, height, depth; + unsigned char wbuf[4]; + + if (current_font < 0) { + ERROR("No font selected!"); + } + + font = &loaded_fonts[current_font]; + + switch (font->type) { + case PHYSICAL: + width = tfm_get_fw_width(font->tfm_id, ch); + width = sqxfw(font->size, width); + + /* Treat a single character as a one byte string and use the + * string routine. + */ + if (!is_xetex && ch > 65535) { /* _FIXME_ */ + wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff; + wbuf[1] = UTF32toUTF16HS(ch) & 0xff; + wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff; + wbuf[3] = UTF32toUTF16LS(ch) & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4, + width, font->font_id, 2); + } else if (ch > 255) { /* _FIXME_ */ + wbuf[0] = (ch >> 8) & 0xff; + wbuf[1] = ch & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, + width, font->font_id, 2); + } else if (font->subfont_id >= 0) { + unsigned int uch; + + uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); + wbuf[0] = (uch >> 8) & 0xff; + wbuf[1] = uch & 0xff; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, + width, font->font_id, 2); + } else { + wbuf[0] = (unsigned char) ch; + pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, + width, font->font_id, 1); + } + if (compute_boxes && link_annot && + marked_depth >= tagged_depth) { + pdf_rect rect; + + height = tfm_get_fw_height(font->tfm_id, ch); + depth = tfm_get_fw_depth (font->tfm_id, ch); + height = sqxfw(font->size, height); + depth = sqxfw(font->size, depth); + + pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, + width, height, depth); + pdf_doc_expand_box(&rect); + } + break; + case VIRTUAL: +#if 0 + /* See comment in locate_font() */ + if (font->subfont_id >= 0) + ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); +#endif /* 0 */ + vf_set_char(ch, font->font_id); + break; + } + + return; +} + + +void +dvi_rule (SIGNED_QUAD width, SIGNED_QUAD height) +{ + do_moveto(dvi_state.h, dvi_state.v); + + switch (dvi_state.d) { + case 0: + pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height); + break; + case 1: + pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width); + break; + case 3: + pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width); + break; + } +} + +void +dvi_dir (UNSIGNED_BYTE dir) +{ + if (verbose) + fprintf(stderr, " > dvi_dir %d\n", dir); + dvi_state.d = dir; + pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */ +} + +static void +do_set1 (void) +{ + dvi_set(get_buffered_unsigned_byte()); +} + +static void +do_set2 (void) +{ + dvi_set(get_buffered_unsigned_pair()); +} + +static void +do_set3 (void) +{ + dvi_set(get_buffered_unsigned_triple()); +} + +static void +do_setrule (void) +{ + SIGNED_QUAD width, height; + + height = get_buffered_signed_quad(); + width = get_buffered_signed_quad(); + if (width > 0 && height > 0) { + dvi_rule(width, height); + } + dvi_right(width); +} + +static void +do_putrule (void) +{ + SIGNED_QUAD width, height; + + height = get_buffered_signed_quad (); + width = get_buffered_signed_quad (); + if (width > 0 && height > 0) { + dvi_rule(width, height); + } +} + +static void +do_put1 (void) +{ + dvi_put(get_buffered_unsigned_byte()); +} + +static void +do_put2 (void) +{ + dvi_put(get_buffered_unsigned_pair()); +} + +static void +do_put3 (void) +{ + dvi_put(get_buffered_unsigned_triple()); +} + +void +dvi_push (void) +{ + if (dvi_stack_depth >= DVI_STACK_DEPTH_MAX) + ERROR("DVI stack exceeded limit."); + + dvi_stack[dvi_stack_depth++] = dvi_state; +} + +void +dvi_pop (void) +{ + if (dvi_stack_depth <= 0) + ERROR ("Tried to pop an empty stack."); + + dvi_state = dvi_stack[--dvi_stack_depth]; + do_moveto(dvi_state.h, dvi_state.v); + pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */ +} + + +static void +do_right1 (void) +{ + dvi_right(get_buffered_signed_byte()); +} + +static void +do_right2 (void) +{ + dvi_right(get_buffered_signed_pair()); +} + +static void +do_right3 (void) +{ + dvi_right(get_buffered_signed_triple()); +} + +static void +do_right4 (void) +{ + dvi_right(get_buffered_signed_quad()); +} + +void +dvi_w (SIGNED_QUAD ch) +{ + dvi_state.w = ch; + dvi_right(ch); +} + +void +dvi_w0 (void) +{ + dvi_right(dvi_state.w); +} + +static void +do_w1 (void) +{ + dvi_w(get_buffered_signed_byte()); +} + +static void +do_w2 (void) +{ + dvi_w(get_buffered_signed_pair()); +} + +static void +do_w3 (void) +{ + dvi_w(get_buffered_signed_triple()); +} + +static void +do_w4 (void) +{ + dvi_w(get_buffered_signed_quad()); +} + +void +dvi_x (SIGNED_QUAD ch) +{ + dvi_state.x = ch; + dvi_right(ch); +} + +void +dvi_x0 (void) +{ + dvi_right(dvi_state.x); +} + +static void +do_x1 (void) +{ + dvi_x(get_buffered_signed_byte()); +} + +static void +do_x2 (void) +{ + dvi_x(get_buffered_signed_pair()); +} + +static void +do_x3 (void) +{ + dvi_x(get_buffered_signed_triple()); +} + +static void +do_x4 (void) +{ + dvi_x(get_buffered_signed_quad()); +} + +static void +do_down1 (void) +{ + dvi_down(get_buffered_signed_byte()); +} + +static void +do_down2 (void) +{ + dvi_down(get_buffered_signed_pair()); +} + +static void +do_down3 (void) +{ + dvi_down(get_buffered_signed_triple()); +} + +static void +do_down4 (void) +{ + dvi_down(get_buffered_signed_quad()); +} + +void +dvi_y (SIGNED_QUAD ch) +{ + dvi_state.y = ch; + dvi_down(ch); +} + +void +dvi_y0 (void) +{ + dvi_down(dvi_state.y); +} + +static +void do_y1 (void) +{ + dvi_y(get_buffered_signed_byte()); +} + +static +void do_y2 (void) +{ + dvi_y(get_buffered_signed_pair()); +} + +static +void do_y3 (void) +{ + dvi_y(get_buffered_signed_triple()); +} + +static +void do_y4 (void) +{ + dvi_y(get_buffered_signed_quad()); +} + +void +dvi_z (SIGNED_QUAD ch) +{ + dvi_state.z = ch; + dvi_down(ch); +} + +void +dvi_z0 (void) +{ + dvi_down(dvi_state.z); +} + +static void +do_z1 (void) +{ + dvi_z(get_buffered_signed_byte()); +} + +static void +do_z2 (void) +{ + dvi_z(get_buffered_signed_pair()); +} + +static void +do_z3 (void) +{ + dvi_z(get_buffered_signed_triple()); +} + +static void +do_z4 (void) +{ + dvi_z(get_buffered_signed_quad()); +} + +static void +skip_fntdef (void) +{ + int area_len, name_len, i; + + get_signed_quad(dvi_file); + get_signed_quad(dvi_file); + get_signed_quad(dvi_file); + area_len = get_unsigned_byte(dvi_file); + name_len = get_unsigned_byte(dvi_file); + for (i = 0; i < area_len + name_len; i++) { + get_unsigned_byte(dvi_file); + } +} + +#ifdef XETEX +/* when pre-scanning the page, we process fntdef + and remove the fntdef opcode from the buffer */ +#define DO_FNTDEF(f) \ + if (scanning) { \ + SIGNED_QUAD tex_id = f(dvi_file); \ + if (linear) { \ + read_font_record(tex_id); \ + } else \ + skip_fntdef(); \ + --dvi_page_buf_index; \ + } +#else +#define DO_FNTDEF(f) \ + f(dvi_file); \ + skip_fntdef(); +#endif + +static void +do_fntdef1 (int scanning) +{ + DO_FNTDEF(get_unsigned_byte) +} + +static void +do_fntdef2 (int scanning) +{ + DO_FNTDEF(get_unsigned_pair) +} + +static void +do_fntdef3 (int scanning) +{ + DO_FNTDEF(get_unsigned_triple) +} + +static void +do_fntdef4 (int scanning) +{ + DO_FNTDEF(get_unsigned_quad) +} + +void +dvi_set_font (int font_id) +{ + current_font = font_id; +} + +static void +do_fnt (SIGNED_QUAD tex_id) +{ + int i; + + for (i = 0; i < num_def_fonts; i++) { + if (def_fonts[i].tex_id == tex_id) + break; + } + + if (i == num_def_fonts) { + ERROR("Tried to select a font that hasn't been defined: id=%ld", tex_id); + } + + if (!def_fonts[i].used) { + int font_id; + +#ifdef XETEX + if (def_fonts[i].native) { + font_id = dvi_locate_native_font(def_fonts[i].font_name, + def_fonts[i].point_size, + 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); + } + loaded_fonts[font_id].rgba_color = def_fonts[i].rgba_color; +#else + font_id = dvi_locate_font(def_fonts[i].font_name, def_fonts[i].point_size); +#endif + loaded_fonts[font_id].source = DVI; + def_fonts[i].used = 1; + def_fonts[i].font_id = font_id; + } + current_font = def_fonts[i].font_id; +} + +static void +do_fnt1 (void) +{ + SIGNED_QUAD tex_id; + + tex_id = get_buffered_unsigned_byte(); + do_fnt(tex_id); +} + +static void +do_fnt2 (void) +{ + SIGNED_QUAD tex_id; + + tex_id = get_buffered_unsigned_pair(); + do_fnt(tex_id); +} + +static void +do_fnt3 (void) +{ + SIGNED_QUAD tex_id; + + tex_id = get_buffered_unsigned_triple(); + do_fnt(tex_id); +} + +static void +do_fnt4 (void) +{ + SIGNED_QUAD tex_id; + + tex_id = get_buffered_signed_quad(); + do_fnt(tex_id); +} + +static void +do_xxx (UNSIGNED_QUAD size) +{ +#ifdef XETEX + dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size); + dvi_page_buf_index += size; +#else + UNSIGNED_QUAD i; + Ubyte *buffer; + + buffer = NEW(size+1, Ubyte); + for (i = 0; i < size; i++) { + buffer[i] = get_buffered_unsigned_byte(); + } + dvi_do_special(buffer, size); + RELEASE(buffer); +#endif +} + +static void +do_xxx1 (void) +{ + SIGNED_QUAD size; + + size = get_buffered_unsigned_byte(); + do_xxx(size); +} + +static void +do_xxx2 (void) +{ + SIGNED_QUAD size; + + size = get_buffered_unsigned_pair(); + do_xxx(size); +} + +static void +do_xxx3 (void) +{ + SIGNED_QUAD size; + + size = get_buffered_unsigned_triple(); + do_xxx(size); +} + +static void +do_xxx4 (void) +{ + SIGNED_QUAD size; + + size = get_buffered_unsigned_quad(); + do_xxx(size); +} + +static void +do_bop (void) +{ + int i; + + if (processing_page) + ERROR("Got a bop in the middle of a page!"); + + /* For now, ignore TeX's count registers */ + for (i = 0; i < 10; i++) { + get_buffered_signed_quad(); + } + /* Ignore previous page pointer since we have already + * saved this information + */ + get_buffered_signed_quad(); + clear_state(); + processing_page = 1; + + pdf_doc_begin_page(dvi_tell_mag(), dev_origin_x, dev_origin_y); + spc_exec_at_begin_page(); + + return; +} + +static void +do_eop (void) +{ + processing_page = 0; + + if (dvi_stack_depth != 0) { + ERROR("DVI stack depth is not zero at end of page"); + } + spc_exec_at_end_page(); + + pdf_doc_end_page(); + + return; +} + +static void +do_dir (void) +{ + dvi_state.d = get_buffered_unsigned_byte(); + pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1,3: vertical */ +} + +#ifdef XETEX +static void +do_native_font_def (int scanning) +{ + if (scanning) { + SIGNED_QUAD tex_id = get_signed_quad(dvi_file); + if (linear) { + read_native_font_record(tex_id); + } else { + UNSIGNED_PAIR flags; + int name_length, nvars, i; + + get_unsigned_quad(dvi_file); /* skip point size */ + flags = get_unsigned_pair(dvi_file); + name_length = (int) get_unsigned_byte(dvi_file); + name_length += (int) get_unsigned_byte(dvi_file); + name_length += (int) get_unsigned_byte(dvi_file); + for (i = 0; i < name_length; ++i) + get_unsigned_byte(dvi_file); + if (flags & XDV_FLAG_COLORED) { + get_unsigned_quad(dvi_file); + } + if (flags & XDV_FLAG_VARIATIONS) { + nvars = get_unsigned_pair(dvi_file); + for (i = 0; i < nvars * 2; ++i) + get_unsigned_quad(dvi_file); /* skip axis and value for each variation setting */ + } + } + --dvi_page_buf_index; /* don't buffer the opcode */ + } +} + +static void +do_glyph_array (int yLocsPresent) +{ + struct loaded_font *font; + spt_t width, height, depth, *xloc, *yloc, glyph_width = 0; + unsigned char wbuf[2]; + unsigned int i, glyph_id, slen = 0; + + if (current_font < 0) + ERROR("No font selected!"); + + font = &loaded_fonts[current_font]; + + width = get_buffered_signed_quad(); + + slen = (unsigned int) get_buffered_unsigned_pair(); + xloc = NEW(slen, spt_t); + yloc = NEW(slen, spt_t); + for (i = 0; i < slen; i++) { + xloc[i] = get_buffered_signed_quad(); + yloc[i] = yLocsPresent ? get_buffered_signed_quad() : 0; + } + + if (font->rgba_color != 0xffffffff) { + pdf_color color; + 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_color_push(&color, &color); + } + + for (i = 0; i < slen; i++) { + glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */ + if (glyph_id < font->ft_face->num_glyphs) { + FT_Error error; + FT_Fixed advance; + int flags = FT_LOAD_NO_SCALE; + + if (font->layout_dir == 1) + flags |= FT_LOAD_VERTICAL_LAYOUT; + + error = FT_Get_Advance(font->ft_face, glyph_id, flags, &advance); + if (error) + advance = 0; + + glyph_width = (double)font->size * (double)advance / (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; + depth = (double)font->size * -(double)font->ft_face->descender / (double)font->ft_face->units_per_EM; + pdf_dev_set_rect(&rect, dvi_state.h + xloc[i], -dvi_state.v - yloc[i], glyph_width, height, depth); + pdf_doc_expand_box(&rect); + } + } + + wbuf[0] = glyph_id >> 8; + wbuf[1] = glyph_id & 0xff; + pdf_dev_set_string(dvi_state.h + xloc[i], -dvi_state.v - yloc[i], wbuf, 2, + glyph_width, font->font_id, -1); + } + + if (font->rgba_color != 0xffffffff) { + pdf_color_pop(); + } + RELEASE(xloc); + RELEASE(yloc); + + if (!dvi_state.d) { + dvi_state.h += width; + } else { + dvi_state.v += width; + } + + return; +} + +static void +do_pic_file(void) + /* parameters for XDV_PIC_FILE opcode: pdf_box[1] t[4][6] p[2] len[2] path[l] */ +{ + int page_no; + UNSIGNED_PAIR len; + char *path; + int i; + int xobj_id; + transform_info ti; + + transform_info_clear(&ti); + + /* pdf_box = */ get_buffered_unsigned_byte(); + + ti.matrix.a = get_buffered_signed_quad() / 65536.0; /* convert 16.16 Fixed to floating-point */ + ti.matrix.b = get_buffered_signed_quad() / 65536.0; + ti.matrix.c = get_buffered_signed_quad() / 65536.0; + ti.matrix.d = get_buffered_signed_quad() / 65536.0; + ti.matrix.e = get_buffered_signed_quad() / 65536.0; + ti.matrix.f = get_buffered_signed_quad() / 65536.0; + + page_no = get_buffered_signed_pair(); + len = get_buffered_unsigned_pair(); + path = NEW(len + 1, char); + for (i = 0; i < len; ++i) + path[i] = get_buffered_unsigned_byte(); + path[len] = 0; + + /* + now we need to place page /page_no/ of the graphic file from /path/, applying /transform/ + if pdf_box=0 the file is a raster image (.jpg, .png, .tif, etc; need to determine format + by examining the file) + else it is a PDF document, pdf_box tells which PDF box (media, trim, crop, etc) to use + page_no is currently only used with PDF documents, though in theory could be used + with multi-page TIFFs, etc + transform is a 3x2 affine transform matrix expressed in fixed-point values + */ + + xobj_id = pdf_ximage_findresource(path, page_no, NULL); + 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, + not just assume the "original" size is 100dpi + */ + pdf_dev_put_image(xobj_id, &ti, dvi_dev_xpos(), dvi_dev_ypos()); + } + + RELEASE(path); +} +#endif + +/* Note to be absolutely certain that the string escape buffer doesn't + * hit its limit, FORMAT_BUF_SIZE should set to 4 times S_BUFFER_SIZE + * in pdfobj.c. Is there any application that genenerate words with + * 1k characters? + */ + +#define SBUF_SIZE 1024 + +/* Most of the work of actually interpreting + * the dvi file is here. + */ +void +dvi_do_page (long n, + double paper_width, double paper_height, + double hmargin, double vmargin) +{ + unsigned char opcode; + unsigned char sbuf[SBUF_SIZE]; + unsigned int slen = 0; + +#ifdef XETEX + /* before this is called, we have scanned the page for papersize specials + and the complete DVI data is now in dvi_page_buffer */ + dvi_page_buf_index = 0; +#else + if (!page_loc || n >= num_pages) + ERROR("Tried to process non-existent page: %ld", n); + seek_absolute(dvi_file, page_loc[n]); +#endif + + /* DVI coordinate */ + dev_origin_x = hmargin; + dev_origin_y = paper_height - vmargin; + + dvi_stack_depth = 0; + for (;;) { + /* The most likely opcodes are individual setchars. + * These are buffered for speed. */ + slen = 0; + while ((opcode = get_buffered_unsigned_byte()) <= SET_CHAR_127 && + slen < SBUF_SIZE) { + sbuf[slen++] = opcode; + } + if (slen > 0) { + do_string(sbuf, slen); + } + if (slen == SBUF_SIZE) + continue; + + /* If we are here, we have an opcode that is something + * other than SET_CHAR. + */ + if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) { + do_fnt(opcode - FNT_NUM_0); + continue; + } + + switch (opcode) { + case SET1: do_set1(); break; + case SET2: do_set2(); break; + case SET3: if (!is_xetex) { do_set3(); break; } + case SET4: + ERROR("Multibyte (>%d bits) character not supported!", + is_xetex ? 16 : 24); + break; + + case SET_RULE: + do_setrule(); + break; + + case PUT1: do_put1(); break; + case PUT2: do_put2(); break; + case PUT3: if (!is_xetex) { do_put3(); break; } + case PUT4: + ERROR("Multibyte (>%d bits) character not supported!", + is_xetex ? 16 : 24); + break; + + case PUT_RULE: + do_putrule(); + break; + + case NOP: + break; + + case BOP: + do_bop(); + MESG("[%d", n+1); + break; + case EOP: + do_eop(); + MESG("]"); + return; + + case PUSH: + dvi_push(); + /* The following line needs to go here instead of in + * dvi_push() since logical structure of document is + * oblivous to virtual fonts. For example the last line on a + * page could be at stack level 3 and the page footer should + * be at stack level 3. However, if the page footer contains + * virtual fonts (or other nested constructions), it could + * fool the link breaker into thinking it was a continuation + * of the link */ + dvi_mark_depth(); + break; + case POP: + dvi_pop(); + /* Above explanation holds for following line too */ + dvi_mark_depth(); + break; + + case RIGHT1: do_right1(); break; + case RIGHT2: do_right2(); break; + case RIGHT3: do_right3(); break; + case RIGHT4: do_right4(); break; + + case W0: dvi_w0(); break; + case W1: do_w1 (); break; + case W2: do_w2 (); break; + case W3: do_w3 (); break; + case W4: do_w4 (); break; + + case X0: dvi_x0(); break; + case X1: do_x1 (); break; + case X2: do_x2 (); break; + case X3: do_x3 (); break; + case X4: do_x4 (); break; + + case DOWN1: do_down1(); break; + case DOWN2: do_down2(); break; + case DOWN3: do_down3(); break; + case DOWN4: do_down4(); break; + + case Y0: dvi_y0(); break; + case Y1: do_y1 (); break; + case Y2: do_y2 (); break; + case Y3: do_y3 (); break; + case Y4: do_y4 (); break; + + case Z0: dvi_z0(); break; + case Z1: do_z1 (); break; + case Z2: do_z2 (); break; + case Z3: do_z3 (); break; + case Z4: do_z4 (); break; + + case FNT1: do_fnt1(); break; + case FNT2: do_fnt2(); break; + case FNT3: do_fnt3(); break; + case FNT4: do_fnt4(); break; + + /* Specials */ + case XXX1: do_xxx1(); break; + case XXX2: do_xxx2(); break; + case XXX3: do_xxx3(); break; + case XXX4: do_xxx4(); break; + + /* Font definition - skipped except in linear mode. */ + /* actually, these should not occur! */ + case FNT_DEF1: do_fntdef1(0); break; + case FNT_DEF2: do_fntdef2(0); break; + case FNT_DEF3: do_fntdef3(0); break; + case FNT_DEF4: do_fntdef4(0); break; + + /* pTeX extension */ + case PTEXDIR: + do_dir(); + break; + +#ifdef XETEX + /* XeTeX extension */ + case XDV_GLYPH_STRING: + do_glyph_array(0); + break; + case XDV_GLYPH_ARRAY: + do_glyph_array(1); + break; + case XDV_NATIVE_FONT_DEF: + do_native_font_def(0); /* should not occur - processed during pre-scanning */ + break; + case XDV_PIC_FILE: + do_pic_file(); + break; +#endif + + case POST: + if (linear && !processing_page) { + /* for linear processing, this means there are no more pages */ + num_pages = 0; /* force loop to terminate */ + return; + } + /* else fall through to error case */ + case PRE: case POST_POST: + ERROR("Unexpected preamble or postamble in dvi file"); + break; + default: + ERROR("Unexpected opcode or DVI file ended prematurely"); + } + } +} + +double +dvi_init (char *dvi_filename, double mag) +{ + long post_location; + +#ifdef XETEX + if (dvi_filename == NULL) { /* no filename: reading from stdin, probably a pipe */ +#ifdef WIN32 + setmode(fileno(stdin), _O_BINARY); +#endif + dvi_file = stdin; + linear = 1; + + get_preamble_dvi_info(); + do_scales(mag); + } + else +#endif + { + dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); +#ifdef XETEX + if (!dvi_file) { + char *p; + p = strrchr(dvi_filename, '.'); + if (p == NULL || (!FILESTRCASEEQ(p, ".dvi") && + !(is_xetex && FILESTRCASEEQ(p, ".xdv")))) { +#ifdef XETEX + strcat(dvi_filename, ".xdv"); + dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); + if (!dvi_file) { + dvi_filename[strlen(dvi_filename) - 4] = '\0'; +#endif + strcat(dvi_filename, ".dvi"); + dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); +#ifdef XETEX + } +#endif + } + } +#endif + if (!dvi_file) { + ERROR("Could not open specified DVI%s file: %s", + is_xetex ? " (or XDV)" : "", dvi_filename); + return 0.0; + } + + /* DVI files are most easily read backwards by + * searching for post_post and then post opcode. + */ + post_location = find_post(); + get_dvi_info(post_location); + do_scales(mag); + get_page_info(post_location); + get_comment(); + get_dvi_fonts(post_location); + } + clear_state(); + +#ifdef XETEX + dvi_page_buf_size = DVI_PAGE_BUF_CHUNK; + dvi_page_buffer = NEW(dvi_page_buf_size, unsigned char); +#endif + + return dvi2pts; +} + +void +dvi_close (void) +{ + int i; + + if (linear) { + /* probably reading a pipe from xetex; consume any remaining data */ + while (fgetc(dvi_file) != EOF) + ; + } + + /* We add comment in dvi_close instead of dvi_init so user + * has a change to overwrite it. The docinfo dictionary is + * treated as a write-once record. + */ + + /* Do some house cleaning */ + MFCLOSE(dvi_file); + dvi_file = NULL; + + if (def_fonts) { + for (i = 0; i < num_def_fonts; i++) { + if (def_fonts[i].font_name) + RELEASE(def_fonts[i].font_name); + def_fonts[i].font_name = NULL; + } + RELEASE(def_fonts); + } + def_fonts = NULL; + + if (page_loc) + RELEASE(page_loc); + page_loc = NULL; + num_pages = 0; + + if (loaded_fonts) + RELEASE(loaded_fonts); + loaded_fonts = NULL; + num_loaded_fonts = 0; + + vf_close_all_fonts(); + tfm_close_all (); + + if (dvi_page_buffer) { + RELEASE(dvi_page_buffer); + dvi_page_buffer = NULL; + dvi_page_buf_size = 0; + } +} + +/* The following are need to implement virtual fonts + According to documentation, the vf "subroutine" + must have state pushed and must have + w,v,y, and z set to zero. The current font + is determined by the virtual font header, which + may be undefined */ + +static int saved_dvi_font[VF_NESTING_MAX]; +static int num_saved_fonts = 0; + +void +dvi_vf_init (int dev_font_id) +{ + dvi_push(); + + dvi_state.w = 0; dvi_state.x = 0; + dvi_state.y = 0; dvi_state.z = 0; + + /* do not reset dvi_state.d. */ + if (num_saved_fonts < VF_NESTING_MAX) { + saved_dvi_font[num_saved_fonts++] = current_font; + } else + ERROR("Virtual fonts nested too deeply!"); + current_font = dev_font_id; +} + +/* After VF subroutine is finished, we simply pop the DVI stack */ +void +dvi_vf_finish (void) +{ + dvi_pop(); + if (num_saved_fonts > 0) + current_font = saved_dvi_font[--num_saved_fonts]; + else { + ERROR("Tried to pop an empty font stack"); + } +} + + +/* Scan various specials */ +#include "dpxutil.h" + +/* This need to allow 'true' prefix for unit and + * length value must be divided by current magnification. + */ +static int +read_length (double *vp, double mag, const char **pp, const char *endptr) +{ + char *q; + const char *p = *pp; + double v, u = 1.0; + const char *_ukeys[] = { +#define K_UNIT__PT 0 +#define K_UNIT__IN 1 +#define K_UNIT__CM 2 +#define K_UNIT__MM 3 +#define K_UNIT__BP 4 + "pt", "in", "cm", "mm", "bp", + NULL + }; + int k, error = 0; + + q = parse_float_decimal(&p, endptr); + if (!q) { + *vp = 0.0; *pp = p; + return -1; + } + + v = atof(q); + RELEASE(q); + + skip_white(&p, endptr); + q = parse_c_ident(&p, endptr); + if (q) { + 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"); + } + 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; + } + } + + *vp = v * u; *pp = p; + return error; +} + + +static int +scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, + unsigned *minorversion, + int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw, + const char *buf, UNSIGNED_QUAD size) +{ + char *q; + const char *p = buf, *endptr; + int ns_pdf = 0, error = 0; + double tmp; + + endptr = p + size; + + skip_white(&p, endptr); + + q = parse_c_ident(&p, endptr); + if (q && !strcmp(q, "pdf")) { + skip_white(&p, endptr); + if (p < endptr && *p == ':') { + p++; + skip_white(&p, endptr); + RELEASE(q); + 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); + } + } + skip_white(&p, endptr); + + if (q) { + if (!strcmp(q, "landscape")) { + *lm = 1; + } else if (ns_pdf && !strcmp(q, "pagesize")) { + while (!error && p < endptr) { + char *kp = parse_c_ident(&p, endptr); + if (!kp) + break; + else { + skip_white(&p, endptr); + if (!strcmp(kp, "width")) { + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); + if (!error) + *wd = tmp * dvi_tell_mag(); + } else if (!strcmp(kp, "height")) { + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); + if (!error) + *ht = tmp * dvi_tell_mag(); + } else if (!strcmp(kp, "xoffset")) { + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); + if (!error) + *xo = tmp * dvi_tell_mag(); + } else if (!strcmp(kp, "yoffset")) { + error = read_length(&tmp, dvi_tell_mag(), &p, endptr); + if (!error) + *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); + } + skip_white(&p, endptr); + } + } else if (!strcmp(q, "papersize")) { + char qchr = 0; + if (*p == '=') p++; + skip_white(&p, endptr); + if (p < endptr && (*p == '\'' || *p == '\"')) { + qchr = *p; p++; + skip_white(&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(&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; + } + } else if (minorversion && ns_pdf && !strcmp(q, "minorversion")) { + char *kv; + if (*p == '=') p++; + skip_white(&p, endptr); + kv = parse_float_decimal(&p, endptr); + if (kv) { + *minorversion = (unsigned)strtol(kv, NULL, 10); + RELEASE(kv); + } + } else if (ns_pdf && !strcmp(q, "encrypt") && do_enc) { + *do_enc = 1; + *owner_pw = *user_pw = 0; + while (!error && p < endptr) { + char *kp = parse_c_ident(&p, endptr); + if (!kp) + break; + else { + pdf_obj *obj; + skip_white(&p, endptr); + if (!strcmp(kp, "ownerpw")) { + if ((obj = parse_pdf_string(&p, endptr))) { + strncpy(owner_pw, pdf_string_value(obj), MAX_PWD_LEN); + pdf_release_obj(obj); + } else + error = -1; + } else if (!strcmp(kp, "userpw")) { + if ((obj = parse_pdf_string(&p, endptr))) { + strncpy(user_pw, pdf_string_value(obj), MAX_PWD_LEN); + pdf_release_obj(obj); + } else + error = -1; + } else if (!strcmp(kp, "length")) { + if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { + *key_bits = (unsigned) pdf_number_value(obj); + } else + error = -1; + if (obj) + pdf_release_obj(obj); + } else if (!strcmp(kp, "perm")) { + if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { + *permission = (unsigned) pdf_number_value(obj); + } else + error = -1; + if (obj) + pdf_release_obj(obj); + } else + error = -1; + RELEASE(kp); + } + skip_white(&p, endptr); + } + } + RELEASE(q); + } + + return error; +} + + +void +dvi_scan_specials (long page_no, + double *page_width, double *page_height, + double *x_offset, double *y_offset, char *landscape, + unsigned *minorversion, + int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw) +{ + FILE *fp = dvi_file; + long offset; + unsigned char opcode; +#ifdef XETEX + static long buffered_page = -1; +#endif + +#ifdef XETEX + if (page_no == buffered_page) + return; /* because dvipdfmx wants to scan first page twice! */ + buffered_page = page_no; + + dvi_page_buf_index = 0; + + if (!linear) { +#else + { +#endif + if (page_no >= num_pages) + ERROR("Invalid page number: %u", page_no); + offset = page_loc[page_no]; + + seek_absolute(fp, offset); + } + + while ((opcode = get_and_buffer_unsigned_byte(fp)) != EOP) { + if (opcode <= SET_CHAR_127 || + (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63)) + continue; + else if (opcode == XXX1 || opcode == XXX2 || + opcode == XXX3 || opcode == XXX4) { + UNSIGNED_QUAD size; +#ifndef XETEX + char *buf; +#endif + switch (opcode) { + case XXX1: size = get_and_buffer_unsigned_byte(fp); break; + case XXX2: size = get_and_buffer_unsigned_pair(fp); break; + case XXX3: size = get_and_buffer_unsigned_triple(fp); break; + case XXX4: size = get_and_buffer_unsigned_quad(fp); break; + } +#ifdef XETEX + if (dvi_page_buf_index + size >= dvi_page_buf_size) { + dvi_page_buf_size = (dvi_page_buf_index + size + DVI_PAGE_BUF_CHUNK); + dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); + } +#define buf (char*)dvi_page_buffer + dvi_page_buf_index +#else + buf = NEW(size, char); +#endif + if (fread(buf, sizeof(char), size, fp) != size) + ERROR("Reading DVI file failed!"); + if (scan_special(page_width, page_height, x_offset, y_offset, landscape, + minorversion, do_enc, key_bits, permission, owner_pw, user_pw, + buf, size)) + WARN("Reading special command failed: \"%.*s\"", size, buf); +#ifdef XETEX +#undef buf + dvi_page_buf_index += size; +#else + RELEASE(buf); +#endif + continue; + } + + /* Skipping... */ + switch (opcode) { + case BOP: + get_and_buffer_bytes(fp, 44); + break; + case NOP: case PUSH: case POP: + case W0: case X0: case Y0: case Z0: + break; + case SET1: case PUT1: case RIGHT1: case DOWN1: + case W1: case X1: case Y1: case Z1: case FNT1: + get_and_buffer_unsigned_byte(fp); + break; + + case SET2: case PUT2: case RIGHT2: case DOWN2: + case W2: case X2: case Y2: case Z2: case FNT2: + get_and_buffer_signed_pair(fp); + break; + + case SET3: case PUT3: case RIGHT3: case DOWN3: + case W3: case X3: case Y3: case Z3: case FNT3: + get_and_buffer_signed_triple(fp); + break; + + case SET4: case PUT4: case RIGHT4: case DOWN4: + case W4: case X4: case Y4: case Z4: case FNT4: + get_and_buffer_signed_quad(fp); + break; + + case SET_RULE: case PUT_RULE: + get_and_buffer_bytes(fp, 8); + break; + + case FNT_DEF1: do_fntdef1(1); break; + case FNT_DEF2: do_fntdef2(1); break; + case FNT_DEF3: do_fntdef3(1); break; + case FNT_DEF4: do_fntdef4(1); break; + +#ifdef XETEX + case XDV_GLYPH_STRING: + { + UNSIGNED_PAIR count; + get_and_buffer_unsigned_quad(fp); /* width */ + count = get_and_buffer_unsigned_pair(fp); /* glyph count */ + get_and_buffer_bytes(fp, count * 6); /* 2 bytes ID + 4 bytes x-location per glyph */ + } + break; + case XDV_GLYPH_ARRAY: + { + UNSIGNED_PAIR count; + get_and_buffer_unsigned_quad(fp); /* width */ + count = get_and_buffer_unsigned_pair(fp); /* glyph count */ + get_and_buffer_bytes(fp, count * 10); /* 2 bytes ID + 8 bytes x,y-location per glyph */ + } + break; + case XDV_NATIVE_FONT_DEF: + do_native_font_def(1); + break; + case XDV_PIC_FILE: + /* params: flags[1] t[4][6] p[2] len[2] path[l] */ + { + UNSIGNED_PAIR len; + get_and_buffer_bytes(fp, 1 + 4 * 6 + 2); + len = get_and_buffer_unsigned_pair(fp); /* length of pathname */ + get_and_buffer_bytes(fp, len); + } + break; +#endif + + case PTEXDIR: + get_and_buffer_unsigned_byte(fp); + break; + + case POST: + if (linear && dvi_page_buf_index == 1) { + /* this is actually an indication that we've reached the end of the input */ + return; + } + /* else fall through to error case */ + default: /* case PRE: case POST_POST: and others */ + ERROR("Unexpected opcode %d at pos=0x%x", opcode, tell_position(fp)); + break; + } + } + + return; +} + diff --git a/Build/source/texk/dvipdfm-x/dvi.h b/Build/source/texk/dvipdfm-x/dvi.h index 41944db5504..07ed296d233 100644 --- a/Build/source/texk/dvipdfm-x/dvi.h +++ b/Build/source/texk/dvipdfm-x/dvi.h @@ -30,13 +30,11 @@ /* spt_t */ #include "pdfdev.h" -#ifdef XETEX /* instantiated in dvipdfmx.c */ extern double paper_width, paper_height; extern char landscape_mode; extern double get_origin (int x); -#endif extern void dvi_set_verbose (void); @@ -45,9 +43,7 @@ extern double dvi_init (char *dvi_filename, double mag); /* may append .dvi or extern void dvi_close (void); /* Closes data structures created by dvi_open */ extern double dvi_tell_mag (void); -#ifdef XETEX extern double dvi_unit_size (void); -#endif extern double dvi_dev_xpos (void); extern double dvi_dev_ypos (void); extern unsigned dvi_npages (void); @@ -101,9 +97,7 @@ extern void dvi_compute_boxes (int flag); extern void dvi_do_special (const void *buffer, UNSIGNED_QUAD size); -#ifdef XETEX /* allow other modules (pdfdev) to ask whether we're collecting box areas */ -int dvi_is_tracking_boxes(void); -#endif +extern int dvi_is_tracking_boxes(void); #endif /* _DVI_H_ */ diff --git a/Build/source/texk/dvipdfm-x/dvicodes.h b/Build/source/texk/dvipdfm-x/dvicodes.h index 964da579b15..16876bb19f5 100644 --- a/Build/source/texk/dvipdfm-x/dvicodes.h +++ b/Build/source/texk/dvipdfm-x/dvicodes.h @@ -2,7 +2,7 @@ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2002-2013 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team. Copyright (C) 1998, 1999 by Mark A. Wicks @@ -102,9 +102,7 @@ one byte unsigned comment length followed by comment. */ #define DVI_ID 2 /* ID Byte for current DVI file */ #define DVIV_ID 3 /* with Ascii pTeX VW mode extension */ -#ifdef XETEX #define XDVI_ID 5 /* XeTeX ".xdv" output that uses XDV opcodes below */ -#endif #define POST 248 /* Postamble- -- similar to preamble four byte pointer to final bop four byte numerator @@ -121,11 +119,10 @@ #define PADDING 223 #define PTEXDIR 255 /* Ascii pTeX DIR command */ -#ifdef XETEX + /* XeTeX ".xdv" codes */ #define XDV_PIC_FILE 251 /* include graphic or PDF file */ #define XDV_NATIVE_FONT_DEF 252 /* fontdef for native platform font */ #define XDV_GLYPH_ARRAY 253 /* string of glyph IDs with X and Y positions */ #define XDV_GLYPH_STRING 254 /* string of glyph IDs with X-positions only */ -#endif #endif /* _DVICODES_H_ */ diff --git a/Build/source/texk/dvipdfm-x/dvipdfm-bb.test b/Build/source/texk/dvipdfm-x/dvipdfm-bb.test index 4d5e9bac67e..ba9f9017d0d 100755 --- a/Build/source/texk/dvipdfm-x/dvipdfm-bb.test +++ b/Build/source/texk/dvipdfm-x/dvipdfm-bb.test @@ -17,8 +17,14 @@ for e in jpeg png pdf; do cp $testsrc/image.$e img$e.$e done -./dvipdfmx --ebb --help \ - && echo "ebb-help tests OK" \ +echo "*** dvipdfmx --ebb --version" \ + && ./dvipdfmx --ebb --version \ + && echo "ebb-version tests OK" && echo \ + || failed="$failed ebb-version" + +echo "*** dvipdfmx --ebb --help" \ + && ./dvipdfmx --ebb --help \ + && echo "ebb-help tests OK" && echo \ || failed="$failed ebb-help" for e in jpeg png pdf; do @@ -29,8 +35,14 @@ for e in jpeg png pdf; do || failed="$failed ebb-$e" done -./dvipdfmx --xbb --help \ - && echo "xbb-help tests OK" \ +echo "*** dvipdfmx --xbb --version" \ + && ./dvipdfmx --xbb --version \ + && echo "xbb-version tests OK" && echo \ + || failed="$failed xbb-version" + +echo "*** dvipdfmx --xbb --help" \ + && ./dvipdfmx --xbb --help \ + && echo "xbb-help tests OK" && echo \ || failed="$failed xbb-help" for e in jpeg png pdf; do diff --git a/Build/source/texk/dvipdfm-x/dvipdfmx.c b/Build/source/texk/dvipdfm-x/dvipdfmx.c new file mode 100644 index 00000000000..130c83d0e82 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/dvipdfmx.c @@ -0,0 +1,1058 @@ +/* + + This is xdvipdfmx, an extended version of... + + DVIPDFMx, an eXtended-2013 version of DVIPDFM by Mark A. Wicks. + + Copyright (c) 2006 SIL. (xdvipdfmx extensions for XeTeX support) + + Copyright (C) 2002-2013 by Jin-Hwan Cho, Matthias Franz, 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "system.h" +#include "mem.h" + +#include "dpxconf.h" +#include "dpxfile.h" +#include "dpxutil.h" + +#include "dvi.h" + +#include "pdflimits.h" +#include "pdfdoc.h" +#include "pdfdev.h" +#include "pdfparse.h" +#include "pdfencrypt.h" + +#include "spc_tpic.h" +#include "specials.h" + +#include "mpost.h" + +#include "fontmap.h" +#include "pdffont.h" +#include "pdfximage.h" +#include "cid.h" + +#include "dvipdfmx.h" +#include "tt_aux.h" + +#include "error.h" + +#ifdef XETEX +#define PROGNAME "xdvipdfmx" +int is_xetex = 1; +#else +#define PROGNAME "dvipdfmx" +int is_xetex = 0; +#endif + +int compat_mode = 0; /* 0 = dvipdfmx, 1 = dvipdfm */ + +static int verbose = 0; + +static int mp_mode = 0; + +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_PDFDOC_NO_DEST_REMOVE (1 << 4) + +static char ignore_colors = 0; +static double annot_grow = 0.0; +static int bookmark_open = 0; +static double mag = 1.0; +static int font_dpi = 600; +static int really_quiet = 0; +/* + * Precision is essentially limited to 0.01pt. + * See, dev_set_string() in pdfdev.c. + */ +static int pdfdecimaldigits = 2; + +/* Image cache life in hours */ +/* 0 means erase all old images and leave new images */ +/* -1 means erase all old images and also erase new images */ +/* -2 means ignore image cache (default) */ +static int image_cache_life = -2; + +/* Encryption */ +static int do_encryption = 0; +static unsigned key_bits = 40; +static unsigned permission = 0x003C; + +/* Page device */ +double paper_width = 595.0; +double paper_height = 842.0; +static double x_offset = 72.0; +static double y_offset = 72.0; +char landscape_mode = 0; + +int always_embed = 0; /* always embed fonts, regardless of licensing flags */ + +char *dvi_filename = NULL, *pdf_filename = NULL; + +static void +read_config_file (const char *config); + +static void +set_default_pdf_filename(void) +{ + const char *dvi_base; + + dvi_base = xbasename(dvi_filename); + if (mp_mode && + strlen(dvi_base) > 4 && + FILESTRCASEEQ(".mps", dvi_base + strlen(dvi_base) - 4)) { + pdf_filename = NEW(strlen(dvi_base)+1, char); + strncpy(pdf_filename, dvi_base, strlen(dvi_base) - 4); + pdf_filename[strlen(dvi_base)-4] = '\0'; + } else if (strlen(dvi_base) > 4 && + (FILESTRCASEEQ(".dvi", dvi_base+strlen(dvi_base)-4) || + (is_xetex && FILESTRCASEEQ(".xdv", dvi_base+strlen(dvi_base)-4)))) { + pdf_filename = NEW(strlen(dvi_base)+1, char); + strncpy(pdf_filename, dvi_base, strlen(dvi_base)-4); + pdf_filename[strlen(dvi_base)-4] = '\0'; + } else { + pdf_filename = NEW(strlen(dvi_base)+5, char); + strcpy(pdf_filename, dvi_base); + } + + strcat (pdf_filename, ".pdf"); +} + +static void +show_version (void) +{ + fprintf (stdout, "\nThis is " PROGNAME " Version " VERSION " by %s,\n", + is_xetex ? "Jonathan Kew and Jin-Hwan Cho" + : "the DVIPDFMx project team"); + fprintf (stdout, "modified for TeX Live,\n"); + if (is_xetex) + 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) 2002-2013 the DVIPDFMx project team\n"); + if (is_xetex) + fprintf (stdout, "Copyright (C) 2006-2013 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"); + fprintf (stdout, "(at your option) any later version.\n"); +} + +static void +show_usage (void) +{ + fprintf (stdout, "\nUsage: " PROGNAME " [options] [dvifile%s]\n", is_xetex ? "" : "[.dvi]"); + fprintf (stdout, " " PROGNAME " --extractbb|--xbb|--ebb [options]\tBe \"extractbb\"\n"); + fprintf (stdout, " " PROGNAME " --help|--version\n"); + fprintf (stdout, "\nOptions:\n"); + fprintf (stdout, " -c \t\tIgnore color specials (for B&W printing)\n"); + if (!is_xetex) + fprintf (stdout, " --dvipdfm\tEnable DVIPDFM emulation mode\n"); + fprintf (stdout, " -d number\tSet PDF decimal digits (0-5) [2]\n"); + fprintf (stdout, " -f filename\tSet font map file name [cid-x.map]\n"); + fprintf (stdout, " -g dimension\tAnnotation \"grow\" amount [0.0in]\n"); + fprintf (stdout, " -h | --help \tShow this help message and exit\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"); + fprintf (stdout, " -t \t\tEmbed thumbnail images of PNG format [dvifile.1] \n"); + fprintf (stdout, " --version\tOutput version information and exit\n"); + fprintf (stdout, " -v \t\tBe verbose\n"); + fprintf (stdout, " -vv\t\tBe more verbose\n"); + 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, " -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\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 optimize PDF destinations.\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, " -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, " -I number\tImage cache life in hours [-2]\n"); + fprintf (stdout, " \t 0: erase all old images and leave new images\n"); + fprintf (stdout, " \t-1: erase all old images and also erase new images\n"); + fprintf (stdout, " \t-2: ignore image cache\n"); + fprintf (stdout, " -K number\tEncryption key length [40]\n"); + fprintf (stdout, " -M \t\tProcess MetaPost PostScript output\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 \t\tEnable PDF encryption\n"); + 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"); +} + +static void +usage (void) +{ + fprintf (stderr, "\nTry \"" PROGNAME " --help\" for more information.\n"); + exit(1); +} + + +static int +read_length (double *vp, const char **pp, const char *endptr) +{ + char *q; + const char *p = *pp; + double v, u = 1.0; + const char *_ukeys[] = { +#define K_UNIT__PT 0 +#define K_UNIT__IN 1 +#define K_UNIT__CM 2 +#define K_UNIT__MM 3 +#define K_UNIT__BP 4 + "pt", "in", "cm", "mm", "bp", + NULL + }; + int k, error = 0; + + q = parse_float_decimal(&p, endptr); + if (!q) { + *vp = 0.0; *pp = p; + return -1; + } + + v = atof(q); + RELEASE(q); + + skip_white(&p, endptr); + q = parse_c_ident(&p, endptr); + if (q) { + char *qq = q; + if (strlen(q) >= strlen("true") && + !memcmp(q, "true", strlen("true"))) { + q += strlen("true"); /* just skip "true" */ + } + 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; + } + } + + *vp = v * u; *pp = p; + return error; +} + +static void +select_paper (const char *paperspec) +{ + const struct paper *pi; + int error = 0; + + pi = paperinfo(paperspec); + if (pi && papername(pi)) { + paper_width = paperpswidth (pi); + paper_height = paperpsheight(pi); + } else { + const char *p = paperspec, *endptr, *comma; + comma = strchr(p, ','); + endptr = p + strlen(p); + if (!comma) + ERROR("Unrecognized paper format: %s", paperspec); + error = read_length(&paper_width, &p, comma); + p = comma + 1; + error = read_length(&paper_height, &p, endptr); + } + if (error || paper_width <= 0.0 || paper_height <= 0.0) + ERROR("Invalid paper size: %s (%.2fx%.2f)", paperspec, paper_width, paper_height); +} + +struct page_range +{ + long first, last; +} *page_ranges = NULL; + +int num_page_ranges = 0; +int max_page_ranges = 0; + +static void +select_pages (const char *pagespec) +{ + char *q; + const char *p = pagespec; + + while (*p != '\0') { + /* Enlarge page range table if necessary */ + if (num_page_ranges >= max_page_ranges) { + max_page_ranges += 4; + page_ranges = RENEW(page_ranges, max_page_ranges, struct page_range); + } + + page_ranges[num_page_ranges].first = 0; + page_ranges[num_page_ranges].last = 0; + + for ( ; *p && isspace(*p); p++); + q = parse_unsigned(&p, p + strlen(p)); /* Can't be signed. */ + if (q) { /* '-' is allowed here */ + page_ranges[num_page_ranges].first = atoi(q) - 1; + page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; + RELEASE(q); + } + for ( ; *p && isspace(*p); p++); + + if (*p == '-') { + for (++p; *p && isspace(*p); p++); + page_ranges[num_page_ranges].last = -1; + if (*p) { + q = parse_unsigned(&p, p + strlen(p)); + if (q) { + page_ranges[num_page_ranges].last = atoi(q) - 1; + RELEASE(q); + } + for ( ; *p && isspace(*p); p++); + } + } else { + page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; + } + + num_page_ranges++; + + if (*p == ',') + p++; + else { + for ( ; *p && isspace(*p); p++); + if (*p) + ERROR("Bad page range specification: %s", p); + } + } + return; +} + +#define POP_ARG() {argv += 1; argc -= 1;} +/* 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();\ +} + +static void +set_verbose (int argc, char *argv[]) +{ + while (argc > 0) { + if(*argv[0] == '-') { + char *flag; + + for (flag = argv[0] + 1; *flag != 0; flag++) { + if (*flag == '-') + break; + if (*flag == 'q') + really_quiet = 1; + if (*flag == 'v') + verbose++; + } + } + POP_ARG(); + } + + if (!really_quiet) { + int i; + + for (i = 0; i < verbose; i++) { + dvi_set_verbose(); + pdf_dev_set_verbose(); + pdf_doc_set_verbose(); + pdf_enc_set_verbose(); + pdf_obj_set_verbose(); + pdf_fontmap_set_verbose(); + dpx_file_set_verbose(); + tt_aux_set_verbose(); + } + } +} + + +static void +do_args (int argc, char *argv[]) +{ + while (argc > 0 && *argv[0] == '-') { + char *flag, *nextptr; + const char *nnextptr; + + for (flag = argv[0] + 1; *flag != 0; flag++) { + switch (*flag) { + case '-': + if (flag == argv[0] + 1 && ++flag) { + if (!strcmp(flag, "help")) { + show_usage(); + exit(0); + } else if (!strcmp(flag, "version")) { + show_version(); + exit(0); + } else if (!is_xetex && !strcmp(flag, "dvipdfm")) { + compat_mode = 1; + break; + } + } + fprintf(stderr, "Unknown option \"%s\"", argv[0]); + usage(); + case 'D': + CHECK_ARG(1, "PS->PDF conversion command line template"); + set_distiller_template(argv[1]); + POP_ARG(); + break; + case 'r': + CHECK_ARG(1, "bitmap font dpi"); + font_dpi = atoi(argv[1]); + if (font_dpi <= 0) + ERROR("Invalid bitmap font dpi specified: %s", argv[1]); + POP_ARG(); + break; + case 'm': + CHECK_ARG(1, "magnification value"); + mag = strtod(argv[1], &nextptr); + if (mag < 0.0 || nextptr == argv[1]) + ERROR("Invalid magnification specifiied: %s", argv[1]); + POP_ARG(); + break; + case 'g': + CHECK_ARG(1, "annotation \"grow\" amount"); + nnextptr = nextptr = argv[1]; + read_length(&annot_grow, &nnextptr, nextptr + strlen(nextptr)); + POP_ARG(); + break; + case 'x': + CHECK_ARG(1, "horizontal offset value"); + nnextptr = nextptr = argv[1]; + read_length(&x_offset, &nnextptr, nextptr + strlen(nextptr)); + POP_ARG(); + break; + case 'y': + CHECK_ARG(1, "vertical offset value"); + nnextptr = nextptr = argv[1]; + read_length(&y_offset, &nnextptr, nextptr + strlen(nextptr)); + POP_ARG(); + break; + case 'o': + CHECK_ARG(1, "output file name"); + pdf_filename = NEW (strlen(argv[1])+1,char); + strcpy(pdf_filename, argv[1]); + POP_ARG(); + break; + case 's': + CHECK_ARG(1, "page selection specification"); + select_pages(argv[1]); + POP_ARG(); + break; + case 't': + pdf_doc_enable_manual_thumbnails(); + break; + case 'p': + CHECK_ARG(1, "paper format/size"); + select_paper(argv[1]); + POP_ARG(); + break; + case 'c': + ignore_colors = 1; + break; + case 'l': + landscape_mode = 1; + break; + case 'f': + CHECK_ARG(1, "fontmap file name"); + if (opt_flags & OPT_FONTMAP_FIRST_MATCH) + pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_APPEND); + else + pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_REPLACE); + POP_ARG(); + break; + case 'i': + CHECK_ARG(1, "subsidiary config file"); + read_config_file(argv[1]); + POP_ARG(); + break; + case 'q': case 'v': + break; + case 'V': + { + int ver_minor; + + if (isdigit(*(flag+1))) { + flag++; + ver_minor = atoi(flag); + } else { + CHECK_ARG(1, "PDF minor version number"); + ver_minor = atoi(argv[1]); + POP_ARG(); + } + if (ver_minor < PDF_VERSION_MIN) { + WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", + ver_minor, PDF_VERSION_MIN); + ver_minor = PDF_VERSION_MIN; + } else if (ver_minor > PDF_VERSION_MAX) { + WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", + ver_minor, PDF_VERSION_MAX); + ver_minor = PDF_VERSION_MAX; + } + pdf_set_version((unsigned) ver_minor); + } + break; + case 'z': + { + int level; + + if (isdigit(*(flag+1))) { + flag++; + level = atoi(flag); + } else { + CHECK_ARG(1, "compression level"); + level = atoi(argv[1]); + POP_ARG(); + } + pdf_set_compression(level); + } + break; + case 'd': + if (isdigit(*(flag+1))) { + flag++; + pdfdecimaldigits = atoi(flag); + } else { + CHECK_ARG(1, "number of fractional digits"); + pdfdecimaldigits = atoi(argv[1]); + POP_ARG(); + } + break; + case 'I': + CHECK_ARG(1, "image cache life in hours"); + image_cache_life = atoi(argv[1]); + POP_ARG(); + break; + case 'S': + do_encryption = 1; + break; + case 'K': + CHECK_ARG(1, "encryption key length"); + key_bits = (unsigned) atoi(argv[1]); + if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) + ERROR("Invalid encryption key length specified: %s", argv[1]); + POP_ARG(); + break; + case 'P': + CHECK_ARG(1, "encryption permission flag"); + permission = (unsigned) strtoul(argv[1], &nextptr, 0); + if (nextptr == argv[1]) + ERROR("Invalid encryption permission flag: %s", argv[1]); + POP_ARG(); + break; + case 'O': + /* Bookmark open level */ + CHECK_ARG(1, "bookmark open level"); + bookmark_open = atoi(argv[1]); + POP_ARG(); + break; + case 'M': + mp_mode = 1; + break; + case 'C': + CHECK_ARG(1, "a number"); + { + long flags; + + flags = (unsigned) strtol(argv[1], &nextptr, 0); + if (nextptr == argv[1]) + ERROR("Invalid flag: %s", argv[1]); + if (flags < 0) + opt_flags = -flags; + else + opt_flags |= flags; + } + POP_ARG(); + break; + case 'E': + always_embed = 1; + break; + case 'h': + show_usage(); + exit(0); + case 'e': + if (compat_mode) { + WARN("dvipdfm \"-e\" option not supported."); + break; + } /* else fall through */ + default: + fprintf (stderr, "Unknown option in \"%s\"", argv[0]); + usage(); + } + } + POP_ARG(); + } + + if (argc > 1) { + fprintf(stderr, "Multiple dvi filenames?"); + usage(); + } else if (argc > 0) { + char *ext; + if (mp_mode || is_xetex || + ((ext = strrchr(argv[0], '.')) && FILESTRCASEEQ(".dvi", ext))) { + dvi_filename = NEW(strlen(argv[0]) + 1, char); + strcpy(dvi_filename, argv[0]); + } else { + dvi_filename = NEW(strlen(argv[0]) + 5, char); + strcpy(dvi_filename, argv[0]); + strcat(dvi_filename, ".dvi"); + } + } +} + +static void +cleanup (void) +{ + if (dvi_filename) + RELEASE(dvi_filename); + if (pdf_filename) + RELEASE(pdf_filename); + if (page_ranges) + RELEASE(page_ranges); +} + +static void +read_config_file (const char *config) +{ + const char *start, *end; + char *option; + FILE *fp; + + fp = DPXFOPEN(config, DPX_RES_TYPE_TEXT); + if (!fp) { + WARN("Could not open config file \"%s\".", config); + return; + } + while ((start = mfgets (work_buffer, WORK_BUFFER_SIZE, fp)) != NULL) { + char *argv[2]; + int argc; + + argc = 0; + end = work_buffer + strlen(work_buffer); + skip_white (&start, end); + if (start >= end) + continue; + /* Build up an argument list as if it were passed on the command + line */ + if ((option = parse_ident (&start, end))) { + argc = 1; + argv[0] = NEW (strlen(option)+2, char); + strcpy (argv[0]+1, option); + RELEASE (option); + *argv[0] = '-'; + skip_white (&start, end); + if (start < end) { + argc += 1; + if (*start == '"') { + argv[1] = parse_c_string (&start, end); + } + else + argv[1] = parse_ident (&start, end); + } + } + do_args (argc, argv); + while (argc > 0) { + RELEASE (argv[--argc]); + } + } + if (fp) + MFCLOSE(fp); +} + +static void +system_default (void) +{ + if (systempapername() != NULL) { + select_paper(systempapername()); + } else if (defaultpapername() != NULL) { + select_paper(defaultpapername()); + } +} + +void +error_cleanup (void) +{ + pdf_close_images(); /* delete temporary files */ + pdf_error_cleanup(); + if (pdf_filename) { + remove(pdf_filename); + fprintf(stderr, "\nOutput file removed.\n"); + } +} + +#define SWAP(v1,v2) do {\ + double _tmp = (v1);\ + (v1) = (v2);\ + (v2) = _tmp;\ + } while (0) + +static void +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(); + + if (num_page_ranges == 0) { + if (!page_ranges) { + page_ranges = NEW(1, struct page_range); + max_page_ranges = 1; + } + page_ranges[0].first = 0; + page_ranges[0].last = -1; /* last page */ + num_page_ranges = 1; + } + + init_paper_width = page_width = paper_width; + init_paper_height = page_height = paper_height; + page_count = 0; + + mediabox.llx = 0.0; + mediabox.lly = 0.0; + mediabox.urx = paper_width; + mediabox.ury = paper_height; + + pdf_doc_set_mediabox(0, &mediabox); /* Root node */ + + for (i = 0; i < num_page_ranges && dvi_npages(); i++) { + if (page_ranges[i].last < 0) + page_ranges[i].last += dvi_npages(); + + step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; + page_no = page_ranges[i].first; + while (dvi_npages()) { + if (page_no < dvi_npages()) { + double w, h, xo, yo; + char lm; + + MESG("[%d", page_no+1); + /* 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_specials(page_no, &w, &h, &xo, &yo, &lm, NULL, NULL, NULL, NULL, NULL, NULL); + if (lm != landscape_mode) { + SWAP(w, h); + landscape_mode = lm; + } + if (page_width != w || page_height != h) { + page_width = w; + page_height = h; + } + if (x_offset != xo || y_offset != yo) { + x_offset = xo; + y_offset = yo; + } + if (page_width != init_paper_width || + page_height != init_paper_height) { + mediabox.llx = 0.0; + mediabox.lly = 0.0; + mediabox.urx = page_width; + mediabox.ury = page_height; + pdf_doc_set_mediabox(page_count+1, &mediabox); + } + dvi_do_page(page_no, + page_width, page_height, x_offset, y_offset); + page_count++; + MESG("]"); + } + + if (step > 0 && + page_no >= page_ranges[i].last) + break; + else if (step < 0 && + page_no <= page_ranges[i].last) + break; + else { + page_no += step; + } + } + } + + if (page_count < 1) { + ERROR("No pages fall in range!"); + } + + spc_exec_at_end_document(); +} + +static void +do_mps_pages (void) +{ + FILE *fp; + + /* _FIXME_ */ + fp = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); + if (fp) { + mps_do_page(fp); + MFCLOSE(fp); + } else { + long i, page_no, step, page_count = 0; + char *filename; + /* Process filename.1, filename.2,... */ + filename = NEW(strlen(dvi_filename) + 16 + 1, char); + for (i = 0; i < num_page_ranges; i++) { + step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; + page_no = page_ranges[i].first; + for (;;) { + if (page_no < 0) + ERROR("Invalid page number for MPS input: %d", page_no); + + sprintf(filename, "%s.%ld", dvi_filename, page_no + 1); + fp = MFOPEN(filename, FOPEN_RBIN_MODE); + if (fp) { + MESG("[%ld<%s>", page_no + 1, filename); + mps_do_page(fp); + page_count++; + MESG("]"); + MFCLOSE(fp); + } + if (step > 0 && + page_no >= page_ranges[i].last) + break; + else if (step < 0 && + page_no <= page_ranges[i].last) + break; + else { + page_no += step; + } + } + } + RELEASE(filename); + if (page_count == 0) + ERROR("No page output for \"%s\".", dvi_filename); + } +} + + +/* TODO: MetaPost mode */ +#if defined(MIKTEX) +# define main Main +#endif +int CDECL +main (int argc, char *argv[]) +{ + double dvi2pts; + char *base; + +#ifdef MIKTEX + miktex_initialize(); +#else + kpse_set_program_name(argv[0], "dvipdfmx"); /* we pretend to be dvipdfmx for kpse purposes */ +#ifdef WIN32 + texlive_gs_init (); +#endif +#endif + + if (argc > 1 && + (STREQ (argv[1], "--xbb") || + (!is_xetex && STREQ (argv[1], "--dvipdfm")) || + STREQ (argv[1], "--ebb"))) { + argc--; + base = argv++[1]+2; + } else + base = kpse_program_basename (argv[0]); + + if (FILESTRCASEEQ (base, "extractbb") || FILESTRCASEEQ (base, "xbb")) + return extractbb (argc, argv); + if (FILESTRCASEEQ (base, "ebb")) { + compat_mode = 1; + return extractbb (argc, argv); + } + + if (!is_xetex && FILESTRCASEEQ (base, "dvipdfm")) + compat_mode = 1; + else + free (base); + + paperinit(); + system_default(); + + argv+=1; + argc-=1; + + set_verbose(argc, argv); + /* quiet mode cannot be set in config file */ + if (really_quiet) + shut_up(really_quiet); + + pdf_init_fontmaps(); /* This must come before parsing options... */ + + read_config_file(DPX_CONFIG_FILE); + + do_args (argc, argv); + +#ifndef MIKTEX + kpse_init_prog("", font_dpi, NULL, NULL); + kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf); +#endif + pdf_font_set_dpi(font_dpi); + dpx_delete_old_cache(image_cache_life); + + if (!dvi_filename) { + if (verbose) + MESG("No dvi filename specified, reading standard input.\n"); + if (!pdf_filename) + if (verbose) + MESG("No pdf filename specified, writing to standard output.\n"); + } else if (!pdf_filename) + set_default_pdf_filename(); + + MESG("%s -> %s\n", dvi_filename ? dvi_filename : "stdin", + pdf_filename ? pdf_filename : "stdout"); + + pdf_enc_compute_id_string(dvi_filename, pdf_filename); + if (do_encryption) { + if (key_bits > 40 && pdf_get_version() < 4) + ERROR("Chosen key length requires at least PDF 1.4. " + "Use \"-V 4\" to change."); + pdf_enc_set_passwd(key_bits, permission, NULL, NULL); + } + + if (mp_mode) { + x_offset = 0.0; + y_offset = 0.0; + dvi2pts = 0.01; /* dvi2pts controls accuracy. */ + } else { + unsigned ver_minor = 0; + char owner_pw[MAX_PWD_LEN], user_pw[MAX_PWD_LEN]; + /* Dependency between DVI and PDF side is rather complicated... */ + dvi2pts = dvi_init(dvi_filename, mag); + if (dvi2pts == 0.0) + ERROR("dvi_init() failed!"); + + pdf_doc_set_creator(dvi_comment()); + + if (do_encryption) + /* command line takes precedence */ + dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, + &ver_minor, NULL, NULL, NULL, NULL, NULL); + else { + dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, + &ver_minor, &do_encryption, &key_bits, &permission, owner_pw, user_pw); + if (do_encryption) { + if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) + ERROR("Invalid encryption key length specified: %u", key_bits); + else if (key_bits > 40 && pdf_get_version() < 4) + ERROR("Chosen key length requires at least PDF 1.4. " + "Use \"-V 4\" to change."); + do_encryption = 1; + pdf_enc_set_passwd(key_bits, permission, owner_pw, user_pw); + } + } + if (ver_minor >= PDF_VERSION_MIN && ver_minor <= PDF_VERSION_MAX) { + pdf_set_version(ver_minor); + } + if (landscape_mode) { + SWAP(paper_width, paper_height); + } + } + + pdf_files_init(); + + /* 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, do_encryption, + paper_width, paper_height, annot_grow, bookmark_open, + !(opt_flags & OPT_PDFDOC_NO_DEST_REMOVE)); + + /* Ignore_colors placed here since + * they are considered as device's capacity. + */ + pdf_init_device(dvi2pts, pdfdecimaldigits, ignore_colors); + + if (opt_flags & OPT_CIDFONT_FIXEDPITCH) + CIDFont_set_flags(CIDFONT_FORCE_FIXEDPITCH); + + /* Please move this to spc_init_specials(). */ + if (opt_flags & OPT_TPIC_TRANSPARENT_FILL) + tpic_set_fill_mode(1); + + if (mp_mode) { + do_mps_pages(); + } else { + do_dvi_pages(); + } + + pdf_files_close(); + + /* Order of close... */ + pdf_close_device (); + /* pdf_close_document flushes XObject (image) and other resources. */ + pdf_close_document(); + + pdf_close_fontmaps(); /* pdf_font may depend on fontmap. */ + + if (!mp_mode) + dvi_close(); + + MESG("\n"); + cleanup(); + + paperdone(); +#ifdef MIKTEX + miktex_uninitialize (); +#endif + + return 0; +} diff --git a/Build/source/texk/dvipdfm-x/dvipdfmx.h b/Build/source/texk/dvipdfm-x/dvipdfmx.h index 0617de47daf..7cb0bf00a2e 100644 --- a/Build/source/texk/dvipdfm-x/dvipdfmx.h +++ b/Build/source/texk/dvipdfm-x/dvipdfmx.h @@ -1,10 +1,16 @@ /* - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + This is xdvipdfmx, an extended version of... - Copyright (C) 2009-2012 by Jin-Hwan Cho, Matthias Franz, and Shunsaku Hirata, - the dvipdfmx project team. + DVIPDFMx, an eXtended-2013 version of DVIPDFM by Mark A. Wicks. + + Copyright (c) 2006 SIL. (xdvipdfmx extensions for XeTeX support) + + Copyright (C) 2002-2013 by Jin-Hwan Cho, Matthias Franz, 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 @@ -24,6 +30,7 @@ #define _DVIPDFMX_H_ extern int compat_mode; +extern int is_xetex; extern int extractbb(int argc, char *argv[]); diff --git a/Build/source/texk/dvipdfm-x/dvipdfmx.test b/Build/source/texk/dvipdfm-x/dvipdfmx.test index cc61bb85a1b..a46ff272355 100755 --- a/Build/source/texk/dvipdfm-x/dvipdfmx.test +++ b/Build/source/texk/dvipdfm-x/dvipdfmx.test @@ -5,7 +5,23 @@ # Not really a test, just making sure the program executes. -TEXMFCNF=${srcdir}/../kpathsea \ - DVIPDFMXINPUTS=${srcdir}/tests:${srcdir}/data \ - ./dvipdfmx --help || exit 1 +TEXMFCNF=${srcdir}/../kpathsea +DVIPDFMXINPUTS=${srcdir}/tests:${srcdir}/data +export TEXMFCNF DVIPDFMXINPUTS + +failed= + +echo "*** dvipdfmx --version" \ + && ./dvipdfmx --version \ + && echo "dvipdfmx-version tests OK" && echo \ + || failed="$failed dvipdfmx-version" + +echo "*** dvipdfmx --help" \ + && ./dvipdfmx --help \ + && echo "dvipdfmx-help tests OK" && echo \ + || failed="$failed dvipdfmx-help" + +test -z "$failed" && exit 0 +echo "failed tests:$failed" +exit 1 diff --git a/Build/source/texk/dvipdfm-x/epdf.c b/Build/source/texk/dvipdfm-x/epdf.c new file mode 100644 index 00000000000..e2c9e99878e --- /dev/null +++ b/Build/source/texk/dvipdfm-x/epdf.c @@ -0,0 +1,974 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 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. +*/ + +/* + * Concatinating content streams are only supported for streams that only uses + * single FlateDecode filter, i.e., + * + * /Filter /FlateDecode or /Filter [/FlateDecode] + * + * TrimBox, BleedBox, ArtBox, Rotate ... + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "mem.h" +#include "mfileio.h" +#include "error.h" +#include "dvipdfmx.h" + +#include "pdfobj.h" +#include "pdfdev.h" +#include "pdfdoc.h" + +#ifdef XETEX +#include "pdfdraw.h" +#include "pdfparse.h" +#endif + +#include "pdfximage.h" + +#include "epdf.h" + +#ifdef XETEX +#if HAVE_ZLIB +#include +static int add_stream_flate (pdf_obj *dst, const void *data, long len); +#endif +static int rect_equal (pdf_obj *rect1, pdf_obj *rect2); + +static int concat_stream (pdf_obj *dst, pdf_obj *src); + +/* + * From PDFReference15_v6.pdf (p.119 and p.834) + * + * MediaBox rectangle (Required; inheritable) + * + * 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) + * + * 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) + * + * 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) + * + * 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) + * + * 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) + * + * 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 +rect_equal (pdf_obj *rect1, pdf_obj *rect2) +{ + int i; + + if (!rect1 || !rect2) + return 0; + for (i = 0; i < 4; i++) { + if (pdf_number_value(pdf_get_array(rect1, i)) != + pdf_number_value(pdf_get_array(rect2, i))) + return 0; + } + + return 1; +} + +static pdf_obj* +pdf_get_page_obj (pdf_file *pf, long page_no, + pdf_obj **ret_bbox, pdf_obj **ret_resources) +{ + pdf_obj *page_tree; + pdf_obj *bbox = NULL, *resources = NULL, *rotate = NULL; + long page_idx; + + /* + * Get Page Tree. + */ + page_tree = NULL; + { + pdf_obj *trailer, *catalog; + pdf_obj *markinfo, *tmp; + + trailer = pdf_file_get_trailer(pf); + + if (pdf_lookup_dict(trailer, "Encrypt")) { + WARN("This PDF document is encrypted."); + pdf_release_obj(trailer); + return NULL; + } + + catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); + 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); + + markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); + if (markinfo) { + tmp = pdf_lookup_dict(markinfo, "Marked"); + if (PDF_OBJ_BOOLEANTYPE(tmp) && pdf_boolean_value(tmp)) + WARN("File contains tagged PDF. Ignoring tags."); + pdf_release_obj(markinfo); + } + + page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); + pdf_release_obj(catalog); + } + if (!page_tree) { + WARN("Page tree not found."); + return NULL; + } + + /* + * 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); + pdf_release_obj(page_tree); + return NULL; + } + page_no = page_idx+1; + } + + /* + * Seek correct page. Get Media/Crop Box. + * Media box and resources can be inherited. + */ + { + pdf_obj *kids_ref, *kids; + pdf_obj *crop_box = NULL; + pdf_obj *tmp; + + tmp = pdf_lookup_dict(page_tree, "Resources"); + resources = tmp ? pdf_deref_obj(tmp) : pdf_new_dict(); + + 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; + } else + pdf_release_obj(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; + } else + pdf_release_obj(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; + } else + pdf_release_obj(tmp); + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { + if (crop_box) + pdf_release_obj(crop_box); + crop_box = tmp; + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { + if (rotate) + pdf_release_obj(rotate); + rotate = tmp; + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { +#if 0 + pdf_merge_dict(tmp, resources); +#endif + if (resources) + 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); + 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; + } + + if (ret_bbox != NULL) + *ret_bbox = bbox; + if (ret_resources != NULL) + *ret_resources = resources; + + 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; + 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++; + } + 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; + } + /* 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; + } + pdf_release_obj(contents); + contents = content_new; + } + + return contents; +} +#endif + +int +pdf_include_page (pdf_ximage *ximage, FILE *image_file, const char *filename) +{ + pdf_file *pf; + xform_info info; + pdf_obj *contents = NULL, *catalog; + pdf_obj *page = NULL, *resources = NULL, *markinfo = NULL; + long page_no; + + pf = pdf_open(filename, image_file); + if (!pf) + return -1; + + if (pdf_file_get_version(pf) > pdf_get_version()) + goto too_recent; + + pdf_ximage_init_form_info(&info); + + /* + * Get Page. + */ + page_no = pdf_ximage_get_page(ximage); + if (page_no == 0) + page_no = 1; + + page = pdf_doc_get_page(pf, page_no, NULL, &info.bbox, &resources); + if(!page) + goto error_silent; + + catalog = pdf_file_get_catalog(pf); + markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); + if (markinfo) { + pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(markinfo, "Marked")); + pdf_release_obj(markinfo); + if (!PDF_OBJ_BOOLEANTYPE(tmp)) { + if (tmp) + pdf_release_obj(tmp); + goto error; + } else if (pdf_boolean_value(tmp)) + WARN("File contains tagged PDF. Ignoring tags."); + pdf_release_obj(tmp); + } + + contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents")); + pdf_release_obj(page); + page = NULL; + + /* + * Handle page content stream. + */ + { + pdf_obj *content_new; + + if (!contents) { + /* + * Empty page + */ + content_new = pdf_new_stream(0); + /* TODO: better don't include anything if the page is empty */ + } else if (PDF_OBJ_STREAMTYPE(contents)) { + /* + * We must import the stream because its dictionary + * may contain indirect references. + */ + content_new = pdf_import_object(contents); + } else if (PDF_OBJ_ARRAYTYPE(contents)) { + /* + * Concatenate all content streams. + */ + int idx, len = pdf_array_length(contents); + content_new = pdf_new_stream(STREAM_COMPRESS); + for (idx = 0; idx < len; idx++) { + pdf_obj *content_seg = pdf_deref_obj(pdf_get_array(contents, idx)); + if (!PDF_OBJ_STREAMTYPE(content_seg) || + pdf_concat_stream(content_new, content_seg) < 0) { + pdf_release_obj(content_seg); + pdf_release_obj(content_new); + goto error; + } + pdf_release_obj(content_seg); + } + } else + goto error; + + if (contents) + pdf_release_obj(contents); + contents = content_new; + } + + /* + * Add entries to contents stream dictionary. + */ + { + pdf_obj *contents_dict, *bbox, *matrix; + + contents_dict = pdf_stream_dict(contents); + pdf_add_dict(contents_dict, + pdf_new_name("Type"), + pdf_new_name("XObject")); + pdf_add_dict(contents_dict, + pdf_new_name("Subtype"), + pdf_new_name("Form")); + pdf_add_dict(contents_dict, + pdf_new_name("FormType"), + pdf_new_number(1.0)); + + bbox = pdf_new_array(); + pdf_add_array(bbox, pdf_new_number(info.bbox.llx)); + pdf_add_array(bbox, pdf_new_number(info.bbox.lly)); + pdf_add_array(bbox, pdf_new_number(info.bbox.urx)); + pdf_add_array(bbox, pdf_new_number(info.bbox.ury)); + + pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox); + + matrix = pdf_new_array(); + pdf_add_array(matrix, pdf_new_number(1.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(1.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + pdf_add_array(matrix, pdf_new_number(0.0)); + + pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix); + + pdf_add_dict(contents_dict, pdf_new_name("Resources"), + pdf_import_object(resources)); + pdf_release_obj(resources); + } + + pdf_close(pf); + + pdf_ximage_set_form(ximage, &info, contents); + + return 0; + + error: + WARN("Cannot parse document. Broken PDF file?"); + error_silent: + if (resources) + pdf_release_obj(resources); + if (markinfo) + pdf_release_obj(markinfo); + if (page) + pdf_release_obj(page); + if (contents) + pdf_release_obj(contents); + + pdf_close(pf); + + return -1; + + too_recent: + pdf_close(pf); + WARN("PDF version of input file more recent than in output file."); + if (compat_mode) { + WARN("Converting. Use \"-V\" switch to change output PDF version."); + return 1; + } else { + WARN("Use \"-V\" switch to change output PDF version."); + return -1; + } +} + +#ifdef XETEX +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; + const char *clip_path, *end_path; + char *save_path, *temp; + pdf_tmatrix M; + double stack[6]; + pdf_file *pf; + + pf = pdf_open(NULL, image_file); + if (!pf) + return -1; + + pdf_dev_currentmatrix(&M); + pdf_invertmatrix(&M); + M.e += x_user; M.f += y_user; + page_tree = pdf_get_page_obj (pf, pageNo, NULL, NULL); + if (!page_tree) { + pdf_close(pf); + return -1; + } + + contents = pdf_get_page_content(page_tree); + pdf_release_obj(page_tree); + if (!contents) { + pdf_close(pf); + return -1; + } + + pdf_doc_add_page_content(" ", 1); + + save_path = malloc(pdf_stream_length(contents) + 1); + strncpy(save_path, (const char *) pdf_stream_dataptr(contents), pdf_stream_length(contents)); + clip_path = save_path; + end_path = clip_path + pdf_stream_length(contents); + depth = 0; + + for (; clip_path < end_path; clip_path++) { + int color_dimen = 0; /* silence uninitialized warning */ + 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, pf); + 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; + } + } + } + free(save_path); + + pdf_release_obj(contents); + pdf_close(pf); + + return 0; +} + +#define WBUF_SIZE 4096 +#if HAVE_ZLIB +static int +add_stream_flate (pdf_obj *dst, const void *data, long len) +{ + z_stream z; + Bytef wbuf[WBUF_SIZE]; + + z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; + + z.next_in = (Bytef *) data; z.avail_in = len; + z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; + + if (inflateInit(&z) != Z_OK) { + WARN("inflateInit() failed."); + return -1; + } + + for (;;) { + int status; + status = inflate(&z, Z_NO_FLUSH); + if (status == Z_STREAM_END) + break; + else if (status != Z_OK) { + WARN("inflate() failed. Broken PDF file?"); + inflateEnd(&z); + return -1; + } + + if (z.avail_out == 0) { + pdf_add_stream(dst, wbuf, WBUF_SIZE); + z.next_out = wbuf; + z.avail_out = WBUF_SIZE; + } + } + + if (WBUF_SIZE - z.avail_out > 0) + pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); + + return (inflateEnd(&z) == Z_OK ? 0 : -1); +} +#endif + +static int +concat_stream (pdf_obj *dst, pdf_obj *src) +{ + const char *stream_data; + long stream_length; + pdf_obj *stream_dict; + pdf_obj *filter; + + if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) + ERROR("Invalid type."); + + stream_data = pdf_stream_dataptr(src); + stream_length = pdf_stream_length (src); + stream_dict = pdf_stream_dict (src); + + if (pdf_lookup_dict(stream_dict, "DecodeParms")) { + WARN("DecodeParams not supported."); + return -1; + } + + filter = pdf_lookup_dict(stream_dict, "Filter"); + if (!filter) { + pdf_add_stream(dst, stream_data, stream_length); + return 0; +#if HAVE_ZLIB + } else { + char *filter_name; + if (PDF_OBJ_NAMETYPE(filter)) { + filter_name = pdf_name_value(filter); + if (filter_name && !strcmp(filter_name, "FlateDecode")) + return add_stream_flate(dst, stream_data, stream_length); + else { + WARN("DecodeFilter \"%s\" not supported.", filter_name); + return -1; + } + } else if (PDF_OBJ_ARRAYTYPE(filter)) { + if (pdf_array_length(filter) > 1) { + WARN("Multiple DecodeFilter not supported."); + return -1; + } else { + filter_name = pdf_name_value(pdf_get_array(filter, 0)); + if (filter_name && !strcmp(filter_name, "FlateDecode")) + return add_stream_flate(dst, stream_data, stream_length); + else { + WARN("DecodeFilter \"%s\" not supported.", filter_name); + return -1; + } + } + } else + ERROR("Broken PDF file?"); +#endif /* HAVE_ZLIB */ + } + + return -1; +} +#endif diff --git a/Build/source/texk/dvipdfm-x/epdf.h b/Build/source/texk/dvipdfm-x/epdf.h index 3efa4884969..2740bfc3cd3 100644 --- a/Build/source/texk/dvipdfm-x/epdf.h +++ b/Build/source/texk/dvipdfm-x/epdf.h @@ -2,7 +2,7 @@ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2002-2013 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team. Copyright (C) 1998, 1999 by Mark A. Wicks @@ -28,7 +28,6 @@ #include "mfileio.h" #include "pdfximage.h" -#ifdef XETEX #define pdfbox_crop 1 #define pdfbox_media 2 #define pdfbox_bleed 3 @@ -36,11 +35,7 @@ #define pdfbox_art 5 extern int pdf_copy_clip (FILE *image_file, int page_index, double x_user, double y_user); -#endif -#if 0 -extern int pdf_include_page (pdf_ximage *ximage, FILE *file, int page_index, int pdf_box); -#endif extern int pdf_include_page (pdf_ximage *ximage, FILE *file, const char *filename); diff --git a/Build/source/texk/dvipdfm-x/jpegimage.c b/Build/source/texk/dvipdfm-x/jpegimage.c new file mode 100644 index 00000000000..c57182cb0d9 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/jpegimage.c @@ -0,0 +1,951 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2013 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * JPEG SUPPORT + * + * Accroding to Libjpeg document: + * + * CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK + * JPEG files: 0 represents 100% ink coverage, rather than 0% ink as you'd + * expect.... + * + * To wrok with this problem, we must detect whether CMYK JPEG file is + * created by Photoshop. But there are no reliable way to determine this. + * + * According to Adobe Technical Note #5516, + * "Supporting the DCT Filters in PostScript Level 2", Section 18, p.27. + * + * DCTDecode ignores and skips any APPE marker segment does not begin with + * the `Adobe' 5-character string. + * + * PDF Reference Manual 4th ed., p.61-62. + * + * The JPEG filter implementation in Adobe Acrobat products does not + * support features of the JPEG standard that are irrelevant to images. + * In addition, certain choices have been made regarding reserved marker + * codes and other optional features of the standard. For details, see + * Adobe Technical Note #5116, Supporting the DCT Filters in PostScript + * Level 2. + */ + +#include "system.h" +#include "error.h" +#include "mem.h" + +#include "mfileio.h" +#include "numbers.h" + +#include "dvipdfmx.h" + +#include "pdfobj.h" + +#include "jpegimage.h" +#include "pdfcolor.h" + +#include "pdfximage.h" + +#define JPEG_DEBUG_STR "JPEG" +#define JPEG_DEBUG 3 + +#ifdef HAVE_LIBJPEG +#include +#endif /* HAVE_LIBJPEG */ + +/* JPEG Markers */ +typedef enum { + JM_SOF0 = 0xc0, + JM_SOF1 = 0xc1, + JM_SOF2 = 0xc2, + JM_SOF3 = 0xc3, + JM_SOF5 = 0xc5, + JM_DHT = 0xc4, + JM_SOF6 = 0xc6, + JM_SOF7 = 0xc7, + JM_SOF9 = 0xc9, + JM_SOF10 = 0xca, + JM_SOF11 = 0xcb, + JM_DAC = 0xcc, + JM_SOF13 = 0xcd, + JM_SOF14 = 0xce, + JM_SOF15 = 0xcf, + + JM_RST0 = 0xd0, + JM_RST1 = 0xd1, + JM_RST2 = 0xd2, + JM_RST3 = 0xd3, + JM_RST4 = 0xd4, + JM_RST5 = 0xd5, + JM_RST6 = 0xd6, + JM_RST7 = 0xd7, + + JM_SOI = 0xd8, + JM_EOI = 0xd9, + JM_SOS = 0xda, + JM_DQT = 0xdb, + JM_DNL = 0xdc, + JM_DRI = 0xdd, + JM_DHP = 0xde, + JM_EXP = 0xdf, + + JM_APP0 = 0xe0, + JM_APP1 = 0xe1, + JM_APP2 = 0xe2, + JM_APP14 = 0xee, + JM_APP15 = 0xef, + + JM_COM = 0xfe +} JPEG_marker; + +typedef enum { + JS_APPn_JFIF, + JS_APPn_ADOBE, + JS_APPn_ICC +} JPEG_APPn_sig; + +struct JPEG_APPn_JFIF /* APP0 */ +{ + unsigned short version; + unsigned char units; /* 0: only aspect ratio + * 1: dots per inch + * 2: dots per cm + */ + unsigned short Xdensity; + unsigned short Ydensity; + unsigned char Xthumbnail; + unsigned char Ythumbnail; + unsigned char *thumbnail; /* Thumbnail data. */ +}; + +struct JPEG_APPn_ICC /* APP2 */ +{ + unsigned char seq_id; + unsigned char num_chunks; + unsigned char *chunk; + + /* Length of ICC profile data in this chunk. */ + unsigned short length; +}; + +struct JPEG_APPn_Adobe /* APP14 */ +{ + unsigned short version; + unsigned short flag0; + unsigned short flag1; + unsigned char transform; /* color transform code */ +}; + +struct JPEG_ext +{ + JPEG_marker marker; + JPEG_APPn_sig app_sig; + void *app_data; +}; + +#define MAX_COUNT 1024 +struct JPEG_info +{ + unsigned short height; + unsigned short width; + + unsigned char bits_per_component; + unsigned char num_components; + + double xdpi; + double ydpi; + + /* Application specific extensions */ + int flags; + int num_appn, max_appn; + struct JPEG_ext *appn; + + /* Skip chunks not necessary. */ + char skipbits[MAX_COUNT / 8 + 1]; +}; + +#define HAVE_APPn_JFIF (1 << 0) +#define HAVE_APPn_ADOBE (1 << 1) +#define HAVE_APPn_ICC (1 << 2) +#define HAVE_APPn_Exif (1 << 3) + +static int JPEG_scan_file (struct JPEG_info *j_info, FILE *fp); +static int JPEG_copy_stream (struct JPEG_info *j_info, + pdf_obj *stream, FILE *fp, int flags); /* flags unused yet */ + +static void JPEG_info_init (struct JPEG_info *j_info); +static void JPEG_info_clear (struct JPEG_info *j_info); +static pdf_obj *JPEG_get_iccp (struct JPEG_info *j_info); +static void jpeg_get_density (struct JPEG_info *j_info, + double *xdensity, double *ydensity); + +int +check_for_jpeg (FILE *fp) +{ + unsigned char jpeg_sig[2]; + + rewind(fp); + if (fread(jpeg_sig, sizeof(unsigned char), 2, fp) != 2) + return 0; + else if (jpeg_sig[0] != 0xff || jpeg_sig[1] != JM_SOI) + return 0; + + return 1; +} + +int +jpeg_include_image (pdf_ximage *ximage, FILE *fp) +{ + pdf_obj *stream; + pdf_obj *stream_dict; + pdf_obj *colorspace; + int colortype; + ximage_info info; + struct JPEG_info j_info; + + if (!check_for_jpeg(fp)) { + WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); + rewind(fp); + return -1; + } + /* File position is 2 here... */ + + pdf_ximage_init_image_info(&info); + + JPEG_info_init(&j_info); + + if (JPEG_scan_file(&j_info, fp) < 0) { + WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); + JPEG_info_clear(&j_info); + return -1; + } + + switch (j_info.num_components) { + case 1: + colortype = PDF_COLORSPACE_TYPE_GRAY; + break; + case 3: + colortype = PDF_COLORSPACE_TYPE_RGB; + break; + case 4: + colortype = PDF_COLORSPACE_TYPE_CMYK; + break; + default: + WARN("%s: Unknown color space (num components: %d)", + JPEG_DEBUG_STR, info.num_components); + JPEG_info_clear(&j_info); + return -1; + } + + /* JPEG image use DCTDecode. */ + stream = pdf_new_stream (0); + stream_dict = pdf_stream_dict(stream); + pdf_add_dict(stream_dict, + pdf_new_name("Filter"), pdf_new_name("DCTDecode")); + + colorspace = NULL; + if (j_info.flags & HAVE_APPn_ICC) { + pdf_obj *icc_stream, *intent; + + icc_stream = JPEG_get_iccp(&j_info); + + if (!icc_stream) + colorspace = NULL; + else { + int cspc_id; + + if (iccp_check_colorspace(colortype, + pdf_stream_dataptr(icc_stream), + pdf_stream_length (icc_stream)) < 0) + colorspace = NULL; + else { + cspc_id = iccp_load_profile(NULL, /* noname */ + pdf_stream_dataptr(icc_stream), + pdf_stream_length (icc_stream)); + if (cspc_id < 0) + colorspace = NULL; + else { + colorspace = pdf_get_colorspace_reference(cspc_id); + intent = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream), + pdf_stream_length (icc_stream)); + if (intent) + pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); + } + } + pdf_release_obj(icc_stream); + } + } + + /* No ICC or invalid ICC profile. */ + if (!colorspace) { + switch (colortype) { + case PDF_COLORSPACE_TYPE_GRAY: + colorspace = pdf_new_name("DeviceGray"); + break; + case PDF_COLORSPACE_TYPE_RGB: + colorspace = pdf_new_name("DeviceRGB"); + break; + case PDF_COLORSPACE_TYPE_CMYK: + colorspace = pdf_new_name("DeviceCMYK"); + break; + } + } + pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); + +#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4) + + if (IS_ADOBE_CMYK(j_info)) { + pdf_obj *decode; + int i; + + WARN("Adobe CMYK JPEG: Inverted color assumed."); + decode = pdf_new_array(); + for (i = 0; i < j_info.num_components; i++) { + pdf_add_array(decode, pdf_new_number(1.0)); + pdf_add_array(decode, pdf_new_number(0.0)); + } + pdf_add_dict(stream_dict, pdf_new_name("Decode"), decode); + } + + /* Copy file */ + JPEG_copy_stream(&j_info, stream, fp, 0); + + info.width = j_info.width; + info.height = j_info.height; + info.bits_per_component = j_info.bits_per_component; + info.num_components = j_info.num_components; + + jpeg_get_density(&j_info, &info.xdensity, &info.ydensity); + + pdf_ximage_set_image(ximage, &info, stream); + JPEG_info_clear(&j_info); + + return 0; +} + +static void +jpeg_get_density (struct JPEG_info *j_info, + double *xdensity, double *ydensity) +{ + if (compat_mode) { + *xdensity = *ydensity = 72.0 / 100.0; + return; + } + + *xdensity = *ydensity = 1.0; + + if (j_info->flags & HAVE_APPn_JFIF) { + struct JPEG_APPn_JFIF *app_data; + 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) { + app_data = (struct JPEG_APPn_JFIF *)j_info->appn[i].app_data; + switch (app_data->units) { + case 1: /* pixels per inch */ + *xdensity = 72.0 / app_data->Xdensity; + *ydensity = 72.0 / app_data->Ydensity; + break; + case 2: /* pixels per centimeter */ + *xdensity = 72.0 / 2.54 / app_data->Xdensity; + *ydensity = 72.0 / 2.54 / app_data->Ydensity; + break; + default: + break; + } + } + } +} + +static void +JPEG_info_init (struct JPEG_info *j_info) +{ + j_info->width = 0; + j_info->height = 0; + j_info->bits_per_component = 0; + j_info->num_components = 0; + + j_info->xdpi = 0.0; + j_info->ydpi = 0.0; + + j_info->flags = 0; + j_info->num_appn = 0; + j_info->max_appn = 0; + j_info->appn = NULL; + + memset(j_info->skipbits, 0, MAX_COUNT / 8 + 1); +} + +static void +JPEG_release_APPn_data (JPEG_marker marker, JPEG_APPn_sig app_sig, void *app_data) +{ + if (marker == JM_APP0 && + app_sig == JS_APPn_JFIF) { + struct JPEG_APPn_JFIF *data; + + data = (struct JPEG_APPn_JFIF *) app_data; + if (data->thumbnail) + RELEASE(data->thumbnail); + data->thumbnail = NULL; + + RELEASE(data); + } else if (marker == JM_APP2 && + app_sig == JS_APPn_ICC) { + struct JPEG_APPn_ICC *data; + + data = (struct JPEG_APPn_ICC *) app_data; + if (data->chunk) + RELEASE(data->chunk); + data->chunk = NULL; + + RELEASE(data); + } else if (marker == JM_APP14 && + app_sig == JS_APPn_ADOBE) { + struct JPEG_APPn_Adobe *data; + + data = (struct JPEG_APPn_Adobe *) app_data; + + RELEASE(data); + } +} + +static void +JPEG_info_clear (struct JPEG_info *j_info) +{ + if (j_info->num_appn > 0 && + j_info->appn != NULL) { + int i; + + for (i = 0; i < j_info->num_appn; i++) + JPEG_release_APPn_data(j_info->appn[i].marker, + j_info->appn[i].app_sig, j_info->appn[i].app_data); + RELEASE(j_info->appn); + } + j_info->appn = NULL; + j_info->num_appn = 0; + j_info->max_appn = 0; + j_info->flags = 0; +} + +static pdf_obj * +JPEG_get_iccp (struct JPEG_info *j_info) +{ + pdf_obj *icc_stream; + struct JPEG_APPn_ICC *icc; + int i, prev_id = 0, num_icc_seg = -1; + + icc_stream = pdf_new_stream(STREAM_COMPRESS); + for (i = 0; i < j_info->num_appn; i++) { + if (j_info->appn[i].marker != JM_APP2 || + j_info->appn[i].app_sig != JS_APPn_ICC) + continue; + icc = (struct JPEG_APPn_ICC *) j_info->appn[i].app_data; + if (num_icc_seg < 0 && prev_id == 0) { + num_icc_seg = icc->num_chunks; + /* ICC chunks are sorted? */ + } else if (icc->seq_id != prev_id + 1 || + num_icc_seg != icc->num_chunks || + icc->seq_id > icc->num_chunks) { + WARN("Invalid JPEG ICC chunk: %d (p:%d, n:%d)", + icc->seq_id, prev_id, icc->num_chunks); + pdf_release_obj(icc_stream); + icc_stream = NULL; + break; + } + pdf_add_stream(icc_stream, icc->chunk, icc->length); + prev_id = icc->seq_id; + num_icc_seg = icc->num_chunks; + } + + return icc_stream; +} + +static JPEG_marker +JPEG_get_marker (FILE *fp) +{ + int c; + + c = fgetc(fp); + if (c != 255) + return -1; + + for (;;) { + c = fgetc(fp); + if (c < 0) + return -1; + else if (c > 0 && c < 255) { + return c; + } + } + + return -1; +} + +static int +add_APPn_marker (struct JPEG_info *j_info, + JPEG_marker marker, int app_sig, void *app_data) +{ + int n; + + if (j_info->num_appn >= j_info->max_appn) { + j_info->max_appn += 16; + j_info->appn = RENEW(j_info->appn, j_info->max_appn, struct JPEG_ext); + } + n = j_info->num_appn; + + j_info->appn[n].marker = marker; + j_info->appn[n].app_sig = app_sig; + j_info->appn[n].app_data = app_data; + + j_info->num_appn += 1; + + return n; +} + +static unsigned short +read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp, unsigned short length) +{ + struct JPEG_APPn_Adobe *app_data; + + app_data = NEW(1, struct JPEG_APPn_Adobe); + app_data->version = get_unsigned_pair(fp); + app_data->flag0 = get_unsigned_pair(fp); + app_data->flag1 = get_unsigned_pair(fp); + app_data->transform = get_unsigned_byte(fp); + + add_APPn_marker(j_info, JM_APP14, JS_APPn_ADOBE, app_data); + + 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; + int num_fields, tag, type; + int value = 0, num = 0, den = 0; /* silence uninitialized warnings */ + 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); + 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) +{ + struct JPEG_APPn_JFIF *app_data; + unsigned short thumb_data_len; + + app_data = NEW(1, struct JPEG_APPn_JFIF); + app_data->version = get_unsigned_pair(fp); + app_data->units = get_unsigned_byte(fp); + app_data->Xdensity = get_unsigned_pair(fp); + app_data->Ydensity = get_unsigned_pair(fp); + app_data->Xthumbnail = get_unsigned_byte(fp); + app_data->Ythumbnail = get_unsigned_byte(fp); + thumb_data_len = 3 * app_data->Xthumbnail * app_data->Ythumbnail; + if (thumb_data_len > 0) { + app_data->thumbnail = NEW(thumb_data_len, unsigned char); + fread(app_data->thumbnail, 1, thumb_data_len, fp); + } else { + app_data->thumbnail = NULL; + } + + add_APPn_marker(j_info, JM_APP0, JS_APPn_JFIF, app_data); + + switch (app_data->units) { + case 1: + j_info->xdpi = app_data->Xdensity; + j_info->ydpi = app_data->Ydensity; + break; + case 2: /* density is in pixels per cm */ + j_info->xdpi = app_data->Xdensity * 2.54; + j_info->ydpi = app_data->Ydensity * 2.54; + break; + default: /* FIXME: not sure what to do with this.... */ + j_info->xdpi = 72.0; + j_info->ydpi = 72.0 * app_data->Ydensity / app_data->Xdensity; + break; + } + + return (9 + thumb_data_len); +} + +static unsigned short +read_APP0_JFXX (struct JPEG_info *j_info, FILE *fp, unsigned short length) +{ + get_unsigned_byte(fp); + /* Extension Code: + * + * 0x10: Thumbnail coded using JPEG + * 0x11: Thumbnail stored using 1 byte/pixel + * 0x13: Thumbnail stored using 3 bytes/pixel + */ + seek_relative(fp, length-1); /* Thunbnail image */ + + /* Ignore */ + + return length; +} + +static unsigned short +read_APP2_ICC (struct JPEG_info *j_info, FILE *fp, unsigned short length) +{ + struct JPEG_APPn_ICC *app_data; + + app_data = NEW(1, struct JPEG_APPn_ICC); + app_data->seq_id = get_unsigned_byte(fp); /* Starting at 1 */ + app_data->num_chunks = get_unsigned_byte(fp); + app_data->length = length - 2; + app_data->chunk = NEW(app_data->length, unsigned char); + fread(app_data->chunk, 1, app_data->length, fp); + + add_APPn_marker(j_info, JM_APP2, JS_APPn_ICC, app_data); + + return length; +} + +static int +JPEG_copy_stream (struct JPEG_info *j_info, + pdf_obj *stream, FILE *fp, int flags) /* flags unused yet */ +{ + JPEG_marker marker; + long length, nb_read; + int found_SOFn, count; + + rewind(fp); + count = 0; + found_SOFn = 0; + while (!found_SOFn && + count < MAX_COUNT && + (marker = JPEG_get_marker(fp)) >= 0) { + if (marker == JM_SOI || + (marker >= JM_RST0 && marker <= JM_RST7)) { + work_buffer[0] = (char) 0xff; + work_buffer[1] = (char) marker; + pdf_add_stream(stream, work_buffer, 2); + count++; + continue; + } + length = get_unsigned_pair(fp) - 2; + switch (marker) { + case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: + case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: + case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: + case JM_SOF15: + work_buffer[0] = (char) 0xff; + work_buffer[1] = (char) marker; + work_buffer[2] = ((length + 2) >> 8) & 0xff; + work_buffer[3] = (length + 2) & 0xff; + pdf_add_stream(stream, work_buffer, 4); + while (length > 0) { + nb_read = fread(work_buffer, sizeof(char), + MIN(length, WORK_BUFFER_SIZE), fp); + if (nb_read > 0) + pdf_add_stream(stream, work_buffer, nb_read); + length -= nb_read; + } + found_SOFn = 1; + break; + default: + if (j_info->skipbits[count / 8] & (1 << (7 - (count % 8)))) { + /* skip */ + while (length > 0) { + nb_read = fread(work_buffer, sizeof(char), + MIN(length, WORK_BUFFER_SIZE), fp); + length -= nb_read; + } + } else { + work_buffer[0] = (char) 0xff; + work_buffer[1] = (char) marker; + work_buffer[2] = ((length + 2) >> 8) & 0xff; + work_buffer[3] = (length + 2) & 0xff; + pdf_add_stream(stream, work_buffer, 4); + while (length > 0) { + nb_read = fread(work_buffer, sizeof(char), + MIN(length, WORK_BUFFER_SIZE), fp); + if (nb_read > 0) + pdf_add_stream(stream, work_buffer, nb_read); + length -= nb_read; + } + } + } + count++; + } + + while ((length = fread(work_buffer, + sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) { + pdf_add_stream(stream, work_buffer, length); + } + + return (found_SOFn ? 0 : -1); +} + +static int +JPEG_scan_file (struct JPEG_info *j_info, FILE *fp) +{ + JPEG_marker marker; + unsigned short length; + int found_SOFn, count; + char app_sig[128]; + + rewind(fp); + count = 0; + found_SOFn = 0; + while (!found_SOFn && + (marker = JPEG_get_marker(fp)) >= 0) { + if (marker == JM_SOI || + (marker >= JM_RST0 && marker <= JM_RST7)) { + count++; + continue; + } + length = get_unsigned_pair(fp) - 2; + switch (marker) { + case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: + case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: + case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: + case JM_SOF15: + j_info->bits_per_component = get_unsigned_byte(fp); + j_info->height = get_unsigned_pair(fp); + j_info->width = get_unsigned_pair(fp); + j_info->num_components = get_unsigned_byte(fp); + found_SOFn = 1; + break; + case JM_APP0: + if (length > 5) { + if (fread(app_sig, sizeof(char), 5, fp) != 5) + return -1; + length -= 5; + if (!memcmp(app_sig, "JFIF\000", 5)) { + j_info->flags |= HAVE_APPn_JFIF; + length -= read_APP0_JFIF(j_info, fp, length); + } else if (!memcmp(app_sig, "JFXX", 5)) { + length -= read_APP0_JFXX(j_info, fp, length); + } + } + 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)) { + j_info->flags |= HAVE_APPn_Exif; + 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) + return -1; + length -= 12; + if (!memcmp(app_sig, "ICC_PROFILE\000", 12)) { + j_info->flags |= HAVE_APPn_ICC; + length -= read_APP2_ICC(j_info, fp, length); + if (count < MAX_COUNT) { + j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); + } + } + } + seek_relative(fp, length); + break; + case JM_APP14: + if (length > 5) { + if (fread(app_sig, sizeof(char), 5, fp) != 5) + return -1; + length -= 5; + if (!memcmp(app_sig, "Adobe", 5)) { + j_info->flags |= HAVE_APPn_ADOBE; + length -= read_APP14_Adobe(j_info, fp, length); + } else { + if (count < MAX_COUNT) { + j_info->skipbits[count/8] |= (1 << (7 - (count % 8))); + } + } + } + seek_relative(fp, length); + break; + default: + seek_relative(fp, length); + if (marker >= JM_APP0 && + marker <= JM_APP15) { + if (count < MAX_COUNT) { + j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); + } + } + break; + } + count++; + } + + return (found_SOFn ? 0 : -1); +} + +int +jpeg_get_bbox (FILE *fp, long *width, long *height, + double *xdensity, double *ydensity) +{ + struct JPEG_info j_info; + + JPEG_info_init(&j_info); + + if (JPEG_scan_file(&j_info, fp) < 0) { + WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); + JPEG_info_clear(&j_info); + return -1; + } + + *width = j_info.width; + *height = j_info.height; + + jpeg_get_density(&j_info, xdensity, ydensity); + + JPEG_info_clear(&j_info); + + return 0; +} diff --git a/Build/source/texk/dvipdfm-x/mpost.c b/Build/source/texk/dvipdfm-x/mpost.c index c5feb0cb1b6..703d0b45a36 100644 --- a/Build/source/texk/dvipdfm-x/mpost.c +++ b/Build/source/texk/dvipdfm-x/mpost.c @@ -1213,12 +1213,8 @@ do_operator (const char *token, double x_user, double y_user) pdf_color_cmykcolor(&color, values[0], values[1], values[2], values[3]); -#ifdef XETEX - pdf_dev_set_color(&color); -#else pdf_dev_set_strokingcolor(&color); pdf_dev_set_nonstrokingcolor(&color); -#endif } break; case SETGRAY: @@ -1226,12 +1222,8 @@ 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]); -#ifdef XETEX - pdf_dev_set_color(&color); -#else pdf_dev_set_strokingcolor(&color); pdf_dev_set_nonstrokingcolor(&color); -#endif } break; case SETRGBCOLOR: @@ -1239,12 +1231,8 @@ do_operator (const char *token, double x_user, double y_user) if (!error) { pdf_color_rgbcolor(&color, values[0], values[1], values[2]); -#ifdef XETEX - pdf_dev_set_color(&color); -#else pdf_dev_set_strokingcolor(&color); pdf_dev_set_nonstrokingcolor(&color); -#endif } break; diff --git a/Build/source/texk/dvipdfm-x/pdfcolor.c b/Build/source/texk/dvipdfm-x/pdfcolor.c new file mode 100644 index 00000000000..191e9236429 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfcolor.c @@ -0,0 +1,1589 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 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. +*/ + +/* No page independence here... + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "mem.h" +#include "error.h" + +#include "dpxfile.h" + +#include "pdfdoc.h" +#include "pdfdev.h" + +#include "pdfcolor.h" + + +static int verbose = 0; +void +pdf_color_set_verbose (void) +{ + verbose++; +} + +#ifndef XETEX +/* This function returns PDF_COLORSPACE_TYPE_GRAY, + * PDF_COLORSPACE_TYPE_RGB or PDF_COLORSPACE_TYPE_CMYK. + */ +int +pdf_color_type (const pdf_color *color) +{ + ASSERT(color); + + return -color->num_components; +} +#endif + +int +pdf_color_rgbcolor (pdf_color *color, double r, double g, double b) +{ + ASSERT(color); + + if (r < 0.0 || r > 1.0) { + WARN("Invalid color value specified: red=%g", r); + return -1; + } + if (g < 0.0 || g > 1.0) { + WARN("Invalid color value specified: green=%g", g); + return -1; + } + if (b < 0.0 || b > 1.0) { + WARN("Invalid color value specified: blue=%g", b); + return -1; + } + color->values[0] = r; + color->values[1] = g; + color->values[2] = b; + + color->num_components = 3; + + return 0; +} + +int +pdf_color_cmykcolor (pdf_color *color, + double c, double m, double y, double k) +{ + ASSERT(color); + + if (c < 0.0 || c > 1.0) { + WARN("Invalid color value specified: cyan=%g", c); + return -1; + } + if (m < 0.0 || m > 1.0) { + WARN("Invalid color value specified: magenta=%g", m); + return -1; + } + if (y < 0.0 || y > 1.0) { + WARN("Invalid color value specified: yellow=%g", y); + return -1; + } + if (k < 0.0 || k > 1.0) { + WARN("Invalid color value specified: black=%g", k); + return -1; + } + + color->values[0] = c; + color->values[1] = m; + color->values[2] = y; + color->values[3] = k; + + color->num_components = 4; + + return 0; +} + +int +pdf_color_graycolor (pdf_color *color, double g) +{ + ASSERT(color); + + if (g < 0.0 || g > 1.0) { + WARN("Invalid color value specified: gray=%g", g); + return -1; + } + + color->values[0] = g; + + color->num_components = 1; + + return 0; +} + + +void +pdf_color_copycolor (pdf_color *color1, const pdf_color *color2) +{ + ASSERT(color1 && color2); + + memcpy(color1, color2, sizeof(pdf_color)); +} + +/* Brighten up a color. f == 0 means no change, f == 1 means white. */ +void +pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f) +{ + ASSERT(dst && src); + + if (f == 1.0) { + pdf_color_white(dst); + } else { + double f0, f1; + int n; + + n = dst->num_components = src->num_components; + f1 = n == 4 ? 0.0 : f; /* n == 4 is CMYK, others are RGB and Gray */ + f0 = 1.0-f; + + while (n--) + dst->values[n] = f0 * src->values[n] + f1; + } +} + +int +pdf_color_is_white (const pdf_color *color) +{ + int n; + double f; + + ASSERT(color); + + n = color->num_components; + switch (n) { + case 1: /* Gray */ + case 3: /* RGB */ + f = 1.0; + break; + case 4: /* CMYK */ + f = 0.0; + break; + default: + return 0; + } + + while (n--) + if (color->values[n] != f) + return 0; + + return 1; +} + +#ifndef XETEX +int +pdf_color_to_string (const pdf_color *color, char *buffer) +{ + int i, len = 0; + + for (i = 0; i < color->num_components; i++) { + len += sprintf(buffer+len, " %g", ROUND(color->values[i], 0.001)); + } + return len; +} +#endif + +pdf_color current_fill = { + 1, + {0.0, 0.0, 0.0, 0.0} +}; + +pdf_color current_stroke = { + 1, + {0.0, 0.0, 0.0, 0.0} +}; + +#ifndef XETEX +/* + * This routine is not a real color matching. + */ +int +pdf_color_compare (const pdf_color *color1, const pdf_color *color2) +{ + int n; + + n = color1->num_components; + switch (n) { + case 1: /* Gray */ + case 3: /* RGB */ + case 4: /* CMYK */ + break; + default: + return -1; + } + + if (n != color2->num_components) + return -1; + + while (n--) + if (color1->values[n] != color2->values[n]) + return -1; + + return 0; +} +#endif + +int +pdf_color_is_valid (const pdf_color *color) +{ + int n; + + n = color->num_components; + switch (n) { + case 1: /* Gray */ + case 3: /* RGB */ + case 4: /* CMYK */ + break; + default: + return 0; + } + + while (n--) + if (color->values[n] < 0.0 || color->values[n] > 1.0) { + WARN("Invalid color value: %g", color->values[n]); + return 0; + } + + return 1; +} + +/* Dvipdfm special */ +pdf_color default_color = { + 1, + {0.0, 0.0, 0.0, 0.0} +}; + +void +pdf_color_set_default (const pdf_color *color) +{ + pdf_color_copycolor(&default_color, color); +} + +#define DEV_COLOR_STACK_MAX 128 + +static struct { + int current; + pdf_color stroke[DEV_COLOR_STACK_MAX]; + pdf_color fill[DEV_COLOR_STACK_MAX]; +} color_stack = { + 0, +}; + +void +pdf_color_clear_stack (void) +{ + if (color_stack.current > 0) { + WARN("You've mistakenly made a global color change within nested colors."); + } + color_stack.current = 0; +#ifdef XETEX + pdf_color_copycolor(&color_stack.stroke[color_stack.current], &default_color); + pdf_color_copycolor(&color_stack.fill[color_stack.current], &default_color); +#else + pdf_color_black(color_stack.stroke); + pdf_color_black(color_stack.fill); +#endif + return; +} + +void +pdf_color_set (pdf_color *sc, pdf_color *fc) +{ + pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); + pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); + pdf_dev_reset_color(0); +} + +void +pdf_color_push (pdf_color *sc, pdf_color *fc) +{ + if (color_stack.current >= DEV_COLOR_STACK_MAX-1) { + WARN("Color stack overflow. Just ignore."); + } else { + color_stack.current++; +#ifdef XETEX + pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); + pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); + pdf_dev_reset_color(0); +#else + pdf_color_set(sc, fc); +#endif + } + return; +} + +void +pdf_color_pop (void) +{ + if (color_stack.current <= 0) { + WARN("Color stack underflow. Just ignore."); + } else { + color_stack.current--; + pdf_dev_reset_color(0); + } + return; +} + +void +pdf_color_get_current (pdf_color **sc, pdf_color **fc) +{ + *sc = &color_stack.stroke[color_stack.current]; + *fc = &color_stack.fill[color_stack.current]; + return; +} + +#if 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) +{ + if (color_stack.current > 0) { + current_stroke = color_stack.stroke[color_stack.current]; + current_fill = color_stack.fill[color_stack.current]; + } +} +#endif + +/***************************** COLOR SPACE *****************************/ + +static int pdf_colorspace_defineresource (const char *ident, + int subtype, + void *cdata, pdf_obj *resource); + +static int pdf_colorspace_findresource (const char *ident, + int subtype, const void *cdata); + +#if 0 +struct calgray_cdata +{ + double white_point[3]; /* required, second component must + * be equal to 1.0 + */ + double black_point[3]; /* optional, default: [0 0 0] */ + double gamma; /* optional, default: 1.0 */ +}; + +struct calrgb_cdata +{ + double white_point[3]; /* required, second component must + * be equal to 1.0 + */ + double black_point[3]; /* optional, default: [0 0 0] */ + double gamma[3]; /* optional, default: [1 1 1] */ + double matrix[9]; /* optional, default: identity + * [1 0 0 0 1 0 0 0 1] + */ +}; + +static void +release_calrgb (void *cdata) +{ + struct calrgb_cdata *calrgb; + + if (cdata) { + calrgb = (struct calrgb_cdata *) cdata; + RELEASE(calrgb); + } +} + +static int +compare_calrgb (const char *ident1, const void *cdata1, + const char *ident2, const void *cdata2) +{ + struct calrgb_cdata *calrgb1; + struct calrgb_cdata *calrgb2; + + if (ident1 && ident2 && + !strcmp(ident1, ident2)) { + return 0; + } +} + +static void +init_calrgb (struct calrgb_cdata *calrgb) +{ + ASSERT(calrgb); + + calrgb->white_point[0] = 1.0; + calrgb->white_point[1] = 1.0; + calrgb->white_point[2] = 1.0; + + calrgb->black_point[0] = 0.0; + calrgb->black_point[1] = 0.0; + calrgb->black_point[2] = 0.0; + + calrgb->gamma[0] = 1.0; + calrgb->gamma[1] = 1.0; + calrgb->gamma[2] = 1.0; + + calrgb->matrix[0] = 1.0; + calrgb->matrix[1] = 0.0; + calrgb->matrix[2] = 0.0; + + calrgb->matrix[3] = 0.0; + calrgb->matrix[4] = 1.0; + calrgb->matrix[5] = 0.0; + + calrgb->matrix[6] = 0.0; + calrgb->matrix[7] = 0.0; + calrgb->matrix[8] = 1.0; +} + +static int +valid_calrgb (struct calrgb_cdata *calrgb) +{ + if (calrgb->white_point[1] != 1.0 || + calrgb->white_point[0] <= 0.0 || + calrgb->white_point[2] <= 0.0) + return 0; + + if (calrgb->black_point[0] < 0.0 || + calrgb->black_point[1] < 0.0 || + calrgb->black_point[2] < 0.0) + return 0; + + if (calrgb->gamma[0] < 0.0 || + calrgb->gamma[1] < 0.0 || + calrgb->gamma[2] < 0.0) + return 0; + + /* matrix should be invertible? */ + + return 1; +} + +static pdf_obj * +pdf_color_make_calrgb_resource (struct calrgb_cdata *calrgb) +{ + pdf_obj *colorspace; + pdf_obj *calparams, *tmp_array; + + ASSERT(calrgb); + + if (!valid_calrgb(calrgb)) + return NULL; + + colorspace = pdf_new_array(); + calparams = pdf_new_dict(); + + tmp_array = pdf_new_array(); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[0], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(1.0)); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[2], 0.001))); + pdf_add_dict(calparams, pdf_new_name("WhitePoint"), tmp_array); + + if (calrgb->black_point[0] != 0.0 || + calrgb->black_point[1] != 0.0 || + calrgb->black_point[2] != 0.0) { + tmp_array = pdf_new_array(); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[0], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[1], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[2], 0.001))); + pdf_add_dict(calparams, pdf_new_name("BlackPoint"), tmp_array); + } + + if (calrgb->gamma[0] != 1.0 || + calrgb->gamma[1] != 1.0 || + calrgb->gamma[2] != 1.0) { + tmp_array = pdf_new_array(); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[0], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[1], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[2], 0.001))); + pdf_add_dict(calparams, pdf_new_name("Gamma"), tmp_array); + } + + if (calrgb->matrix[0] != 1.0 || + calrgb->matrix[1] != 0.0 || + calrgb->matrix[2] != 0.0 || + calrgb->matrix[3] != 0.0 || + calrgb->matrix[4] != 1.0 || + calrgb->matrix[5] != 0.0 || + calrgb->matrix[6] != 0.0 || + calrgb->matrix[7] != 0.0 || + calrgb->matrix[8] != 1.0) { + tmp_array = pdf_new_array(); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[0], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[1], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[2], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[3], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[4], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[5], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[6], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[7], 0.001))); + pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[8], 0.001))); + pdf_add_dict(calparams, pdf_new_name("Matrix"), tmp_array); + } + + pdf_add_array(colorspace, pdf_new_name("CalRGB")); + pdf_add_array(colorspace, calparams); + + return colorspace; +} +#endif + +static unsigned char nullbytes16[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static struct +{ + int major; + int minor; +} icc_versions[] = { + {0, 0}, /* PDF-1.0, we don't support them */ + {0, 0}, /* PDF-1.1, we don't support them */ + {0, 0}, /* PDF-1.2, we don't support them */ + {0x02, 0x10}, /* PDF-1.3 */ + {0x02, 0x20}, /* PDF-1.4 */ + {0x04, 0x00} /* PDF-1.5 */ +}; + +static int +iccp_version_supported (int major, int minor) +{ + int pdf_ver; + + pdf_ver = pdf_get_version(); + if (pdf_ver < 6) { + if (icc_versions[pdf_ver].major < major) + return 0; + else if (icc_versions[pdf_ver].major == major && + icc_versions[pdf_ver].minor < minor) + return 0; + else { + return 1; + } + } + + return 0; +} + +typedef unsigned long iccSig; +static iccSig +str2iccSig (const void *s) +{ + const char *p; + + p = (const char *) s; + + return (iccSig) ((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); +} + +typedef struct +{ + long X, Y, Z; /* s15Fixed16Numeber */ +} iccXYZNumber; + +typedef struct +{ + long size; + iccSig CMMType; + long version; + iccSig devClass; + iccSig colorSpace; + iccSig PCS; /* Profile Connection Space */ + char creationDate[12]; + iccSig acsp; + iccSig platform; + char flags[4]; + iccSig devMnfct; + iccSig devModel; + char devAttr[8]; + long intent; + iccXYZNumber illuminant; + iccSig creator; + unsigned char ID[16]; /* MD5 checksum with Rendering intent, + * Header attrs, Profile ID fields are + * set to zeros. + */ + /* 28 bytes reserved - must be set to zeros */ +} iccHeader; + +#define iccNullSig 0 +static void +iccp_init_iccHeader (iccHeader *icch) +{ + ASSERT(icch); + + icch->size = 0; + icch->CMMType = iccNullSig; + icch->version = 0xFFFFFF; + icch->devClass = iccNullSig; + icch->colorSpace = iccNullSig; + icch->PCS = iccNullSig; + memset(icch->creationDate, 0, 12); + icch->acsp = str2iccSig("ascp"); + icch->platform = iccNullSig; + memset(icch->flags, 0, 4); + icch->devMnfct = iccNullSig; + icch->devModel = iccNullSig; + memset(icch->devAttr, 0, 8); + icch->intent = 0; + icch->illuminant.X = 0; + icch->illuminant.Y = 0; + icch->illuminant.Z = 0; + icch->creator = iccNullSig; + memset(icch->ID, 0, 16); +} + +#define ICC_INTENT_TYPE(n) ((int) (((n) >> 16) & 0xff)) +#define ICC_INTENT_PERCEPTUAL 0 +#define ICC_INTENT_RELATIVE 1 +#define ICC_INTENT_SATURATION 2 +#define ICC_INTENT_ABSOLUTE 3 + +/* + * In ICC profile stream dicrionary, there is /Range whose values must + * "match the information in the profile". But where is those values in? + * + * How should I treat rendering intent? + */ +struct iccbased_cdata +{ + long sig; /* 'i' 'c' 'c' 'b' */ + + unsigned char checksum[16]; /* 16 bytes MD5 Checksum */ + int colorspace; /* input colorspace: + * RGB, Gray, CMYK, (Lab?) + */ + int alternate; /* alternate colorspace (id), unused */ +}; + +#define check_sig(d,p,q,r,s) ((d) && (d)->sig == ((p)<<24|(q)<<16|(r)<<8|(s))) + +static void +init_iccbased_cdata (struct iccbased_cdata *cdata) +{ + ASSERT(cdata); + + cdata->sig = ('i' << 24|'c' << 16|'c' << 8|'b'); + memset(cdata->checksum, 0, 16); + cdata->colorspace = PDF_COLORSPACE_TYPE_INVALID; + cdata->alternate = -1; + + return; +} + +static void +release_iccbased_cdata (struct iccbased_cdata *cdata) +{ + ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); + + RELEASE(cdata); +} + +static int +get_num_components_iccbased (const struct iccbased_cdata *cdata) +{ + int num_components = 0; + + ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); + + switch (cdata->colorspace) { + case PDF_COLORSPACE_TYPE_RGB: + num_components = 3; + break; + case PDF_COLORSPACE_TYPE_CMYK: + num_components = 4; + break; + case PDF_COLORSPACE_TYPE_GRAY: + num_components = 1; + break; + case PDF_COLORSPACE_TYPE_CIELAB: + num_components = 3; + break; + } + + return num_components; +} + +static int +compare_iccbased (const char *ident1, const struct iccbased_cdata *cdata1, + const char *ident2, const struct iccbased_cdata *cdata2) +{ + if (cdata1 && cdata2) { + + ASSERT(check_sig(cdata1, 'i', 'c', 'c', 'b')); + ASSERT(check_sig(cdata2, 'i', 'c', 'c', 'b')); + + if (memcmp(cdata1->checksum, nullbytes16, 16) && + memcmp(cdata2->checksum, nullbytes16, 16)) { + return memcmp(cdata1->checksum, cdata2->checksum, 16); + } + if (cdata1->colorspace != cdata2->colorspace) { + return (cdata1->colorspace - cdata2->colorspace); + } + + /* Continue if checksum unknown and colorspace is same. */ + } + + if (ident1 && ident2) + return strcmp(ident1, ident2); + + /* No way to compare */ + return -1; +} + +int +iccp_check_colorspace (int colortype, const void *profile, long proflen) +{ + iccSig colorspace; + const unsigned char *p; + + if (!profile || proflen < 128) + return -1; + + p = (const unsigned char *) profile; + + colorspace = str2iccSig(p + 16); + + switch (colortype) { + case PDF_COLORSPACE_TYPE_CALRGB: + case PDF_COLORSPACE_TYPE_RGB: + if (colorspace != str2iccSig("RGB ")) { + return -1; + } + break; + case PDF_COLORSPACE_TYPE_CALGRAY: + case PDF_COLORSPACE_TYPE_GRAY: + if (colorspace != str2iccSig("GRAY")) { + return -1; + } + break; + case PDF_COLORSPACE_TYPE_CMYK: + if (colorspace != str2iccSig("CMYK")) { + return -1; + } + break; + default: + return -1; + break; + } + + return 0; +} + +pdf_obj * +iccp_get_rendering_intent (const void *profile, long proflen) +{ + pdf_obj *ri = NULL; + const unsigned char *p; + long intent; + + if (!profile || proflen < 128) + return NULL; + + p = (const unsigned char *) profile; + + intent = (p[64] << 24)|(p[65] << 16)|(p[66] << 8)|p[67]; + switch (ICC_INTENT_TYPE(intent)) { + case ICC_INTENT_SATURATION: + ri = pdf_new_name("Saturation"); + break; + case ICC_INTENT_PERCEPTUAL: + ri = pdf_new_name("Perceptual"); + break; + case ICC_INTENT_ABSOLUTE: + ri = pdf_new_name("AbsoluteColorimetric"); + break; + case ICC_INTENT_RELATIVE: + ri = pdf_new_name("RelativeColorimetric"); + break; + default: + WARN("Invalid rendering intent type: %d", ICC_INTENT_TYPE(intent)); + ri = NULL; + } + + return ri; +} + +#define sget_signed_long(p) ((long) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) +#define sget_signed_short(p) ((short) ((p)[0] << 8|(p)[1])) +#define get_iccSig(p) ((iccSig) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) + +static int +iccp_unpack_header (iccHeader *icch, + const void *profile, long proflen, int check_size) +{ + const unsigned char *p, *endptr; + + if (check_size) { + if (!profile || proflen < 128 || + proflen % 4 != 0) { + WARN("Profile size: %ld", proflen); + return -1; + } + } + + p = (const unsigned char *) profile; + endptr = p + 128; + + icch->size = sget_signed_long(p); + if (check_size) { + if (icch->size != proflen) { + WARN("ICC Profile size: %ld(header) != %ld", icch->size, proflen); + return -1; + } + } + p += 4; + + icch->CMMType = str2iccSig(p); + p += 4; + icch->version = sget_signed_long(p); + p += 4; + icch->devClass = str2iccSig(p); + p += 4; + icch->colorSpace = str2iccSig(p); + p += 4; + icch->PCS = str2iccSig(p); + p += 4; + memcpy(icch->creationDate, p, 12); + p += 12; + icch->acsp = str2iccSig(p); /* acsp */ + if (icch->acsp != str2iccSig("acsp")) { + WARN("Invalid ICC profile: not \"acsp\" - %c%c%c%c ", + p[0], p[1], p[2], p[3]); + return -1; + } + p += 4; + icch->platform = str2iccSig(p); + p += 4; + memcpy(icch->flags, p, 4); + p += 4; + icch->devMnfct = str2iccSig(p); + p += 4; + icch->devModel = str2iccSig(p); + p += 4; + memcpy(icch->devAttr, p, 8); + p += 8; + icch->intent = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + p += 4; + icch->illuminant.X = sget_signed_long(p); + p += 4; + icch->illuminant.Y = sget_signed_long(p); + p += 4; + icch->illuminant.Z = sget_signed_long(p); + p += 4; + icch->creator = str2iccSig(p); + p += 4; + memcpy(icch->ID, p, 16); + p += 16; + + /* 28 bytes reserved - must be set to zeros */ + for (; p < endptr; p++) { + if (*p != '\0') { + WARN("Reserved pad not zero: %02x (at offset %ld in ICC profile header.)", + *p, 128 - ((long) (endptr - p))); + return -1; + } + } + + return 0; +} + +/* MD5 checksum with Rendering intent, + * Header attrs, Profile ID fields are + * set to zeros. + */ +#define ICC_HEAD_SECT1_START 0 +#define ICC_HEAD_SECT1_LENGTH 56 +/* 8 bytes devAttr, 4 bytes intent */ +#define ICC_HEAD_SECT2_START 68 +#define ICC_HEAD_SECT2_LENGTH 16 +/* 16 bytes ID (checksum) */ +#define ICC_HEAD_SECT3_START 100 +#define ICC_HEAD_SECT3_LENGTH 28 + +#include "dpxcrypt.h" +static void +iccp_get_checksum (unsigned char *checksum, const void *profile, long proflen) +{ + const unsigned char *p; + MD5_CONTEXT md5; + + p = (const unsigned char *) profile; + + MD5_init (&md5); + MD5_write(&md5, p + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); + MD5_write(&md5, nullbytes16, 12); + MD5_write(&md5, p + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); + MD5_write(&md5, nullbytes16, 16); + MD5_write(&md5, p + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); + + /* body */ + MD5_write(&md5, p + 128, proflen - 128); + + MD5_final(checksum, &md5); +} + +static void +print_iccp_header (iccHeader *icch, unsigned char *checksum) +{ + int i; + + ASSERT(icch); + +#define print_iccSig(s,t) if ((s) == 0) {\ + MESG("pdf_color>> %s:\t(null)\n", (t)); \ + } else if (!isprint(((s) >> 24) & 0xff) || \ + !isprint(((s) >> 16) & 0xff) || \ + !isprint(((s) >> 8) & 0xff) || \ + !isprint((s) & 0xff)) { \ + MESG("pdf_color>> %s:\t(invalid)\n", (t)); \ + } else { \ + MESG("pdf_color>> %s:\t%c%c%c%c\n", (t), \ + ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, \ + ((s) >> 8) & 0xff, (s) & 0xff); \ +} + + MESG("\n"); + MESG("pdf_color>> ICC Profile Info\n"); + MESG("pdf_color>> Profile Size:\t%ld bytes\n", icch->size); + print_iccSig(icch->CMMType, "CMM Type"); + MESG("pdf_color>> Profile Version:\t%d.%01d.%01d\n", + (icch->version >> 24) & 0xff, + (icch->version >> 20) & 0x0f, + (icch->version >> 16) & 0x0f); + print_iccSig(icch->devClass, "Device Class"); + print_iccSig(icch->colorSpace, "Color Space"); + print_iccSig(icch->PCS, "Connection Space"); + MESG("pdf_color>> Creation Date:\t"); + for (i = 0; i < 12; i += 2) { + if (i == 0) + MESG("%04u", + sget_unsigned_pair((unsigned char *) icch->creationDate)); + else { + MESG(":%02u", + sget_unsigned_pair((unsigned char *) (&icch->creationDate[i]))); + } + } + MESG("\n"); + print_iccSig(icch->platform, "Primary Platform"); + MESG("pdf_color>> Profile Flags:\t%02x:%02x:%02x:%02x\n", + icch->flags[0], icch->flags[1], icch->flags[2], icch->flags[3]); + print_iccSig(icch->devMnfct, "Device Mnfct"); + print_iccSig(icch->devModel, "Device Model"); + MESG("pdf_color>> Device Attr:\t"); + for (i = 0; i < 8; i++) { + if (i == 0) + MESG("%02x", icch->devAttr[i]); + else + MESG(":%02x", icch->devAttr[i]); + } + MESG("\n"); + MESG("pdf_color>> Rendering Intent:\t"); + switch (ICC_INTENT_TYPE(icch->intent)) { + case ICC_INTENT_SATURATION: + MESG("Saturation"); + break; + case ICC_INTENT_PERCEPTUAL: + MESG("Perceptual"); + break; + case ICC_INTENT_ABSOLUTE: + MESG("Absolute Colorimetric"); + break; + case ICC_INTENT_RELATIVE: + MESG("Relative Colorimetric"); + break; + default: + MESG("(invalid)"); + break; + } + MESG("\n"); + print_iccSig(icch->creator, "Creator"); + MESG("pdf_color>> Illuminant (XYZ):\t"); + MESG("%.3f %.3f %.3f\n", + (double) icch->illuminant.X / 0x10000, + (double) icch->illuminant.Y / 0x10000, + (double) icch->illuminant.Z / 0x10000); + MESG("pdf_color>> Checksum:\t"); + if (!memcmp(icch->ID, nullbytes16, 16)) { + MESG("(null)"); + } else { + for (i = 0; i < 16; i++) { + if (i == 0) + MESG("%02x", icch->ID[i]); + else + MESG(":%02x", icch->ID[i]); + } + } + MESG("\n"); + if (checksum) { + MESG("pdf_color>> Calculated:\t"); + for (i = 0; i < 16; i++) { + if (i == 0) + MESG("%02x", checksum[i]); + else + MESG(":%02x", checksum[i]); + } + MESG("\n"); + } + + return; +} + + +static int +iccp_devClass_allowed (int dev_class) +{ + int colormode; + + colormode = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); + + switch (colormode) { +#if 0 + case PDF_DEV_COLORMODE_PDFX1: + break; + case PDF_DEV_COLORMODE_PDFX3: + if (dev_class != str2iccSig("prtr")) { + return 0; + } + break; +#endif + default: + if (dev_class != str2iccSig("scnr") && + dev_class != str2iccSig("mntr") && + dev_class != str2iccSig("prtr") && + dev_class != str2iccSig("spac")) { + return 0; + } + break; + } + + + return 1; +} + +int +iccp_load_profile (const char *ident, + const void *profile, long proflen) +{ + int cspc_id; + pdf_obj *resource; + pdf_obj *stream; + pdf_obj *stream_dict; + iccHeader icch; + int colorspace; + unsigned char checksum[16]; + struct iccbased_cdata *cdata; + + iccp_init_iccHeader(&icch); + if (iccp_unpack_header(&icch, profile, proflen, 1) < 0) { /* check size */ + WARN("Invalid ICC profile header in \"%s\"", ident); + print_iccp_header(&icch, NULL); + return -1; + } + + if (!iccp_version_supported((icch.version >> 24) & 0xff, + (icch.version >> 16) & 0xff)) { + WARN("ICC profile format spec. version %d.%01d.%01d" + " not supported in current PDF version setting.", + (icch.version >> 24) & 0xff, + (icch.version >> 20) & 0x0f, + (icch.version >> 16) & 0x0f); + WARN("ICC profile not embedded."); + print_iccp_header(&icch, NULL); + return -1; + } + + if (!iccp_devClass_allowed(icch.devClass)) { + WARN("Unsupported ICC Profile Device Class:"); + print_iccp_header(&icch, NULL); + return -1; + } + + if (icch.colorSpace == str2iccSig("RGB ")) { + colorspace = PDF_COLORSPACE_TYPE_RGB; + } else if (icch.colorSpace == str2iccSig("GRAY")) { + colorspace = PDF_COLORSPACE_TYPE_GRAY; + } else if (icch.colorSpace == str2iccSig("CMYK")) { + colorspace = PDF_COLORSPACE_TYPE_CMYK; + } else { + WARN("Unsupported input color space."); + print_iccp_header(&icch, NULL); + return -1; + } + + iccp_get_checksum(checksum, profile, proflen); + if (memcmp(icch.ID, nullbytes16, 16) && + memcmp(icch.ID, checksum, 16)) { + WARN("Invalid ICC profile: Inconsistent checksum."); + print_iccp_header(&icch, checksum); + return -1; + } + + cdata = NEW(1, struct iccbased_cdata); + init_iccbased_cdata(cdata); + cdata->colorspace = colorspace; + memcpy(cdata->checksum, checksum, 16); + + cspc_id = pdf_colorspace_findresource(ident, + PDF_COLORSPACE_TYPE_ICCBASED, cdata); + if (cspc_id >= 0) { + if (verbose) + MESG("(ICCP:[id=%d])", cspc_id); + release_iccbased_cdata(cdata); + return cspc_id; + } + if (verbose > 1) { + print_iccp_header(&icch, checksum); + } + + resource = pdf_new_array(); + + stream = pdf_new_stream(STREAM_COMPRESS); + pdf_add_array(resource, pdf_new_name("ICCBased")); + pdf_add_array(resource, pdf_ref_obj (stream)); + + stream_dict = pdf_stream_dict(stream); + pdf_add_dict(stream_dict, pdf_new_name("N"), + pdf_new_number(get_num_components_iccbased(cdata))); + + pdf_add_stream (stream, profile, proflen); + pdf_release_obj(stream); + + cspc_id = pdf_colorspace_defineresource(ident, + PDF_COLORSPACE_TYPE_ICCBASED, + cdata, resource); + + return cspc_id; +} + +#ifdef XETEX +#define WBUF_SIZE 4096 +static unsigned char wbuf[WBUF_SIZE]; + +static pdf_obj * +iccp_load_file_stream (unsigned char *checksum, long length, FILE *fp) +{ + pdf_obj *stream; + MD5_CONTEXT md5; + long nb_read; + + rewind(fp); + + if (fread(wbuf, 1, 128, fp) != 128) { + return NULL; + } + length -= 128; + + stream = pdf_new_stream(STREAM_COMPRESS); + + MD5_init (&md5); + MD5_write(&md5, wbuf + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); + MD5_write(&md5, nullbytes16, 12); + MD5_write(&md5, wbuf + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); + MD5_write(&md5, nullbytes16, 16); + MD5_write(&md5, wbuf + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); + + pdf_add_stream(stream, wbuf, 128); + + /* body */ + while (length > 0) { + nb_read = fread(wbuf, 1, MIN(length, WBUF_SIZE), fp); + MD5_write(&md5, wbuf, nb_read); + pdf_add_stream(stream, wbuf, nb_read); + length -= nb_read; + } + + MD5_final(checksum, &md5); + + + return stream; +} + +int +pdf_colorspace_load_ICCBased (const char *ident, const char *filename) +{ + int cspc_id; + FILE *fp; + pdf_obj *resource; + pdf_obj *stream; + pdf_obj *stream_dict; + iccHeader icch; + int colorspace; + long size; + unsigned char checksum[16]; + struct iccbased_cdata *cdata; + + + fp = DPXFOPEN(filename, DPX_RES_TYPE_ICCPROFILE); + if (!fp) + return -1; + + size = file_size(fp); + if (size < 128) { + MFCLOSE(fp); + return -1; + } + if (fread(wbuf, 1, 128, fp) != 128) { + DPXFCLOSE(fp); + return -1; + } + + iccp_init_iccHeader(&icch); + if (iccp_unpack_header(&icch, wbuf, 128, 0) < 0) { + WARN("Invalid ICC profile header in \"%s\"", ident); + print_iccp_header(&icch, NULL); + DPXFCLOSE(fp); + return -1; + } + if (icch.size > size) { + WARN("File size smaller than recorded in header: %ld %ld", + icch.size, size); + DPXFCLOSE(fp); + return -1; + } + + if (!iccp_version_supported((icch.version >> 24) & 0xff, + (icch.version >> 16) & 0xff)) { + WARN("ICC profile format spec. version %d.%01d.%01d" + " not supported in current PDF version setting.", + (icch.version >> 24) & 0xff, + (icch.version >> 20) & 0x0f, + (icch.version >> 16) & 0x0f); + WARN("ICC profile not embedded."); + print_iccp_header(&icch, NULL); + DPXFCLOSE(fp); + return -1; + } + + if (!iccp_devClass_allowed(icch.devClass)) { + WARN("Unsupported ICC Profile Device Class:"); + print_iccp_header(&icch, NULL); + DPXFCLOSE(fp); + return -1; + } + + if (icch.colorSpace == str2iccSig("RGB ")) { + colorspace = PDF_COLORSPACE_TYPE_RGB; + } else if (icch.colorSpace == str2iccSig("GRAY")) { + colorspace = PDF_COLORSPACE_TYPE_GRAY; + } else if (icch.colorSpace == str2iccSig("CMYK")) { + colorspace = PDF_COLORSPACE_TYPE_CMYK; + } else { + WARN("Unsupported input color space."); + print_iccp_header(&icch, NULL); + DPXFCLOSE(fp); + return -1; + } + + stream = iccp_load_file_stream(checksum, icch.size, fp); + DPXFCLOSE(fp); + + if (!stream) { + WARN("Loading ICC Profile failed...: %s", filename); + return -1; + } + + if (memcmp(icch.ID, nullbytes16, 16) && + memcmp(icch.ID, checksum, 16)) { + WARN("Invalid ICC profile: Inconsistent checksum."); + print_iccp_header(&icch, NULL); + pdf_release_obj(stream); + return -1; + } + + cdata = NEW(1, struct iccbased_cdata); + init_iccbased_cdata(cdata); + cdata->colorspace = colorspace; + memcpy(cdata->checksum, checksum, 16); + + cspc_id = pdf_colorspace_findresource(ident, + PDF_COLORSPACE_TYPE_ICCBASED, cdata); + if (cspc_id >= 0) { + if (verbose) + MESG("(ICCP:[id=%d])", cspc_id); + release_iccbased_cdata(cdata); + pdf_release_obj(stream); + return cspc_id; + } + if (verbose > 1) { + print_iccp_header(&icch, checksum); + } + + resource = pdf_new_array(); + + pdf_add_array(resource, pdf_new_name("ICCBased")); + pdf_add_array(resource, pdf_ref_obj (stream)); + + stream_dict = pdf_stream_dict(stream); + pdf_add_dict(stream_dict, pdf_new_name("N"), + pdf_new_number(get_num_components_iccbased(cdata))); + pdf_release_obj(stream); + + cspc_id = pdf_colorspace_defineresource(ident, + PDF_COLORSPACE_TYPE_ICCBASED, + cdata, resource); + + return cspc_id; +} +#endif + +typedef struct { + char *ident; + int subtype; + + pdf_obj *resource; + pdf_obj *reference; + + void *cdata; +} pdf_colorspace; + +static struct { + int count; + int capacity; + pdf_colorspace *colorspaces; +} cspc_cache = { + 0, 0, NULL +}; + +int +pdf_colorspace_findresource (const char *ident, + int type, const void *cdata) +{ + pdf_colorspace *colorspace; + int cspc_id, cmp = -1; + + for (cspc_id = 0; + cmp && cspc_id < cspc_cache.count; cspc_id++) { + colorspace = &cspc_cache.colorspaces[cspc_id]; + if (colorspace->subtype != type) + continue; + + switch (colorspace->subtype) { + case PDF_COLORSPACE_TYPE_ICCBASED: + cmp = compare_iccbased(ident, cdata, + colorspace->ident, colorspace->cdata); + break; + } + if (!cmp) + return cspc_id; + } + + return -1; /* not found */ +} + +static void +pdf_init_colorspace_struct (pdf_colorspace *colorspace) +{ + ASSERT(colorspace); + + colorspace->ident = NULL; + colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; + + colorspace->resource = NULL; + colorspace->reference = NULL; + colorspace->cdata = NULL; + + return; +} + +static void +pdf_clean_colorspace_struct (pdf_colorspace *colorspace) +{ + ASSERT(colorspace); + + if (colorspace->ident) + RELEASE(colorspace->ident); + if (colorspace->resource) + pdf_release_obj(colorspace->resource); + if (colorspace->reference) + pdf_release_obj(colorspace->reference); + colorspace->resource = NULL; + colorspace->reference = NULL; + + if (colorspace->cdata) { + switch (colorspace->subtype) { + case PDF_COLORSPACE_TYPE_ICCBASED: + release_iccbased_cdata(colorspace->cdata); + break; + } + } + colorspace->cdata = NULL; + colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; + + return; +} + +static void +pdf_flush_colorspace (pdf_colorspace *colorspace) +{ + ASSERT(colorspace); + + if (colorspace->resource) + pdf_release_obj(colorspace->resource); + if (colorspace->reference) + pdf_release_obj(colorspace->reference); + + colorspace->resource = NULL; + colorspace->reference = NULL; +} + +int +pdf_colorspace_defineresource (const char *ident, + int subtype, void *cdata, pdf_obj *resource) +{ + int cspc_id; + pdf_colorspace *colorspace; + + if (cspc_cache.count >= cspc_cache.capacity) { + cspc_cache.capacity += 16; + cspc_cache.colorspaces = RENEW(cspc_cache.colorspaces, + cspc_cache.capacity, pdf_colorspace); + } + cspc_id = cspc_cache.count; + colorspace = &cspc_cache.colorspaces[cspc_id]; + + pdf_init_colorspace_struct(colorspace); + if (ident) { + colorspace->ident = NEW(strlen(ident) + 1, char); + strcpy(colorspace->ident, ident); + } + colorspace->subtype = subtype; + colorspace->cdata = cdata; + colorspace->resource = resource; + + if (verbose) { + MESG("(ColorSpace:%s", ident); + if (verbose > 1) { + switch (subtype) { + case PDF_COLORSPACE_TYPE_ICCBASED: + MESG("[ICCBased]"); + break; + case PDF_COLORSPACE_TYPE_CALRGB: + MESG("[CalRGB]"); + break; + case PDF_COLORSPACE_TYPE_CALGRAY: + MESG("[CalGray]"); + break; + } + } + MESG(")"); + } + + cspc_cache.count++; + + return cspc_id; +} + +pdf_obj * +pdf_get_colorspace_reference (int cspc_id) +{ + pdf_colorspace *colorspace; + + colorspace = &cspc_cache.colorspaces[cspc_id]; + if (!colorspace->reference) { + colorspace->reference = pdf_ref_obj(colorspace->resource); + pdf_release_obj(colorspace->resource); /* .... */ + colorspace->resource = NULL; + } + + return pdf_link_obj(colorspace->reference); +} + +#if 0 +int +pdf_get_colorspace_num_components (int cspc_id) +{ + pdf_colorspace *colorspace; + int num_components; + + colorspace = &cspc_cache.colorspaces[cspc_id]; + + switch (colorspace->subtype) { + case PDF_COLORSPACE_TYPE_ICCBASED: + num_components = get_num_components_iccbased(colorspace->cdata); + break; + case PDF_COLORSPACE_TYPE_DEVICEGRAY: + num_components = 1; + break; + case PDF_COLORSPACE_TYPE_DEVICERGB: + num_components = 3; + break; + case PDF_COLORSPACE_TYPE_DEVICECMYK: + num_components = 4; + break; + case PDF_COLORSPACE_TYPE_CALRGB: + num_components = 3; + break; + case PDF_COLORSPACE_TYPE_CALGRAY: + num_components = 1; + break; + default: + num_components = 0; + break; + } + + return num_components; +} + +int +pdf_get_colorspace_subtype (int cspc_id) +{ + pdf_colorspace *colorspace; + + colorspace = &cspc_cache.colorspaces[cspc_id]; + + return colorspace->subtype; +} +#endif + +void +pdf_init_colors (void) +{ + cspc_cache.count = 0; + cspc_cache.capacity = 0; + cspc_cache.colorspaces = NULL; +} + +void +pdf_close_colors (void) +{ + int i; + + for (i = 0; i < cspc_cache.count; i++) { + pdf_colorspace *colorspace; + + colorspace = &cspc_cache.colorspaces[i]; + pdf_flush_colorspace(colorspace); + pdf_clean_colorspace_struct(colorspace); + } + RELEASE(cspc_cache.colorspaces); + cspc_cache.colorspaces = NULL; + cspc_cache.count = cspc_cache.capacity = 0; + +} + +#define PDF_COLORSPACE_FAMILY_DEVICE 0 +#define PDF_COLORSPACE_FAMILY_CIEBASED 1 +#define PDF_COLORSPACE_FAMILY_SPECIAL 2 diff --git a/Build/source/texk/dvipdfm-x/pdfcolor.h b/Build/source/texk/dvipdfm-x/pdfcolor.h index a58a049ae1a..71c0afbfe1c 100644 --- a/Build/source/texk/dvipdfm-x/pdfcolor.h +++ b/Build/source/texk/dvipdfm-x/pdfcolor.h @@ -58,17 +58,14 @@ extern int pdf_color_cmykcolor (pdf_color *color, extern int pdf_color_graycolor (pdf_color *color, double g); extern void pdf_color_copycolor (pdf_color *color1, const pdf_color *color2); -#ifndef XETEX #define pdf_color_black(c) pdf_color_graycolor(c, 0.0); #define pdf_color_white(c) pdf_color_graycolor(c, 1.0); -extern int pdf_color_type (const pdf_color *color); extern void pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f); +extern int pdf_color_type (const pdf_color *color); extern int pdf_color_compare (const pdf_color *color1, const pdf_color *color2); - extern int pdf_color_to_string (const pdf_color *color, char *buffer); -#endif extern int pdf_color_is_white (const pdf_color *color); extern int pdf_color_is_valid (const pdf_color *color); @@ -91,18 +88,14 @@ extern int pdf_get_colorspace_num_components (int cspc_id); extern int pdf_get_colorspace_subtype (int cspc_id); #endif -#ifdef XETEX /* Not working */ extern int pdf_colorspace_load_ICCBased (const char *ident, const char *profile_filename); -#endif /* Color special * See remark in spc_color.c. */ -#ifndef XETEX extern void pdf_color_set (pdf_color *sc, pdf_color *fc); -#endif extern void pdf_color_set_default (const pdf_color *color); extern void pdf_color_push (pdf_color *sc, pdf_color *fc); extern void pdf_color_pop (void); @@ -112,7 +105,7 @@ extern void pdf_color_pop (void); extern void pdf_color_clear_stack (void); extern void pdf_color_get_current (pdf_color **sc, pdf_color **fc); -#ifdef XETEX +#if 0 /* Reinstall color */ extern void pdf_dev_preserve_color(void); #endif diff --git a/Build/source/texk/dvipdfm-x/pdfdev.c b/Build/source/texk/dvipdfm-x/pdfdev.c new file mode 100644 index 00000000000..11d55a4cf73 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfdev.c @@ -0,0 +1,1963 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "system.h" +#include "mem.h" +#include "error.h" + +#include "mfileio.h" +#include "numbers.h" + +#include "pdfdoc.h" +#include "pdfobj.h" + +#include "pdffont.h" +#include "fontmap.h" +#include "cmap.h" +#include "pdfximage.h" + +#include "pdfdraw.h" +#include "pdfcolor.h" + +#include "pdflimits.h" + +#include "dvi.h" + +#include "pdfdev.h" + +static int verbose = 0; + +void +pdf_dev_set_verbose (void) +{ + verbose++; +} + +/* Not working yet... */ +double +pdf_dev_scale (void) +{ + return 1.0; +} + +/* + * Unit conversion, formatting and others. + */ + +#define TEX_ONE_HUNDRED_BP 6578176 +static struct { + double dvi2pts; + long min_bp_val; /* Shortest resolvable distance in the output PDF. */ + int precision; /* Number of decimal digits (in fractional part) kept. */ +} dev_unit = { + 0.0, + 658, + 2 +}; + + +double +dev_unit_dviunit (void) +{ + return (1.0/dev_unit.dvi2pts); +} + +#define DEV_PRECISION_MAX 8 +static unsigned long ten_pow[10] = { + 1ul, 10ul, 100ul, 1000ul, 10000ul, 100000ul, 1000000ul, 10000000ul, 100000000ul, 1000000000ul +}; + +static double ten_pow_inv[10] = { + 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001 +}; + +#define bpt2spt(b) ( (spt_t) round( (b) / dev_unit.dvi2pts ) ) +#define spt2bpt(s) ( (s) * dev_unit.dvi2pts ) +#define dround_at(v,p) (ROUND( (v), ten_pow_inv[(p)] )) + +static int +p_itoa (long value, char *buf) +{ + int sign, ndigits; + char *p = buf; + + if (value < 0) { + *p++ = '-'; + value = -value; + sign = 1; + } else { + sign = 0; + } + + ndigits = 0; + /* Generate at least one digit in reverse order */ + do { + p[ndigits++] = (value % 10) + '0'; + value /= 10; + } while (value != 0); + + /* Reverse the digits */ + { + int i; + + for (i = 0; i < ndigits / 2 ; i++) { + char tmp = p[i]; + p[i] = p[ndigits-i-1]; + p[ndigits-i-1] = tmp; + } + } + p[ndigits] = '\0'; + + return (sign ? ndigits + 1 : ndigits); +} + +/* ... */ +static int +p_dtoa (double value, int prec, char *buf) +{ + const long p[10] = { 1, 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000, 1000000000 }; + long i, f; + char *c = buf; + int n; + + if (value < 0) { + value = -value; + *c++ = '-'; + n = 1; + } else + n = 0; + + i = (long) value; + f = (long) ((value-i)*p[prec] + 0.5); + + if (f == p[prec]) { + f = 0; + i++; + } + + if (i) { + int m = p_itoa(i, c); + c += m; + n += m; + } else if (!f) { + *(c = buf) = '0'; + n = 1; + } + + if (f) { + int j = prec; + + *c++ = '.'; + + while (j--) { + c[j] = (f % 10) + '0'; + f /= 10; + } + c += prec-1; + n += 1+prec; + + while (*c == '0') { + c--; + n--; + } + } + + *(++c) = 0; + + return n; +} + +static int +dev_sprint_bp (char *buf, spt_t value, spt_t *error) +{ + double value_in_bp; + double error_in_bp; + int prec = dev_unit.precision; + + value_in_bp = spt2bpt(value); + if (error) { + error_in_bp = value_in_bp - dround_at(value_in_bp, prec); + *error = bpt2spt(error_in_bp); + } + + return p_dtoa(value_in_bp, prec, buf); +} + +/* They are affected by precision (set at device initialization). */ +int +pdf_sprint_matrix (char *buf, const pdf_tmatrix *M) +{ + int len; + int prec2 = MIN(dev_unit.precision + 2, DEV_PRECISION_MAX); + int prec0 = MAX(dev_unit.precision, 2); + + len = p_dtoa(M->a, prec2, buf); + buf[len++] = ' '; + len += p_dtoa(M->b, prec2, buf+len); + buf[len++] = ' '; + len += p_dtoa(M->c, prec2, buf+len); + buf[len++] = ' '; + len += p_dtoa(M->d, prec2, buf+len); + buf[len++] = ' '; + len += p_dtoa(M->e, prec0, buf+len); + buf[len++] = ' '; + len += p_dtoa(M->f, prec0, buf+len); + buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ + + return len; +} + +int +pdf_sprint_rect (char *buf, const pdf_rect *rect) +{ + int len; + + len = p_dtoa(rect->llx, dev_unit.precision, buf); + buf[len++] = ' '; + len += p_dtoa(rect->lly, dev_unit.precision, buf+len); + buf[len++] = ' '; + len += p_dtoa(rect->urx, dev_unit.precision, buf+len); + buf[len++] = ' '; + len += p_dtoa(rect->ury, dev_unit.precision, buf+len); + buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ + + return len; +} + +int +pdf_sprint_coord (char *buf, const pdf_coord *p) +{ + int len; + + len = p_dtoa(p->x, dev_unit.precision, buf); + buf[len++] = ' '; + len += p_dtoa(p->y, dev_unit.precision, buf+len); + buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ + + return len; +} + +int +pdf_sprint_length (char *buf, double value) +{ + int len; + + len = p_dtoa(value, dev_unit.precision, buf); + buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ + + return len; +} + + +int +pdf_sprint_number (char *buf, double value) +{ + int len; + + len = p_dtoa(value, DEV_PRECISION_MAX, buf); + buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ + + return len; +} + + +static struct +{ + /* Text composition (direction) mode is ignored (always same + * as font's writing mode) if autorotate is unset (value zero). + */ + int autorotate; + + /* + * Ignore color migrated to here. This is device's capacity. + * colormode 0 for ignore colors + */ + int colormode; + +} dev_param = { + 1, /* autorotate */ + 1, /* colormode */ +}; + +/* + * Text handling routines. + */ + +/* Motion state: + * GRAPHICS_MODE Initial state (not within BT/ET block nor in string) + * TEXT_MODE Text section is started via BT operator but not + * in string. + * STRING_MODE In string. A string or array of strings are currently + * in process. May started '[', '<' or '('. + */ +#define GRAPHICS_MODE 1 +#define TEXT_MODE 2 +#define STRING_MODE 3 + +static int motion_state = GRAPHICS_MODE; + +#define FORMAT_BUF_SIZE 4096 +static char format_buffer[FORMAT_BUF_SIZE]; + +/* + * In PDF, vertical text positioning is always applied when current font + * is vertical font. While ASCII pTeX manages current writing direction + * and font's WMode separately. + * + * 000/101 WMODE_HH/VV h(v) font, h(v) direction. + * 001 WMODE_HV -90 deg. rotated + * 100 WMODE_VH +90 deg. rotated + * 011 WMODE_HD +90 deg. rotated + * 111 WMODE_VD 180 deg. rotated + + * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode + * is applied. + */ +#define TEXT_WMODE_HH 0 +#define TEXT_WMODE_HV 1 +#define TEXT_WMODE_VH 4 +#define TEXT_WMODE_VV 5 +#define TEXT_WMODE_HD 3 +#define TEXT_WMODE_VD 7 + +#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1) +#define ROTATE_TEXT(m) ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV) + +static struct { + + /* Current font. + * This is index within dev_fonts. + */ + int font_id; + + /* Dvipdfmx does compression of text by doing text positioning + * in relative motion and uses string array [(foo) -250 (bar)] + * with kerning (negative kern is used for white space as suited + * for TeX). This is offset within current string. + */ + spt_t offset; + + /* This is reference point of strings. + * It may include error correction induced by rounding. + */ + spt_t ref_x; + spt_t ref_y; + + /* Using text raise and leading is highly recommended for + * text extraction to work properly. But not implemented yet. + * We can't do consice output for \TeX without this. + */ + spt_t raise; /* unused */ + spt_t leading; /* unused */ + + /* This is not always text matrix but rather font matrix. + * We do not use horizontal scaling in PDF text state parameter + * since they always apply scaling in fixed direction regardless + * of writing mode. + */ + struct { + double slant; + double extend; + int rotate; /* TEXT_WMODE_XX */ + } matrix; + + /* Fake bold parameter: + * If bold_param is positive, use text rendering mode + * fill-then-stroke with stroking line width specified + * by bold_param. + */ + double bold_param; + + /* Text composition (direction) mode. */ + int dir_mode; + + /* internal */ + + /* Flag indicating text matrix to be forcibly reset. + * Enabled if synthetic font features (slant, extend, etc) + * are used for current font or when text rotation mode + * changes. + */ + int force_reset; + + /* This information is duplicated from dev[font_id].format. + * Set to 1 if font is composite (Type0) font. + */ + int is_mb; +} text_state = { + -1, /* font */ + 0, /* offset */ + 0, 0, /* ref_x, ref_y */ + 0, 0, /* raise, leading */ + {0.0, 1.0, 0}, + + 0.0, /* Experimental boldness param */ + + 0, /* dir_mode */ + + /* internal */ + 0, /* force_reset */ + 0 /* is_mb */ +}; + +#define PDF_FONTTYPE_SIMPLE 1 +#define PDF_FONTTYPE_BITMAP 2 +#define PDF_FONTTYPE_COMPOSITE 3 + +struct dev_font { + /* Needs to be big enough to hold name "Fxxx" + * where xxx is number of largest font + */ + char short_name[7]; /* Resource name */ + int used_on_this_page; + + char *tex_name; /* String identifier of this font */ + spt_t sptsize; /* Point size */ + + /* Returned values from font/encoding layer: + * + * The font_id and enc_id is font and encoding (CMap) identifier + * used in pdf_font or encoding/cmap layer. + * The PDF object "resource" is an indirect reference object + * pointing font resource of this font. The used_chars is somewhat + * misleading, this is actually used_glyphs in CIDFont for Type0 + * and is 65536/8 bytes binary data with each bits representing + * whether the glyph is in-use or not. It is 256 char array for + * simple font. + */ + int font_id; + int enc_id; +#ifdef XETEX + unsigned short *ft_to_gid; +#endif + + /* if >= 0, index of a dev_font that really has the resource and used_chars */ + int real_font_index; + + pdf_obj *resource; + char *used_chars; + + /* Font format: + * simple, composite or bitmap. + */ + int format; + + /* Writing mode: + * Non-zero for vertical. Duplicated from CMap. + */ + int wmode; + + /* Syntetic Font: + * + * We use text matrix for creating extended or slanted font, + * but not with font's FontMatrix since TrueType and Type0 + * font don't support them. + */ + double extend; + double slant; + double bold; /* Boldness prameter */ + + /* Compatibility */ + int mapc; /* Nasty workaround for Omega */ + + /* There are no font metric format supporting four-bytes + * charcter code. So we should provide an option to specify + * UCS group and plane. + */ + int ucs_group; + int ucs_plane; + + int is_unicode; +}; +static struct dev_font *dev_fonts = NULL; + +static int num_dev_fonts = 0; +static int max_dev_fonts = 0; +static int num_phys_fonts = 0; + +#define CURRENTFONT() ((text_state.font_id < 0) ? NULL : &(dev_fonts[text_state.font_id])) +#define GET_FONT(n) (&(dev_fonts[(n)])) + + +static void +dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +{ + pdf_tmatrix tm; + int len = 0; + + /* slant is negated for vertical font so that right-side + * is always lower. */ + switch (rotate) { + case TEXT_WMODE_VH: + /* Vertical font */ + tm.a = slant ; tm.b = 1.0; + tm.c = -extend; tm.d = 0.0 ; + break; + case TEXT_WMODE_HV: + /* Horizontal font */ + tm.a = 0.0; tm.b = -extend; + tm.c = 1.0; tm.d = -slant ; + break; + case TEXT_WMODE_HH: + /* Horizontal font */ + tm.a = extend; tm.b = 0.0; + tm.c = slant ; tm.d = 1.0; + break; + case TEXT_WMODE_VV: + /* Vertical font */ + tm.a = 1.0; tm.b = -slant; + tm.c = 0.0; tm.d = extend; + break; + case TEXT_WMODE_HD: + /* Horizontal font */ + tm.a = 0.0; tm.b = extend; + tm.c = -1.0; tm.d = slant ; + break; + case TEXT_WMODE_VD: + /* Vertical font */ + tm.a = -1.0; tm.b = slant; + tm.c = 0.0; tm.d = -extend; + break; + } + tm.e = xpos * dev_unit.dvi2pts; + tm.f = ypos * dev_unit.dvi2pts; + + format_buffer[len++] = ' '; + len += pdf_sprint_matrix(format_buffer+len, &tm); + format_buffer[len++] = ' '; + format_buffer[len++] = 'T'; + format_buffer[len++] = 'm'; + + pdf_doc_add_page_content(format_buffer, len); /* op: Tm */ + + text_state.ref_x = xpos; + text_state.ref_y = ypos; + text_state.matrix.slant = slant; + text_state.matrix.extend = extend; + text_state.matrix.rotate = rotate; +} + +/* + * reset_text_state() outputs a BT and does any necessary coordinate + * transformations to get ready to ship out text. + */ + +static void +reset_text_state (void) +{ + /* + * We need to reset the line matrix to handle slanted fonts. + */ + pdf_doc_add_page_content(" BT", 3); /* op: BT */ + /* + * text_state.matrix is identity at top of page. + * This sometimes write unnecessary "Tm"s when transition from + * GRAPHICS_MODE to TEXT_MODE occurs. + */ + if (text_state.force_reset || + text_state.matrix.slant != 0.0 || + text_state.matrix.extend != 1.0 || + ROTATE_TEXT(text_state.matrix.rotate)) { + dev_set_text_matrix(0, 0, + text_state.matrix.slant, + text_state.matrix.extend, + text_state.matrix.rotate); + } + text_state.ref_x = 0; + text_state.ref_y = 0; + text_state.offset = 0; + text_state.force_reset = 0; +} + +static void +text_mode (void) +{ + switch (motion_state) { + case TEXT_MODE: + break; + case STRING_MODE: + pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ + break; + case GRAPHICS_MODE: + reset_text_state(); + break; + } + motion_state = TEXT_MODE; + text_state.offset = 0; +} + +void +graphics_mode (void) +{ + switch (motion_state) { + case GRAPHICS_MODE: + break; + case STRING_MODE: + pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ + /* continue */ + case TEXT_MODE: + pdf_doc_add_page_content(" ET", 3); /* op: ET */ + text_state.force_reset = 0; + text_state.font_id = -1; + break; + } + motion_state = GRAPHICS_MODE; +} + +static void +start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +{ + spt_t delx, dely, error_delx, error_dely; + spt_t desired_delx, desired_dely; + int len = 0; + + delx = xpos - text_state.ref_x; + dely = ypos - text_state.ref_y; + /* + * Precompensating for line transformation matrix. + * + * Line transformation matrix L for horizontal font in horizontal + * mode and it's inverse I is + * + * | e 0| | 1/e 0| + * L_hh = | | , I_hh = | | + * | s 1| |-s/e 1| + * + * For vertical font in vertical mode, + * + * | 1 -s| | 1 s/e| + * L_vv = | | , I_vv = | | + * | 0 e| | 0 1/e| + * + * For vertical font in horizontal mode, + * + * | s 1| | 0 1| + * L_vh = | | = L_vv x | | + * |-e 0| |-1 0| + * + * | 0 -1| + * I_vh = | | x I_vv + * | 1 0| + * + * For horizontal font in vertical mode, + * + * | 0 -e| | 0 -1| + * L_hv = | | = L_hh x | | + * | 1 -s| | 1 0| + * + * | 0 1| + * I_hv = | | x I_hh + * |-1 0| + * + */ + switch (rotate) { + case TEXT_WMODE_VH: + /* Vertical font in horizontal mode: rot = +90 + * | 0 -1/e| + * d_user = d x I_vh = d x | | + * | 1 s/e| + */ + desired_delx = dely; + desired_dely = (spt_t) (-(delx - dely*slant)/extend); + + /* error_del is in device space + * + * | 0 1| + * e = e_user x | | = (-e_user_y, e_user_x) + * |-1 0| + * + * We must care about rotation here but not extend/slant... + * The extend and slant actually is font matrix. + */ + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); + error_delx = -error_delx; + break; + case TEXT_WMODE_HV: + /* Horizontal font in vertical mode: rot = -90 + * + * |-s/e 1| + * d_user = d x I_hv = d x | | + * |-1/e 0| + */ + desired_delx = (spt_t)(-(dely + delx*slant)/extend); + desired_dely = delx; + + /* + * e = (e_user_y, -e_user_x) + */ + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); + error_dely = -error_dely; + break; + case TEXT_WMODE_HH: + /* Horizontal font in horizontal mode: + * | 1/e 0| + * d_user = d x I_hh = d x | | + * |-s/e 1| + */ + desired_delx = (spt_t)((delx - dely*slant)/extend); + desired_dely = dely; + + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); + break; + case TEXT_WMODE_VV: + /* Vertical font in vertical mode: + * | 1 s/e| + * d_user = d x I_vv = d x | | + * | 0 1/e| + */ + desired_delx = delx; + desired_dely = (spt_t)((dely + delx*slant)/extend); + + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); + break; + case TEXT_WMODE_HD: + /* Horizontal font in down-to-up mode: rot = +90 + * + * | s/e -1| + * d_user = d x -I_hv = d x | | + * | 1/e 0| + */ + desired_delx = -(spt_t)(-(dely + delx*slant)/extend); + desired_dely = -delx; + + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); + error_delx = -error_delx; + error_dely = -error_dely; + break; + case TEXT_WMODE_VD: + /* Vertical font in down-to-up mode: rot = 180 + * |-1 -s/e| + * d_user = d x -I_vv = d x | | + * | 0 -1/e| + */ + desired_delx = -delx; + desired_dely = -(spt_t)((dely + delx*slant)/extend); + + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); + format_buffer[len++] = ' '; + len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); + error_delx = -error_delx; + error_dely = -error_dely; + break; + } + pdf_doc_add_page_content(format_buffer, len); /* op: */ + /* + * dvipdfm wrongly using "TD" in place of "Td". + * The TD operator set leading, but we are not using T* etc. + */ + pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ + + /* Error correction */ + text_state.ref_x = xpos - error_delx; + text_state.ref_y = ypos - error_dely; + + text_state.offset = 0; +} + +static void +string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) +{ + switch (motion_state) { + case STRING_MODE: + break; + case GRAPHICS_MODE: + reset_text_state(); + /* continue */ + case TEXT_MODE: + if (text_state.force_reset) { + dev_set_text_matrix(xpos, ypos, slant, extend, rotate); + pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2); /* op: */ + text_state.force_reset = 0; + } else { + start_string(xpos, ypos, slant, extend, rotate); + } + break; + } + motion_state = STRING_MODE; +} + +/* + * The purpose of the following routine is to force a Tf only + * when it's actually necessary. This became a problem when the + * VF code was added. The VF spec says to instantiate the + * first font contained in the VF file before drawing a virtual + * character. However, that font may not be used for + * many characters (e.g. small caps fonts). For this reason, + * dev_select_font() should not force a "physical" font selection. + * This routine prevents a PDF Tf font selection until there's + * really a character in that font. + */ + +static int +dev_set_font (int font_id) +{ + struct dev_font *font; + struct dev_font *real_font; + int text_rotate; + double font_scale; + int len; + int vert_dir, vert_font; + + /* text_mode() must come before text_state.is_mb is changed. */ + text_mode(); + + font = GET_FONT(font_id); + ASSERT(font); /* Caller should check font_id. */ + + if (font->real_font_index >= 0) + real_font = GET_FONT(font->real_font_index); + else + real_font = font; + + text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; + + vert_font = font->wmode ? 1 : 0; + if (dev_param.autorotate) { + vert_dir = text_state.dir_mode; + } else { + vert_dir = vert_font; + } + text_rotate = (vert_font << 2)|vert_dir; + + if (font->slant != text_state.matrix.slant || + font->extend != text_state.matrix.extend || + ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { + text_state.force_reset = 1; + } + text_state.matrix.slant = font->slant; + text_state.matrix.extend = font->extend; + text_state.matrix.rotate = text_rotate; + + if (!real_font->resource) { + real_font->resource = pdf_get_font_reference(real_font->font_id); + real_font->used_chars = pdf_get_font_usedchars(real_font->font_id); + } + + if (!real_font->used_on_this_page) { + pdf_doc_add_page_resource("Font", + real_font->short_name, + pdf_link_obj(real_font->resource)); + real_font->used_on_this_page = 1; + } + + font_scale = (double) font->sptsize * dev_unit.dvi2pts; + len = sprintf(format_buffer, " /%s", real_font->short_name); /* space not necessary. */ + format_buffer[len++] = ' '; + len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len); + format_buffer[len++] = ' '; + format_buffer[len++] = 'T'; + format_buffer[len++] = 'f'; + pdf_doc_add_page_content(format_buffer, len); /* op: Tf */ + + if (font->bold > 0.0 || font->bold != text_state.bold_param) { + if (font->bold <= 0.0) + len = sprintf(format_buffer, " 0 Tr"); + else + len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ + pdf_doc_add_page_content(format_buffer, len); /* op: Tr w */ + } + text_state.bold_param = font->bold; + + text_state.font_id = font_id; + + return 0; +} + + +/* Access text state parameters. + */ +#if 0 +int +pdf_dev_currentfont (void) +{ + return text_state.font_id; +} + +double +pdf_dev_get_font_ptsize (int font_id) +{ + struct dev_font *font; + + font = GET_FONT(font_id); + if (font) { + return font->sptsize * dev_unit.dvi2pts; + } + + return 1.0; +} +#endif + +int +pdf_dev_get_font_wmode (int font_id) +{ + struct dev_font *font; + + font = GET_FONT(font_id); + if (font) { + return font->wmode; + } + + return 0; +} + +static unsigned char sbuf0[FORMAT_BUF_SIZE]; +static unsigned char sbuf1[FORMAT_BUF_SIZE]; + +static int +handle_multibyte_string (struct dev_font *font, + const unsigned char **str_ptr, int *str_len, int ctype) +{ + const unsigned char *p; + int i, length; + + p = *str_ptr; + length = *str_len; + +#ifdef XETEX + if (ctype == -1) { /* freetype glyph indexes */ + if (font->ft_to_gid) { + /* convert freetype glyph indexes to physical GID */ + const unsigned char *inbuf = p; + unsigned char *outbuf = sbuf0; + for (i = 0; i < length; i += 2) { + unsigned int gid; + gid = *inbuf++ << 8; + gid += *inbuf++; + gid = font->ft_to_gid[gid]; + *outbuf++ = gid >> 8; + *outbuf++ = gid & 0xff; + } + p = sbuf0; + length = outbuf - sbuf0; + } + } + else +#endif + /* _FIXME_ */ + if (font->is_unicode) { /* UCS-4 */ + if (ctype == 1) { + if (length * 4 >= FORMAT_BUF_SIZE) { + WARN("Too long string..."); + return -1; + } + for (i = 0; i < length; i++) { + sbuf1[i*4 ] = font->ucs_group; + sbuf1[i*4+1] = font->ucs_plane; + sbuf1[i*4+2] = '\0'; + sbuf1[i*4+3] = p[i]; + } + length *= 4; + } else if (ctype == 2) { + int len = 0; + + if (length * 2 >= FORMAT_BUF_SIZE) { + WARN("Too long string..."); + return -1; + } + for (i = 0; i < length; i += 2, len += 4) { + sbuf1[len ] = font->ucs_group; + if ((p[i] & 0xf8) == 0xd8) { + int c; + /* Check for valid surrogate pair. */ + if ((p[i] & 0xfc) != 0xd8 || i + 2 >= length || (p[i+2] & 0xfc) != 0xdc) { + WARN("Invalid surrogate p[%d]=%02X...", i, p[i]); + return -1; + } + c = (((p[i] & 0x03) << 10) | (p[i+1] << 2) | (p[i+2] & 0x03)) + 0x100; + sbuf1[len+1] = (c >> 8) & 0xff; + sbuf1[len+2] = c & 0xff; + i += 2; + } else { + sbuf1[len+1] = font->ucs_plane; + sbuf1[len+2] = p[i]; + } + sbuf1[len+3] = p[i+1]; + } + length = len; + } + p = sbuf1; + } else if (ctype == 1 && font->mapc >= 0) { + /* Omega workaround... + * Translate single-byte chars to double byte code space. + */ + if (length * 2 >= FORMAT_BUF_SIZE) { + WARN("Too long string..."); + return -1; + } + for (i = 0; i < length; i++) { + sbuf1[i*2 ] = (font->mapc & 0xff); + sbuf1[i*2+1] = p[i]; + } + length *= 2; + p = sbuf1; + } + + /* + * Font is double-byte font. Output is assumed to be 16-bit fixed length + * encoding. + * TODO: A character decomposed to multiple characters. + */ +#ifdef XETEX + if (ctype != -1 && font->enc_id >= 0) { +#else + if (font->enc_id >= 0) { +#endif + const unsigned char *inbuf; + unsigned char *outbuf; + long inbytesleft, outbytesleft; + CMap *cmap; + + cmap = CMap_cache_get(font->enc_id); + inbuf = p; + outbuf = sbuf0; + inbytesleft = length; + outbytesleft = FORMAT_BUF_SIZE; + + CMap_decode(cmap, + &inbuf, &inbytesleft, &outbuf, &outbytesleft); + if (inbytesleft != 0) { + WARN("CMap conversion failed. (%d bytes remains)", inbytesleft); + return -1; + } + length = FORMAT_BUF_SIZE - outbytesleft; + p = sbuf0; + } + + *str_ptr = p; + *str_len = length; + return 0; +} + + +static pdf_coord *dev_coords = NULL; +static int num_dev_coords = 0; +static int max_dev_coords = 0; + +void pdf_dev_get_coord(double *xpos, double *ypos) +{ + if (num_dev_coords > 0) { + *xpos = dev_coords[num_dev_coords-1].x; + *ypos = dev_coords[num_dev_coords-1].y; + } else { + *xpos = *ypos = 0.0; + } +} + +void pdf_dev_push_coord(double xpos, double ypos) +{ + if (num_dev_coords >= max_dev_coords) { + max_dev_coords += 4; + dev_coords = RENEW(dev_coords, max_dev_coords, pdf_coord); + } + dev_coords[num_dev_coords].x = xpos; + dev_coords[num_dev_coords].y = ypos; + num_dev_coords++; +} + +void pdf_dev_pop_coord(void) +{ + if (num_dev_coords > 0) num_dev_coords--; +} + +/* + * ctype: +#ifdef XETEX + * -1 input string contains 2-byte Freetype glyph index values +#endif + * 0 byte-width of char can be variable and input string + * is properly encoded. + * n Single character cosumes n bytes in input string. + * + * _FIXME_ + * --> + * selectfont(font_name, point_size) and show_string(pos, string) + */ +void +pdf_dev_set_string (spt_t xpos, spt_t ypos, + const void *instr_ptr, int instr_len, + spt_t width, + int font_id, int ctype) +{ + struct dev_font *font; + struct dev_font *real_font; + const unsigned char *str_ptr; /* Pointer to the reencoded string. */ + int length, i, len = 0; + spt_t kern, delh, delv; + spt_t text_xorigin; + spt_t text_yorigin; + + if (font_id < 0 || font_id >= num_dev_fonts) { + ERROR("Invalid font: %d (%d)", font_id, num_dev_fonts); + return; + } + if (font_id != text_state.font_id) { + dev_set_font(font_id); + } + + font = CURRENTFONT(); + if (!font) { + ERROR("Currentfont not set."); + return; + } + + if (font->real_font_index >= 0) + real_font = GET_FONT(font->real_font_index); + else + real_font = font; + + text_xorigin = text_state.ref_x; + text_yorigin = text_state.ref_y; + + str_ptr = instr_ptr; + length = instr_len; + + if (font->format == PDF_FONTTYPE_COMPOSITE) { + if (handle_multibyte_string(font, &str_ptr, &length, ctype) < 0) { + ERROR("Error in converting input string..."); + return; + } + if (real_font->used_chars != NULL) { + for (i = 0; i < length; i += 2) + add_to_used_chars2(real_font->used_chars, + (unsigned short) (str_ptr[i] << 8)|str_ptr[i+1]); + } + } else { + if (real_font->used_chars != NULL) { + for (i = 0; i < length; i++) + real_font->used_chars[str_ptr[i]] = 1; + } + } + + if (num_dev_coords > 0) { + xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); + ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); + } + + /* + * Kern is in units of character units, i.e., 1000 = 1 em. + * + * Positive kern means kerning (reduce excess white space). + * + * The following formula is of the form a*x/b where a, x, and b are signed long + * integers. Since in integer arithmetic (a*x) could overflow and a*(x/b) would + * not be accurate, we use floating point arithmetic rather than trying to do + * this all with integer arithmetic. + * + * 1000.0 / (font->extend * font->sptsize) is caluculated each times... + * Is accuracy really a matter? Character widths are always rounded to integer + * (in 1000 units per em) but dvipdfmx does not take into account of this... + */ + + if (text_state.dir_mode==0) { + /* Left-to-right */ + delh = text_xorigin + text_state.offset - xpos; + delv = ypos - text_yorigin; + } else if (text_state.dir_mode==1) { + /* Top-to-bottom */ + delh = ypos - text_yorigin + text_state.offset; + delv = xpos - text_xorigin; + } else { + /* Bottom-to-top */ + delh = ypos + text_yorigin + text_state.offset; + delv = xpos + text_xorigin; + } + + /* White-space more than 3em is not considered as a part of single text. + * So we will break string mode in that case. + * Dvipdfmx spend most of time processing strings with kern = 0 (but far + * more times in font handling). + * You may want to use pre-calculated value for WORD_SPACE_MAX. + * More text compression may be possible by replacing kern with space char + * when -kern is equal to space char width. + */ +#define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize) + + if (text_state.force_reset || + labs(delv) > dev_unit.min_bp_val || + labs(delh) > WORD_SPACE_MAX(font)) { + text_mode(); + kern = 0; + } else { + kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize); + } + + /* Inaccucary introduced by rounding of character width appears within + * single text block. There are point_size/1000 rounding error per character. + * If you really care about accuracy, you should compensate this here too. + */ + if (motion_state != STRING_MODE) + string_mode(xpos, ypos, + font->slant, font->extend, text_state.matrix.rotate); + else if (kern != 0) { + /* + * Same issues as earlier. Use floating point for simplicity. + * This routine needs to be fast, so we don't call sprintf() or strcpy(). + */ + text_state.offset -= + (spt_t) (kern * font->extend * (font->sptsize / 1000.0)); + format_buffer[len++] = text_state.is_mb ? '>' : ')'; + if (font->wmode) + len += p_itoa(-kern, format_buffer + len); + else { + len += p_itoa( kern, format_buffer + len); + } + format_buffer[len++] = text_state.is_mb ? '<' : '('; + pdf_doc_add_page_content(format_buffer, len); /* op: */ + len = 0; + } + + if (text_state.is_mb) { + if (FORMAT_BUF_SIZE - len < 2 * length) + ERROR("Buffer overflow..."); + for (i = 0; i < length; i++) { + int first, second; + + first = (str_ptr[i] >> 4) & 0x0f; + second = str_ptr[i] & 0x0f; + format_buffer[len++] = ((first >= 10) ? first + 'W' : first + '0'); + format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0'); + } + } else { + len += pdfobj_escape_str(format_buffer + len, + FORMAT_BUF_SIZE - len, str_ptr, length); + } + /* I think if you really care about speed, you should avoid memcopy here. */ + pdf_doc_add_page_content(format_buffer, len); /* op: */ + + text_state.offset += width; +} + +void +pdf_init_device (double dvi2pts, int precision, int black_and_white) +{ + if (precision < 0 || + precision > DEV_PRECISION_MAX) + WARN("Number of decimal digits out of range [0-%d].", + DEV_PRECISION_MAX); + + if (precision < 0) { + dev_unit.precision = 0; + } else if (precision > DEV_PRECISION_MAX) { + dev_unit.precision = DEV_PRECISION_MAX; + } else { + dev_unit.precision = precision; + } + dev_unit.dvi2pts = dvi2pts; + dev_unit.min_bp_val = (long) ROUND(1.0/(ten_pow[dev_unit.precision]*dvi2pts), 1); + if (dev_unit.min_bp_val < 0) + dev_unit.min_bp_val = -dev_unit.min_bp_val; + + dev_param.colormode = (black_and_white ? 0 : 1); + + graphics_mode(); + pdf_color_clear_stack(); + pdf_dev_init_gstates(); + + num_dev_fonts = max_dev_fonts = 0; + dev_fonts = NULL; + num_dev_coords = max_dev_coords = 0; + dev_coords = NULL; +} + +void +pdf_close_device (void) +{ + if (dev_fonts) { + int i; + + for (i = 0; i < num_dev_fonts; i++) { + if (dev_fonts[i].tex_name) + RELEASE(dev_fonts[i].tex_name); + if (dev_fonts[i].resource) + pdf_release_obj(dev_fonts[i].resource); + dev_fonts[i].tex_name = NULL; + dev_fonts[i].resource = NULL; + } + RELEASE(dev_fonts); + } + if (dev_coords) RELEASE(dev_coords); + pdf_dev_clear_gstates(); +} + +/* + * BOP, EOP, and FONT section. + * BOP and EOP manipulate some of the same data structures + * as the font stuff. + */ +void +pdf_dev_reset_fonts (void) +{ + int i; + + for (i = 0; i < num_dev_fonts; i++) { + dev_fonts[i].used_on_this_page = 0; + } + + text_state.font_id = -1; + + text_state.matrix.slant = 0.0; + text_state.matrix.extend = 1.0; + text_state.matrix.rotate = TEXT_WMODE_HH; + + text_state.bold_param = 0.0; + + text_state.is_mb = 0; +} + +void +pdf_dev_reset_color (int force) +{ + pdf_color *sc, *fc; + +#ifdef XETEX + 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); + } +#else + { + pdf_color_get_current(&sc, &fc); + pdf_dev_set_color(sc, 0, force); + pdf_dev_set_color(fc, 0x20, force); + } +#endif +} + +#if 0 +/* Not working */ +void +pdf_dev_set_origin (double phys_x, double phys_y) +{ + pdf_tmatrix M0, M1; + + pdf_dev_currentmatrix(&M0); + pdf_dev_currentmatrix(&M1); + pdf_invertmatrix(&M1); + M0.e = phys_x; M0.f = phys_y; + pdf_concatmatrix(&M1, &M0); + + pdf_dev_concat(&M1); +} +#endif + +void +pdf_dev_bop (const pdf_tmatrix *M) +{ + graphics_mode(); + + text_state.force_reset = 0; + + pdf_dev_gsave(); + pdf_dev_concat(M); + + pdf_dev_reset_fonts(); + pdf_dev_reset_color(0); +} + +void +pdf_dev_eop (void) +{ + int depth; + + graphics_mode(); + + depth = pdf_dev_current_depth(); + if (depth != 1) { + WARN("Unbalenced q/Q nesting...: %d", depth); + pdf_dev_grestore_to(0); + } else { + pdf_dev_grestore(); + } +} + +static void +print_fontmap (const char *font_name, fontmap_rec *mrec) +{ + if (!mrec) + return; + + MESG("\n"); + + MESG("fontmap: %s -> %s", font_name, mrec->font_name); + if (mrec->enc_name) + MESG("(%s)", mrec->enc_name); + if (mrec->opt.extend != 1.0) + MESG("[extend:%g]", mrec->opt.extend); + if (mrec->opt.slant != 0.0) + MESG("[slant:%g]", mrec->opt.slant); + if (mrec->opt.bold != 0.0) + MESG("[bold:%g]", mrec->opt.bold); + if (mrec->opt.flags & FONTMAP_OPT_NOEMBED) + MESG("[noemb]"); + if (mrec->opt.mapc >= 0) + MESG("[map:<%02x>]", mrec->opt.mapc); + if (mrec->opt.charcoll) + MESG("[csi:%s]", mrec->opt.charcoll); + if (mrec->opt.index) + MESG("[index:%d]", mrec->opt.index); + + switch (mrec->opt.style) { + case FONTMAP_STYLE_BOLD: + MESG("[style:bold]"); + break; + case FONTMAP_STYLE_ITALIC: + MESG("[style:italic]"); + break; + case FONTMAP_STYLE_BOLDITALIC: + MESG("[style:bolditalic]"); + break; + } + MESG("\n"); + +} + +/* _FIXME_ + * Font is identified with font_name and point_size as in DVI here. + * However, except for PDF_FONTTYPE_BITMAP, we can share the + * short_name, resource and used_chars between multiple instances + * of the same font at different sizes. + */ +int +pdf_dev_locate_font (const char *font_name, spt_t ptsize) +{ + int i; + fontmap_rec *mrec; + struct dev_font *font; + + if (!font_name) + return -1; + + if (ptsize == 0) { + ERROR("pdf_dev_locate_font() called with the zero ptsize."); + return -1; + } + + for (i = 0; i < num_dev_fonts; i++) { + if (strcmp(font_name, dev_fonts[i].tex_name) == 0) { + if (ptsize == dev_fonts[i].sptsize) + return i; /* found a dev_font that matches the request */ + if (dev_fonts[i].format != PDF_FONTTYPE_BITMAP) + break; /* new dev_font will share pdf resource with /i/ */ + } + } + + /* + * Make sure we have room for a new one, even though we may not + * actually create one. + */ + if (num_dev_fonts >= max_dev_fonts) { + max_dev_fonts += 16; + dev_fonts = RENEW(dev_fonts, max_dev_fonts, struct dev_font); + } + + font = &dev_fonts[num_dev_fonts]; + + /* New font */ + mrec = pdf_lookup_fontmap_record(font_name); + + if (verbose > 1) + print_fontmap(font_name, mrec); + + font->font_id = pdf_font_findresource(font_name, ptsize * dev_unit.dvi2pts, mrec); + if (font->font_id < 0) + return -1; + + /* We found device font here. */ + if (i < num_dev_fonts) { + font->real_font_index = i; + strcpy(font->short_name, dev_fonts[i].short_name); + } + else { + font->real_font_index = -1; + font->short_name[0] = 'F'; + p_itoa(num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */ + num_phys_fonts++; + } + + font->used_on_this_page = 0; + + font->tex_name = NEW(strlen(font_name) + 1, char); + strcpy(font->tex_name, font_name); + font->sptsize = ptsize; + + switch (pdf_get_font_subtype(font->font_id)) { + case PDF_FONT_FONTTYPE_TYPE3: + font->format = PDF_FONTTYPE_BITMAP; + break; + case PDF_FONT_FONTTYPE_TYPE0: + font->format = PDF_FONTTYPE_COMPOSITE; + break; + default: + font->format = PDF_FONTTYPE_SIMPLE; + break; + } + + font->wmode = pdf_get_font_wmode (font->font_id); + font->enc_id = pdf_get_font_encoding(font->font_id); +#ifdef XETEX + font->ft_to_gid = pdf_get_font_ft_to_gid(font->font_id); +#endif + + font->resource = NULL; /* Don't ref obj until font is actually used. */ + font->used_chars = NULL; + + font->extend = 1.0; + font->slant = 0.0; + font->bold = 0.0; + font->mapc = -1; + font->is_unicode = 0; + font->ucs_group = 0; + font->ucs_plane = 0; + + if (mrec) { + font->extend = mrec->opt.extend; + font->slant = mrec->opt.slant; + font->bold = mrec->opt.bold; + if (mrec->opt.mapc >= 0) + font->mapc = (mrec->opt.mapc >> 8) & 0xff; + else { + font->mapc = -1; + } + if (mrec->enc_name && + !strcmp(mrec->enc_name, "unicode")) { + font->is_unicode = 1; + if (mrec->opt.mapc >= 0) { + font->ucs_group = (mrec->opt.mapc >> 24) & 0xff; + font->ucs_plane = (mrec->opt.mapc >> 16) & 0xff; + } else { + font->ucs_group = 0; + font->ucs_plane = 0; + } + } else { + font->is_unicode = 0; + } + } + + return num_dev_fonts++; +} + + +/* This does not remember current stroking width. */ +static int +dev_sprint_line (char *buf, spt_t width, + spt_t p0_x, spt_t p0_y, spt_t p1_x, spt_t p1_y) +{ + int len = 0; + double w; + + w = width * dev_unit.dvi2pts; + + len += p_dtoa(w, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), buf+len); + buf[len++] = ' '; + buf[len++] = 'w'; + buf[len++] = ' '; + len += dev_sprint_bp(buf+len, p0_x, NULL); + buf[len++] = ' '; + len += dev_sprint_bp(buf+len, p0_y, NULL); + buf[len++] = ' '; + buf[len++] = 'm'; + buf[len++] = ' '; + len += dev_sprint_bp(buf+len, p1_x, NULL); + buf[len++] = ' '; + len += dev_sprint_bp(buf+len, p1_y, NULL); + buf[len++] = ' '; + buf[len++] = 'l'; + buf[len++] = ' '; + buf[len++] = 'S'; + + return len; +} + +/* Not optimized. */ +#define PDF_LINE_THICKNESS_MAX 5.0 +void +pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) +{ + int len = 0; + double width_in_bp; + + if (num_dev_coords > 0) { + xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); + ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); + } + + graphics_mode(); + + format_buffer[len++] = ' '; + format_buffer[len++] = 'q'; + format_buffer[len++] = ' '; + /* Don't use too thick line. */ + width_in_bp = ((width < height) ? width : height) * dev_unit.dvi2pts; + if (width_in_bp < 0.0 || /* Shouldn't happen */ + width_in_bp > PDF_LINE_THICKNESS_MAX) { + pdf_rect rect; + + rect.llx = dev_unit.dvi2pts * xpos; + rect.lly = dev_unit.dvi2pts * ypos; + rect.urx = dev_unit.dvi2pts * width; + rect.ury = dev_unit.dvi2pts * height; + len += pdf_sprint_rect(format_buffer+len, &rect); + format_buffer[len++] = ' '; + format_buffer[len++] = 'r'; + format_buffer[len++] = 'e'; + format_buffer[len++] = ' '; + format_buffer[len++] = 'f'; + } else { + if (width > height) { + /* NOTE: + * A line width of 0 denotes the thinnest line that can be rendered at + * device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2, + * "Details of Graphics State Parameters", p. 185. + */ + if (height < dev_unit.min_bp_val) { + WARN("Too thin line: height=%ld (%g bp)", height, width_in_bp); + WARN("Please consider using \"-d\" option."); + } + len += dev_sprint_line(format_buffer+len, + height, + xpos, + ypos + height/2, + xpos + width, + ypos + height/2); + } else { + if (width < dev_unit.min_bp_val) { + WARN("Too thin line: width=%ld (%g bp)", width, width_in_bp); + WARN("Please consider using \"-d\" option."); + } + len += dev_sprint_line(format_buffer+len, + width, + xpos + width/2, + ypos, + xpos + width/2, + ypos + height); + } + } + format_buffer[len++] = ' '; + format_buffer[len++] = 'Q'; + pdf_doc_add_page_content(format_buffer, len); /* op: q re f Q */ +} + +/* Rectangle in device space coordinate. */ +void +pdf_dev_set_rect (pdf_rect *rect, + spt_t x_user, spt_t y_user, + spt_t width, spt_t height, spt_t depth) +{ + double dev_x, dev_y; + pdf_coord p0, p1, p2, p3; + double min_x, min_y, max_x, max_y; + + dev_x = x_user * dev_unit.dvi2pts; + dev_y = y_user * dev_unit.dvi2pts; + if (text_state.dir_mode) { + p0.x = dev_x - dev_unit.dvi2pts * depth; + p0.y = dev_y - dev_unit.dvi2pts * width; + p1.x = dev_x + dev_unit.dvi2pts * height; + p1.y = p0.y; + p2.x = p1.x; + p2.y = dev_y; + p3.x = p0.x; + p3.y = p2.y; + } else { + p0.x = dev_x; + p0.y = dev_y - dev_unit.dvi2pts * depth; + p1.x = dev_x + dev_unit.dvi2pts * width; + p1.y = p0.y; + p2.x = p1.x; + p2.y = dev_y + dev_unit.dvi2pts * height; + p3.x = p0.x; + p3.y = p2.y; + } + + pdf_dev_transform(&p0, NULL); /* currentmatrix */ + pdf_dev_transform(&p1, NULL); + pdf_dev_transform(&p2, NULL); + pdf_dev_transform(&p3, NULL); + + min_x = MIN(p0.x , p1.x); + min_x = MIN(min_x, p2.x); + min_x = MIN(min_x, p3.x); + + max_x = MAX(p0.x , p1.x); + max_x = MAX(max_x, p2.x); + max_x = MAX(max_x, p3.x); + + min_y = MIN(p0.y , p1.y); + min_y = MIN(min_y, p2.y); + min_y = MIN(min_y, p3.y); + + max_y = MAX(p0.y , p1.y); + max_y = MAX(max_y, p2.y); + max_y = MAX(max_y, p3.y); + + rect->llx = min_x; + rect->lly = min_y; + rect->urx = max_x; + rect->ury = max_y; + + return; +} + +int +pdf_dev_get_dirmode (void) +{ + return text_state.dir_mode; +} + +void +pdf_dev_set_dirmode (int text_dir) +{ + struct dev_font *font; + int text_rotate; + int vert_dir, vert_font; + + font = CURRENTFONT(); + + vert_font = (font && font->wmode) ? 1 : 0; + if (dev_param.autorotate) { + vert_dir = text_dir; + } else { + vert_dir = vert_font; + } + text_rotate = (vert_font << 2)|vert_dir; + + if (font && + ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { + text_state.force_reset = 1; + } + + text_state.matrix.rotate = text_rotate; + text_state.dir_mode = text_dir; +} + +static void +dev_set_param_autorotate (int auto_rotate) +{ + struct dev_font *font; + int text_rotate, vert_font, vert_dir; + + font = CURRENTFONT(); + + vert_font = (font && font->wmode) ? 1 : 0; + if (auto_rotate) { + vert_dir = text_state.dir_mode; + } else { + vert_dir = vert_font; + } + text_rotate = (vert_font << 2)|vert_dir; + + if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { + text_state.force_reset = 1; + } + text_state.matrix.rotate = text_rotate; + dev_param.autorotate = auto_rotate; +} + +int +pdf_dev_get_param (int param_type) +{ + int value = 0; + + switch (param_type) { + case PDF_DEV_PARAM_AUTOROTATE: + value = dev_param.autorotate; + break; + case PDF_DEV_PARAM_COLORMODE: + value = dev_param.colormode; + break; + default: + ERROR("Unknown device parameter: %d", param_type); + } + + return value; +} + +void +pdf_dev_set_param (int param_type, int value) +{ + switch (param_type) { + case PDF_DEV_PARAM_AUTOROTATE: + dev_set_param_autorotate(value); + break; + case PDF_DEV_PARAM_COLORMODE: + dev_param.colormode = value; /* 0 for B&W */ + break; + default: + ERROR("Unknown device parameter: %d", param_type); + } + + return; +} + + +int +pdf_dev_put_image (int id, + transform_info *p, + double ref_x, + double ref_y) +{ + char *res_name; + pdf_tmatrix M, M1; + pdf_rect r; + int len = 0; + + if (num_dev_coords > 0) { + ref_x -= dev_coords[num_dev_coords-1].x; + ref_y -= dev_coords[num_dev_coords-1].y; + } + + pdf_copymatrix(&M, &(p->matrix)); + M.e += ref_x; M.f += ref_y; + /* Just rotate by -90, but not tested yet. Any problem if M has scaling? */ + if (dev_param.autorotate && + text_state.dir_mode) { + double tmp; + tmp = -M.a; M.a = M.b; M.b = tmp; + tmp = -M.c; M.c = M.d; M.d = tmp; + } + + graphics_mode(); + pdf_dev_gsave(); + + pdf_ximage_scale_image(id, &M1, &r, p); + pdf_concatmatrix(&M, &M1); + pdf_dev_concat(&M); + + /* Clip */ + if (p->flags & INFO_DO_CLIP) { +#if 0 + pdf_dev_newpath(); + pdf_dev_moveto(r.llx, r.lly); + pdf_dev_lineto(r.urx, r.lly); + pdf_dev_lineto(r.urx, r.ury); + pdf_dev_lineto(r.llx, r.ury); + pdf_dev_closepath(); + pdf_dev_clip(); + pdf_dev_newpath(); +#else + pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); +#endif + } + + res_name = pdf_ximage_get_resname(id); + len = sprintf(work_buffer, " /%s Do", res_name); + pdf_doc_add_page_content(work_buffer, len); /* op: Do */ + + pdf_dev_grestore(); + + pdf_doc_add_page_resource("XObject", + res_name, + pdf_ximage_get_reference(id)); + +#ifdef XETEX + 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); + } +#endif + + return 0; +} + + +void +transform_info_clear (transform_info *info) +{ + /* Physical dimensions */ + info->width = 0.0; + info->height = 0.0; + info->depth = 0.0; + + info->bbox.llx = 0.0; + info->bbox.lly = 0.0; + info->bbox.urx = 0.0; + info->bbox.ury = 0.0; + + /* Transformation matrix */ + pdf_setmatrix(&(info->matrix), 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); + + info->flags = 0; +} diff --git a/Build/source/texk/dvipdfm-x/pdfdev.h b/Build/source/texk/dvipdfm-x/pdfdev.h index 63642cbc3e5..dbebf13249a 100644 --- a/Build/source/texk/dvipdfm-x/pdfdev.h +++ b/Build/source/texk/dvipdfm-x/pdfdev.h @@ -208,13 +208,7 @@ 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); - -#ifdef XETEX -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); -#endif +extern void pdf_dev_reset_color (int force); /* 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/dvipdfm-x/pdfdoc.c b/Build/source/texk/dvipdfm-x/pdfdoc.c new file mode 100644 index 00000000000..8a1b679c328 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfdoc.c @@ -0,0 +1,2742 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. +*/ + +/* + * TODO: Many things... + * {begin,end}_{bead,article}, box stack, name tree (not limited to dests)... + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" + +#include "numbers.h" + +#include "pdfobj.h" +#include "pdfparse.h" +#include "pdfnames.h" + +#include "pdfencrypt.h" + +#include "pdfdev.h" +#include "pdfdraw.h" +#include "pdfcolor.h" + +#include "pdfresource.h" +#include "pdffont.h" +#include "pdfximage.h" + +#include "pdflimits.h" + +#if HAVE_LIBPNG +#include "pngimage.h" +#endif +#include "jpegimage.h" + +#include "pdfdoc.h" + +#define PDFDOC_PAGES_ALLOC_SIZE 128u +#define PDFDOC_ARTICLE_ALLOC_SIZE 16 +#define PDFDOC_BEAD_ALLOC_SIZE 16 + +static int verbose = 0; + +static char manual_thumb_enabled = 0; +static char *thumb_basename = NULL; + +void +pdf_doc_enable_manual_thumbnails (void) +{ +#if HAVE_LIBPNG + manual_thumb_enabled = 1; +#else + WARN("Manual thumbnail is not supported without the libpng library."); +#endif +} + +static pdf_obj * +read_thumbnail (const char *thumb_filename) +{ + pdf_obj *image_ref; + int xobj_id; + FILE *fp; + + fp = MFOPEN(thumb_filename, FOPEN_RBIN_MODE); + if (!fp) { + WARN("Could not open thumbnail file \"%s\"", thumb_filename); + return NULL; + } + if (!check_for_png(fp) && !check_for_jpeg(fp)) { + WARN("Thumbnail \"%s\" not a png/jpeg file!", thumb_filename); + MFCLOSE(fp); + return NULL; + } + MFCLOSE(fp); + + xobj_id = pdf_ximage_findresource(thumb_filename, 0, NULL); + if (xobj_id < 0) { + WARN("Could not read thumbnail file \"%s\".", thumb_filename); + image_ref = NULL; + } else { + image_ref = pdf_ximage_get_reference(xobj_id); + } + + return image_ref; +} + +void +pdf_doc_set_verbose (void) +{ + verbose++; + pdf_font_set_verbose(); + pdf_color_set_verbose(); + pdf_ximage_set_verbose(); +} + +typedef struct pdf_form +{ + char *ident; + + pdf_tmatrix matrix; + pdf_rect cropbox; + + pdf_obj *resources; + pdf_obj *contents; +} pdf_form; + +struct form_list_node +{ + int q_depth; + pdf_form form; + + struct form_list_node *prev; +}; + +#define USE_MY_MEDIABOX (1 << 0) +typedef struct pdf_page +{ + pdf_obj *page_obj; + pdf_obj *page_ref; + + int flags; + + double ref_x, ref_y; + pdf_rect cropbox; + + pdf_obj *resources; + + /* Contents */ + pdf_obj *background; + pdf_obj *contents; + + /* global bop, background, contents, global eop */ + pdf_obj *content_refs[4]; + + pdf_obj *annots; + pdf_obj *beads; +} pdf_page; + +typedef struct pdf_olitem +{ + pdf_obj *dict; + + int is_open; + + struct pdf_olitem *first; + struct pdf_olitem *parent; + + struct pdf_olitem *next; +} pdf_olitem; + +typedef struct pdf_bead +{ + char *id; + long page_no; + pdf_rect rect; +} pdf_bead; + +typedef struct pdf_article +{ + char *id; + pdf_obj *info; + long num_beads; + long max_beads; + pdf_bead *beads; +} pdf_article; + +struct name_dict +{ + const char *category; + struct ht_table *data; +}; + + +typedef struct pdf_doc +{ + struct { + pdf_obj *dict; + + pdf_obj *viewerpref; + pdf_obj *pagelabels; + pdf_obj *pages; + pdf_obj *names; + pdf_obj *threads; + } root; + + pdf_obj *info; + + struct { + pdf_rect mediabox; + pdf_obj *bop, *eop; + + long num_entries; /* This is not actually total number of pages. */ + long max_entries; + pdf_page *entries; + } pages; + + struct { + pdf_olitem *first; + pdf_olitem *current; + int current_depth; + } outlines; + + struct { + long num_entries; + long max_entries; + pdf_article *entries; + } articles; + + struct name_dict *names; + + int check_gotos; + struct ht_table gotos; + + struct { + int outline_open_depth; + double annot_grow; + } opt; + + struct form_list_node *pending_forms; + +} pdf_doc; +static pdf_doc pdoc; + +static void +pdf_doc_init_catalog (pdf_doc *p) +{ + p->root.viewerpref = NULL; + p->root.pagelabels = NULL; + p->root.pages = NULL; + p->root.names = NULL; + p->root.threads = NULL; + + p->root.dict = pdf_new_dict(); + pdf_set_root(p->root.dict); + + return; +} + +static void +pdf_doc_close_catalog (pdf_doc *p) +{ + pdf_obj *tmp; + + if (p->root.viewerpref) { + tmp = pdf_lookup_dict(p->root.dict, "ViewerPreferences"); + if (!tmp) { + pdf_add_dict(p->root.dict, + pdf_new_name("ViewerPreferences"), + pdf_ref_obj (p->root.viewerpref)); + } else if (PDF_OBJ_DICTTYPE(tmp)) { + pdf_merge_dict(p->root.viewerpref, tmp); + pdf_add_dict(p->root.dict, + pdf_new_name("ViewerPreferences"), + pdf_ref_obj (p->root.viewerpref)); + } else { /* Maybe reference */ + /* What should I do? */ + WARN("Could not modify ViewerPreferences."); + } + pdf_release_obj(p->root.viewerpref); + p->root.viewerpref = NULL; + } + + if (p->root.pagelabels) { + tmp = pdf_lookup_dict(p->root.dict, "PageLabels"); + if (!tmp) { + tmp = pdf_new_dict(); + pdf_add_dict(tmp, pdf_new_name("Nums"), pdf_link_obj(p->root.pagelabels)); + pdf_add_dict(p->root.dict, + pdf_new_name("PageLabels"), pdf_ref_obj(tmp)); + pdf_release_obj(tmp); + } else { /* Maybe reference */ + /* What should I do? */ + WARN("Could not modify PageLabels."); + } + pdf_release_obj(p->root.pagelabels); + p->root.pagelabels = NULL; + } + + pdf_add_dict(p->root.dict, + pdf_new_name("Type"), pdf_new_name("Catalog")); + pdf_release_obj(p->root.dict); + p->root.dict = NULL; + + return; +} + +/* + * Pages are starting at 1. + * The page count does not increase until the page is finished. + */ +#define LASTPAGE(p) (&(p->pages.entries[p->pages.num_entries])) +#define FIRSTPAGE(p) (&(p->pages.entries[0])) +#define PAGECOUNT(p) (p->pages.num_entries) +#define MAXPAGES(p) (p->pages.max_entries) + +static void +doc_resize_page_entries (pdf_doc *p, long size) +{ + if (size > MAXPAGES(p)) { + long i; + + p->pages.entries = RENEW(p->pages.entries, size, struct pdf_page); + for (i = p->pages.max_entries; i < size; i++) { + p->pages.entries[i].page_obj = NULL; + p->pages.entries[i].page_ref = NULL; + p->pages.entries[i].flags = 0; + p->pages.entries[i].resources = NULL; + p->pages.entries[i].background = NULL; + p->pages.entries[i].contents = NULL; + p->pages.entries[i].content_refs[0] = NULL; /* global bop */ + p->pages.entries[i].content_refs[1] = NULL; /* background */ + p->pages.entries[i].content_refs[2] = NULL; /* page body */ + p->pages.entries[i].content_refs[3] = NULL; /* global eop */ + p->pages.entries[i].annots = NULL; + p->pages.entries[i].beads = NULL; + } + p->pages.max_entries = size; + } + + return; +} + +static pdf_page * +doc_get_page_entry (pdf_doc *p, unsigned long page_no) +{ + pdf_page *page; + + if (page_no > 65535ul) { + ERROR("Page number %ul too large!", page_no); + } else if (page_no == 0) { + ERROR("Invalid Page number %ul.", page_no); + } + + if (page_no > MAXPAGES(p)) { + doc_resize_page_entries(p, page_no + PDFDOC_PAGES_ALLOC_SIZE); + } + + page = &(p->pages.entries[page_no - 1]); + + return page; +} + +static void pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height); +static void pdf_doc_close_page_tree (pdf_doc *p); + +static void pdf_doc_init_names (pdf_doc *p, int check_gotos); +static void pdf_doc_close_names (pdf_doc *p); + +static void pdf_doc_add_goto (pdf_obj *annot_dict); + +static void pdf_doc_init_docinfo (pdf_doc *p); +static void pdf_doc_close_docinfo (pdf_doc *p); + +static void pdf_doc_init_articles (pdf_doc *p); +static void pdf_doc_close_articles (pdf_doc *p); +static void pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth); +static void pdf_doc_close_bookmarks (pdf_doc *p); + +void +pdf_doc_set_bop_content (const char *content, unsigned length) +{ + pdf_doc *p = &pdoc; + + ASSERT(p); + + if (p->pages.bop) { + pdf_release_obj(p->pages.bop); + p->pages.bop = NULL; + } + + if (length > 0) { + p->pages.bop = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(p->pages.bop, content, length); + } else { + p->pages.bop = NULL; + } + + return; +} + +void +pdf_doc_set_eop_content (const char *content, unsigned length) +{ + pdf_doc *p = &pdoc; + + if (p->pages.eop) { + pdf_release_obj(p->pages.eop); + p->pages.eop = NULL; + } + + if (length > 0) { + p->pages.eop = pdf_new_stream(STREAM_COMPRESS); + pdf_add_stream(p->pages.eop, content, length); + } else { + p->pages.eop = NULL; + } + + return; +} + +#ifndef HAVE_TM_GMTOFF +#ifndef HAVE_TIMEZONE + +/* auxiliary function to compute timezone offset on + systems that do not support the tm_gmtoff in struct tm, + or have a timezone variable. Such as i386-solaris. */ + +static long +compute_timezone_offset() +{ + const time_t now = time(NULL); + struct tm tm; + struct tm local; + time_t gmtoff; + + localtime_r(&now, &local); + gmtime_r(&now, &tm); + return (mktime(&local) - mktime(&tm)); +} + +#endif /* HAVE_TIMEZONE */ +#endif /* HAVE_TM_GMTOFF */ + +/* + * Docinfo + */ +static long +asn_date (char *date_string) +{ + long tz_offset; + time_t current_time; + struct tm *bd_time; + + time(¤t_time); + bd_time = localtime(¤t_time); + +#ifdef HAVE_TM_GMTOFF + tz_offset = bd_time->tm_gmtoff; +#else +# ifdef HAVE_TIMEZONE + tz_offset = -timezone; +# else + tz_offset = compute_timezone_offset(); +# endif /* HAVE_TIMEZONE */ +#endif /* HAVE_TM_GMTOFF */ + + sprintf(date_string, "D:%04d%02d%02d%02d%02d%02d%c%02ld'%02ld'", + bd_time->tm_year + 1900, bd_time->tm_mon + 1, bd_time->tm_mday, + bd_time->tm_hour, bd_time->tm_min, bd_time->tm_sec, + (tz_offset > 0) ? '+' : '-', labs(tz_offset) / 3600, + (labs(tz_offset) / 60) % 60); + + return strlen(date_string); +} + +static void +pdf_doc_init_docinfo (pdf_doc *p) +{ + p->info = pdf_new_dict(); + pdf_set_info(p->info); + + return; +} + +static void +pdf_doc_close_docinfo (pdf_doc *p) +{ + pdf_obj *docinfo = p->info; + + /* + * Excerpt from PDF Reference 4th ed., sec. 10.2.1. + * + * Any entry whose value is not known should be omitted from the dictionary, + * rather than included with an empty string as its value. + * + * .... + * + * Note: Although viewer applications can store custom metadata in the document + * information dictionary, it is inappropriate to store private content or + * structural information there; such information should be stored in the + * document catalog instead (see Section 3.6.1, Document Catalog ). + */ + const char *keys[] = { + "Title", "Author", "Subject", "Keywords", "Creator", "Producer", + "CreationDate", "ModDate", /* Date */ + NULL + }; + pdf_obj *value; + char *banner; + int i; + + for (i = 0; keys[i] != NULL; i++) { + value = pdf_lookup_dict(docinfo, keys[i]); + if (value) { + if (!PDF_OBJ_STRINGTYPE(value)) { + WARN("\"%s\" in DocInfo dictionary not string type.", keys[i]); + pdf_remove_dict(docinfo, keys[i]); + WARN("\"%s\" removed from DocInfo.", keys[i]); + } else if (pdf_string_length(value) == 0) { + /* The hyperref package often uses emtpy strings. */ + pdf_remove_dict(docinfo, keys[i]); + } + } + } + + banner = NEW(strlen(PACKAGE)+strlen(VERSION)+4, char); + sprintf(banner, "%s (%s)", PACKAGE, VERSION); + pdf_add_dict(docinfo, + pdf_new_name("Producer"), + pdf_new_string(banner, strlen(banner))); + RELEASE(banner); + + if (!pdf_lookup_dict(docinfo, "CreationDate")) { + char now[32]; + + asn_date(now); + pdf_add_dict(docinfo, + pdf_new_name ("CreationDate"), + pdf_new_string(now, strlen(now))); + } + + pdf_release_obj(docinfo); + p->info = NULL; + + return; +} + +static pdf_obj * +pdf_doc_get_page_resources (pdf_doc *p, const char *category) +{ + pdf_obj *resources; + pdf_page *currentpage; + pdf_obj *res_dict; + + if (!p || !category) { + return NULL; + } + + if (p->pending_forms) { + if (p->pending_forms->form.resources) { + res_dict = p->pending_forms->form.resources; + } else { + res_dict = p->pending_forms->form.resources = pdf_new_dict(); + } + } else { + currentpage = LASTPAGE(p); + if (currentpage->resources) { + res_dict = currentpage->resources; + } else { + res_dict = currentpage->resources = pdf_new_dict(); + } + } + resources = pdf_lookup_dict(res_dict, category); + if (!resources) { + resources = pdf_new_dict(); + pdf_add_dict(res_dict, pdf_new_name(category), resources); + } + + return resources; +} + +void +pdf_doc_add_page_resource (const char *category, + const char *resource_name, pdf_obj *resource_ref) +{ + pdf_doc *p = &pdoc; + pdf_obj *resources; + pdf_obj *duplicate; + + if (!PDF_OBJ_INDIRECTTYPE(resource_ref)) { + WARN("Passed non indirect reference..."); + resource_ref = pdf_ref_obj(resource_ref); /* leak */ + } + resources = pdf_doc_get_page_resources(p, category); + duplicate = pdf_lookup_dict(resources, resource_name); + if (duplicate && pdf_compare_reference(duplicate, resource_ref)) { + WARN("Conflicting page resource found (page: %ld, category: %s, name: %s).", + pdf_doc_current_page_number(), category, resource_name); + WARN("Ignoring..."); + pdf_release_obj(resource_ref); + } else { + pdf_add_dict(resources, pdf_new_name(resource_name), resource_ref); + } + + return; +} + +static void +doc_flush_page (pdf_doc *p, pdf_page *page, pdf_obj *parent_ref) +{ + pdf_obj *contents_array; + int count; + + pdf_add_dict(page->page_obj, + pdf_new_name("Type"), pdf_new_name("Page")); + pdf_add_dict(page->page_obj, + pdf_new_name("Parent"), parent_ref); + + /* + * Clipping area specified by CropBox is affected by MediaBox which + * might be inherit from parent node. If MediaBox of the root node + * does not have enough size to cover all page's imaging area, using + * CropBox here gives incorrect result. + */ + if (page->flags & USE_MY_MEDIABOX) { + pdf_obj *mediabox; + + mediabox = pdf_new_array(); + pdf_add_array(mediabox, + pdf_new_number(ROUND(page->cropbox.llx, 0.01))); + pdf_add_array(mediabox, + pdf_new_number(ROUND(page->cropbox.lly, 0.01))); + pdf_add_array(mediabox, + pdf_new_number(ROUND(page->cropbox.urx, 0.01))); + pdf_add_array(mediabox, + pdf_new_number(ROUND(page->cropbox.ury, 0.01))); + pdf_add_dict(page->page_obj, pdf_new_name("MediaBox"), mediabox); + } + + count = 0; + contents_array = pdf_new_array(); + if (page->content_refs[0]) { /* global bop */ + pdf_add_array(contents_array, page->content_refs[0]); + count++; + } else if (p->pages.bop && + pdf_stream_length(p->pages.bop) > 0) { + pdf_add_array(contents_array, pdf_ref_obj(p->pages.bop)); + count++; + } + if (page->content_refs[1]) { /* background */ + pdf_add_array(contents_array, page->content_refs[1]); + count++; + } + if (page->content_refs[2]) { /* page body */ + pdf_add_array(contents_array, page->content_refs[2]); + count++; + } + if (page->content_refs[3]) { /* global eop */ + pdf_add_array(contents_array, page->content_refs[3]); + count++; + } else if (p->pages.eop && + pdf_stream_length(p->pages.eop) > 0) { + pdf_add_array(contents_array, pdf_ref_obj(p->pages.eop)); + count++; + } + + if (count == 0) { + WARN("Page with empty content found!!!"); + } + page->content_refs[0] = NULL; + page->content_refs[1] = NULL; + page->content_refs[2] = NULL; + page->content_refs[3] = NULL; + + pdf_add_dict(page->page_obj, + pdf_new_name("Contents"), contents_array); + + + if (page->annots) { + pdf_add_dict(page->page_obj, + pdf_new_name("Annots"), pdf_ref_obj(page->annots)); + pdf_release_obj(page->annots); + } + if (page->beads) { + pdf_add_dict(page->page_obj, + pdf_new_name("B"), pdf_ref_obj(page->beads)); + pdf_release_obj(page->beads); + } + pdf_release_obj(page->page_obj); + pdf_release_obj(page->page_ref); + + page->page_obj = NULL; + page->page_ref = NULL; + page->annots = NULL; + page->beads = NULL; + + return; +} + +/* B-tree? */ +#define PAGE_CLUSTER 4 +static pdf_obj * +build_page_tree (pdf_doc *p, + pdf_page *firstpage, long num_pages, + pdf_obj *parent_ref) +{ + pdf_obj *self, *self_ref, *kids; + long i; + + self = pdf_new_dict(); + /* + * This is a slight kludge which allow the subtree dictionary + * generated by this routine to be merged with the real + * page_tree dictionary, while keeping the indirect object + * references right. + */ + self_ref = parent_ref ? pdf_ref_obj(self) : pdf_ref_obj(p->root.pages); + + pdf_add_dict(self, pdf_new_name("Type"), pdf_new_name("Pages")); + pdf_add_dict(self, pdf_new_name("Count"), pdf_new_number((double) num_pages)); + + if (parent_ref != NULL) + pdf_add_dict(self, pdf_new_name("Parent"), parent_ref); + + kids = pdf_new_array(); + if (num_pages > 0 && num_pages <= PAGE_CLUSTER) { + for (i = 0; i < num_pages; i++) { + pdf_page *page; + + page = firstpage + i; + if (!page->page_ref) + page->page_ref = pdf_ref_obj(page->page_obj); + pdf_add_array (kids, pdf_link_obj(page->page_ref)); + doc_flush_page(p, page, pdf_link_obj(self_ref)); + } + } else if (num_pages > 0) { + for (i = 0; i < PAGE_CLUSTER; i++) { + long start, end; + + start = (i*num_pages)/PAGE_CLUSTER; + end = ((i+1)*num_pages)/PAGE_CLUSTER; + if (end - start > 1) { + pdf_obj *subtree; + + subtree = build_page_tree(p, firstpage + start, end - start, + pdf_link_obj(self_ref)); + pdf_add_array(kids, pdf_ref_obj(subtree)); + pdf_release_obj(subtree); + } else { + pdf_page *page; + + page = firstpage + start; + if (!page->page_ref) + page->page_ref = pdf_ref_obj(page->page_obj); + pdf_add_array (kids, pdf_link_obj(page->page_ref)); + doc_flush_page(p, page, pdf_link_obj(self_ref)); + } + } + } + pdf_add_dict(self, pdf_new_name("Kids"), kids); + pdf_release_obj(self_ref); + + return self; +} + +static void +pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height) +{ + /* + * Create empty page tree. + * The docroot.pages is kept open until the document is closed. + * This allows the user to write to pages if he so choses. + */ + p->root.pages = pdf_new_dict(); + + p->pages.num_entries = 0; + p->pages.max_entries = 0; + p->pages.entries = NULL; + + p->pages.bop = NULL; + p->pages.eop = NULL; + + p->pages.mediabox.llx = 0.0; + p->pages.mediabox.lly = 0.0; + p->pages.mediabox.urx = media_width; + p->pages.mediabox.ury = media_height; + + return; +} + +static void +pdf_doc_close_page_tree (pdf_doc *p) +{ + pdf_obj *page_tree_root; + pdf_obj *mediabox; + long page_no; + + /* + * Do consistency check on forward references to pages. + */ + for (page_no = PAGECOUNT(p) + 1; page_no <= MAXPAGES(p); page_no++) { + pdf_page *page; + + page = doc_get_page_entry(p, page_no); + if (page->page_obj) { + WARN("Nonexistent page #%ld refered.", page_no); + pdf_release_obj(page->page_ref); + page->page_ref = NULL; + } + if (page->page_obj) { + WARN("Entry for a nonexistent page #%ld created.", page_no); + pdf_release_obj(page->page_obj); + page->page_obj = NULL; + } + if (page->annots) { + WARN("Annotation attached to a nonexistent page #%ld.", page_no); + pdf_release_obj(page->annots); + page->annots = NULL; + } + if (page->beads) { + WARN("Article beads attached to a nonexistent page #%ld.", page_no); + pdf_release_obj(page->beads); + page->beads = NULL; + } + if (page->resources) { + pdf_release_obj(page->resources); + page->resources = NULL; + } + } + + /* + * Connect page tree to root node. + */ + page_tree_root = build_page_tree(p, FIRSTPAGE(p), PAGECOUNT(p), NULL); + pdf_merge_dict (p->root.pages, page_tree_root); + pdf_release_obj(page_tree_root); + + /* They must be after build_page_tree() */ + if (p->pages.bop) { + pdf_add_stream (p->pages.bop, "\n", 1); + pdf_release_obj(p->pages.bop); + p->pages.bop = NULL; + } + if (p->pages.eop) { + pdf_add_stream (p->pages.eop, "\n", 1); + pdf_release_obj(p->pages.eop); + p->pages.eop = NULL; + } + + /* Create media box at root node and let the other pages inherit it. */ + mediabox = pdf_new_array(); + pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.llx, 0.01))); + pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.lly, 0.01))); + pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.urx, 0.01))); + pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.ury, 0.01))); + pdf_add_dict(p->root.pages, pdf_new_name("MediaBox"), mediabox); + + pdf_add_dict(p->root.dict, + pdf_new_name("Pages"), + pdf_ref_obj (p->root.pages)); + pdf_release_obj(p->root.pages); + p->root.pages = NULL; + + RELEASE(p->pages.entries); + p->pages.entries = NULL; + p->pages.num_entries = 0; + p->pages.max_entries = 0; + + return; +} + +/* + * From PDFReference15_v6.pdf (p.119 and p.834) + * + * MediaBox rectangle (Required; inheritable) + * + * 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) + * + * 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) + * + * 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) + * + * 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) + * + * 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) + * + * 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. + */ + +pdf_obj * +pdf_doc_get_page (pdf_file *pf, long page_no, long *count_p, + pdf_rect *bbox, pdf_obj **resources_p) { + pdf_obj *page_tree = NULL; + pdf_obj *resources = NULL, *box = NULL, *rotate = NULL; + pdf_obj *catalog; + + catalog = pdf_file_get_catalog(pf); + + page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); + + if (!PDF_OBJ_DICTTYPE(page_tree)) + goto error; + + { + long count; + pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); + if (!PDF_OBJ_NUMBERTYPE(tmp)) { + if (tmp) + pdf_release_obj(tmp); + goto error; + } + count = pdf_number_value(tmp); + pdf_release_obj(tmp); + if (count_p) + *count_p = count; + if (page_no <= 0 || page_no > count) { + WARN("Page %ld does not exist.", page_no); + goto error_silent; + } + } + + /* + * Seek correct page. Get MediaBox, CropBox and Resources. + * (Note that these entries can be inherited.) + */ + { + pdf_obj *media_box = NULL, *crop_box = NULL, *kids, *tmp; + int depth = PDF_OBJ_MAX_DEPTH; + long page_idx = page_no-1, kids_length = 1, i = 0; + + while (--depth && i != kids_length) { + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) { + if (media_box) + pdf_release_obj(media_box); + media_box = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { + if (crop_box) + pdf_release_obj(crop_box); + crop_box = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { + if (rotate) + pdf_release_obj(rotate); + rotate = tmp; + } + + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { + if (resources) + pdf_release_obj(resources); + resources = tmp; + } + + kids = pdf_deref_obj(pdf_lookup_dict(page_tree, "Kids")); + if (!kids) + break; + else if (!PDF_OBJ_ARRAYTYPE(kids)) { + pdf_release_obj(kids); + goto error; + } + 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)); + if (!PDF_OBJ_DICTTYPE(page_tree)) + goto error; + + tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); + if (PDF_OBJ_NUMBERTYPE(tmp)) { + /* Pages object */ + count = pdf_number_value(tmp); + pdf_release_obj(tmp); + } else if (!tmp) + /* Page object */ + count = 1; + else { + pdf_release_obj(tmp); + goto error; + } + + if (page_idx < count) + break; + + page_idx -= count; + } + + pdf_release_obj(kids); + } + + if (!depth || kids_length == i) { + if (media_box) + pdf_release_obj(media_box); + if (crop_box) + pdf_release_obj(crop_box); + goto error; + } + + if (crop_box) + box = crop_box; + else + if (!(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox"))) && + !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox"))) && + !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox"))) && + media_box) { + box = media_box; + media_box = NULL; + } + if (media_box) + pdf_release_obj(media_box); + } + + if (!PDF_OBJ_ARRAYTYPE(box) || pdf_array_length(box) != 4 || + !PDF_OBJ_DICTTYPE(resources)) + goto error; + + if (PDF_OBJ_NUMBERTYPE(rotate)) { + if (pdf_number_value(rotate)) + WARN("<< /Rotate %d >> found. (Not supported yet)", + (int) pdf_number_value(rotate)); + pdf_release_obj(rotate); + rotate = NULL; + } else if (rotate) + goto error; + + { + int i; + + for (i = 4; i--; ) { + double x; + pdf_obj *tmp = pdf_deref_obj(pdf_get_array(box, i)); + if (!PDF_OBJ_NUMBERTYPE(tmp)) { + pdf_release_obj(tmp); + goto error; + } + x = pdf_number_value(tmp); + switch (i) { + case 0: bbox->llx = x; break; + case 1: bbox->lly = x; break; + case 2: bbox->urx = x; break; + case 3: bbox->ury = x; break; + } + pdf_release_obj(tmp); + } + } + + pdf_release_obj(box); + + if (resources_p) + *resources_p = resources; + else if (resources) + pdf_release_obj(resources); + + return page_tree; + + error: + WARN("Cannot parse document. Broken PDF file?"); + error_silent: + if (box) + pdf_release_obj(box); + if (rotate) + pdf_release_obj(rotate); + if (resources) + pdf_release_obj(resources); + if (page_tree) + pdf_release_obj(page_tree); + + return NULL; +} + +#ifndef BOOKMARKS_OPEN_DEFAULT +#define BOOKMARKS_OPEN_DEFAULT 0 +#endif + +static int clean_bookmarks (pdf_olitem *item); +static int flush_bookmarks (pdf_olitem *item, + pdf_obj *parent_ref, + pdf_obj *parent_dict); + +static void +pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth) +{ + pdf_olitem *item; + +#define MAX_OUTLINE_DEPTH 256u + p->opt.outline_open_depth = + ((bm_open_depth >= 0) ? + bm_open_depth : MAX_OUTLINE_DEPTH - bm_open_depth); + + p->outlines.current_depth = 1; + + item = NEW(1, pdf_olitem); + item->dict = NULL; + item->next = NULL; + item->first = NULL; + item->parent = NULL; + item->is_open = 1; + + p->outlines.current = item; + p->outlines.first = item; + + return; +} + +static int +clean_bookmarks (pdf_olitem *item) +{ + pdf_olitem *next; + + while (item) { + next = item->next; + if (item->dict) + pdf_release_obj(item->dict); + if (item->first) + clean_bookmarks(item->first); + RELEASE(item); + + item = next; + } + + return 0; +} + +static int +flush_bookmarks (pdf_olitem *node, + pdf_obj *parent_ref, pdf_obj *parent_dict) +{ + int retval; + int count; + pdf_olitem *item; + pdf_obj *this_ref, *prev_ref, *next_ref; + + ASSERT(node->dict); + + this_ref = pdf_ref_obj(node->dict); + pdf_add_dict(parent_dict, + pdf_new_name("First"), pdf_link_obj(this_ref)); + + retval = 0; + for (item = node, prev_ref = NULL; + item && item->dict; item = item->next) { + if (item->first && item->first->dict) { + count = flush_bookmarks(item->first, this_ref, item->dict); + if (item->is_open) { + pdf_add_dict(item->dict, + pdf_new_name("Count"), + pdf_new_number(count)); + retval += count; + } else { + pdf_add_dict(item->dict, + pdf_new_name("Count"), + pdf_new_number(-count)); + } + } + pdf_add_dict(item->dict, + pdf_new_name("Parent"), + pdf_link_obj(parent_ref)); + if (prev_ref) { + pdf_add_dict(item->dict, + pdf_new_name("Prev"), + prev_ref); + } + if (item->next && item->next->dict) { + next_ref = pdf_ref_obj(item->next->dict); + pdf_add_dict(item->dict, + pdf_new_name("Next"), + pdf_link_obj(next_ref)); + } else { + next_ref = NULL; + } + + pdf_release_obj(item->dict); + item->dict = NULL; + + prev_ref = this_ref; + this_ref = next_ref; + retval++; + } + + pdf_add_dict(parent_dict, + pdf_new_name("Last"), + pdf_link_obj(prev_ref)); + + pdf_release_obj(prev_ref); + pdf_release_obj(node->dict); + node->dict = NULL; + + return retval; +} + +int +pdf_doc_bookmarks_up (void) +{ + pdf_doc *p = &pdoc; + pdf_olitem *parent, *item; + + item = p->outlines.current; + if (!item || !item->parent) { + WARN("Can't go up above the bookmark root node!"); + return -1; + } + parent = item->parent; + item = parent->next; + if (!parent->next) { + parent->next = item = NEW(1, pdf_olitem); + item->dict = NULL; + item->first = NULL; + item->next = NULL; + item->is_open = 0; + item->parent = parent->parent; + } + p->outlines.current = item; + p->outlines.current_depth--; + + return 0; +} + +int +pdf_doc_bookmarks_down (void) +{ + pdf_doc *p = &pdoc; + pdf_olitem *item, *first; + + item = p->outlines.current; + if (!item->dict) { + pdf_obj *tcolor, *action; + + WARN("Empty bookmark node!"); + WARN("You have tried to jump more than 1 level."); + + item->dict = pdf_new_dict(); + +#define TITLE_STRING "" + pdf_add_dict(item->dict, + pdf_new_name("Title"), + pdf_new_string(TITLE_STRING, strlen(TITLE_STRING))); + + tcolor = pdf_new_array(); + pdf_add_array(tcolor, pdf_new_number(1.0)); + pdf_add_array(tcolor, pdf_new_number(0.0)); + pdf_add_array(tcolor, pdf_new_number(0.0)); + pdf_add_dict (item->dict, + pdf_new_name("C"), pdf_link_obj(tcolor)); + pdf_release_obj(tcolor); + + pdf_add_dict (item->dict, + pdf_new_name("F"), pdf_new_number(1.0)); + +#define JS_CODE "app.alert(\"The author of this document made this bookmark item empty!\", 3, 0)" + action = pdf_new_dict(); + pdf_add_dict(action, + pdf_new_name("S"), pdf_new_name("JavaScript")); + pdf_add_dict(action, + pdf_new_name("JS"), pdf_new_string(JS_CODE, strlen(JS_CODE))); + pdf_add_dict(item->dict, + pdf_new_name("A"), pdf_link_obj(action)); + pdf_release_obj(action); + } + + item->first = first = NEW(1, pdf_olitem); + first->dict = NULL; + first->is_open = 0; + first->parent = item; + first->next = NULL; + first->first = NULL; + + p->outlines.current = first; + p->outlines.current_depth++; + + return 0; +} + +int +pdf_doc_bookmarks_depth (void) +{ + pdf_doc *p = &pdoc; + + return p->outlines.current_depth; +} + +void +pdf_doc_bookmarks_add (pdf_obj *dict, int is_open) +{ + pdf_doc *p = &pdoc; + pdf_olitem *item, *next; + + ASSERT(p && dict); + + item = p->outlines.current; + + if (!item) { + item = NEW(1, pdf_olitem); + item->parent = NULL; + p->outlines.first = item; + } else if (item->dict) { /* go to next item */ + item = item->next; + } + +#define BMOPEN(b,p) (((b) < 0) ? (((p)->outlines.current_depth > (p)->opt.outline_open_depth) ? 0 : 1) : (b)) + +#if 0 + item->dict = pdf_link_obj(dict); +#endif + item->dict = dict; + item->first = NULL; + item->is_open = BMOPEN(is_open, p); + + item->next = next = NEW(1, pdf_olitem); + next->dict = NULL; + next->parent = item->parent; + next->first = NULL; + next->is_open = -1; + next->next = NULL; + + p->outlines.current = item; + + pdf_doc_add_goto(dict); + + return; +} + +static void +pdf_doc_close_bookmarks (pdf_doc *p) +{ + pdf_obj *catalog = p->root.dict; + pdf_olitem *item; + int count; + pdf_obj *bm_root, *bm_root_ref; + + item = p->outlines.first; + if (item->dict) { + bm_root = pdf_new_dict(); + bm_root_ref = pdf_ref_obj(bm_root); + count = flush_bookmarks(item, bm_root_ref, bm_root); + pdf_add_dict(bm_root, + pdf_new_name("Count"), + pdf_new_number(count)); + pdf_add_dict(catalog, + pdf_new_name("Outlines"), + bm_root_ref); + pdf_release_obj(bm_root); + } + clean_bookmarks(item); + + p->outlines.first = NULL; + p->outlines.current = NULL; + p->outlines.current_depth = 0; + + return; +} + + +static const char *name_dict_categories[] = { + "Dests", "AP", "JavaScript", "Pages", + "Templates", "IDS", "URLS", "EmbeddedFiles", + "AlternatePresentations", "Renditions" +}; +#define NUM_NAME_CATEGORY (sizeof(name_dict_categories)/sizeof(name_dict_categories[0])) + +static void +pdf_doc_init_names (pdf_doc *p, int check_gotos) +{ + int i; + + p->root.names = NULL; + + p->names = NEW(NUM_NAME_CATEGORY + 1, struct name_dict); + for (i = 0; i < NUM_NAME_CATEGORY; i++) { + p->names[i].category = name_dict_categories[i]; + p->names[i].data = strcmp(name_dict_categories[i], "Dests") ? + NULL : pdf_new_name_tree(); + /* + * We need a non-null entry for PDF destinations in order to find + * broken links even if no destination is defined in the DVI file. + */ + } + p->names[NUM_NAME_CATEGORY].category = NULL; + p->names[NUM_NAME_CATEGORY].data = NULL; + + p->check_gotos = check_gotos; + ht_init_table(&p->gotos, (void (*) (void *)) pdf_release_obj); + + return; +} + +int +pdf_doc_add_names (const char *category, + const void *key, int keylen, pdf_obj *value) +{ + pdf_doc *p = &pdoc; + int i; + + for (i = 0; p->names[i].category != NULL; i++) { + if (!strcmp(p->names[i].category, category)) { + break; + } + } + if (p->names[i].category == NULL) { + WARN("Unknown name dictionary category \"%s\".", category); + return -1; + } + if (!p->names[i].data) { + p->names[i].data = pdf_new_name_tree(); + } + + return pdf_names_add_object(p->names[i].data, key, keylen, value); +} + +static void +pdf_doc_add_goto (pdf_obj *annot_dict) +{ + pdf_obj *subtype = NULL, *A = NULL, *S = NULL, *D = NULL, *D_new, *dict; + const char *dest, *key; + + if (!pdoc.check_gotos) + return; + + /* + * An annotation dictionary coming from an annotation special + * must have a "Subtype". An annotation dictionary coming from + * an outline special has none. + */ + subtype = pdf_deref_obj(pdf_lookup_dict(annot_dict, "Subtype")); + if (subtype) { + if (PDF_OBJ_UNDEFINED(subtype)) + goto undefined; + else if (!PDF_OBJ_NAMETYPE(subtype)) + goto error; + else if (strcmp(pdf_name_value(subtype), "Link")) + goto cleanup; + } + + dict = annot_dict; + key = "Dest"; + D = pdf_deref_obj(pdf_lookup_dict(annot_dict, key)); + if (PDF_OBJ_UNDEFINED(D)) + goto undefined; + + A = pdf_deref_obj(pdf_lookup_dict(annot_dict, "A")); + if (A) { + if (PDF_OBJ_UNDEFINED(A)) + goto undefined; + else if (D || !PDF_OBJ_DICTTYPE(A)) + goto error; + else { + S = pdf_deref_obj(pdf_lookup_dict(A, "S")); + if (PDF_OBJ_UNDEFINED(S)) + goto undefined; + else if (!PDF_OBJ_NAMETYPE(S)) + goto error; + else if (strcmp(pdf_name_value(S), "GoTo")) + goto cleanup; + + dict = A; + key = "D"; + D = pdf_deref_obj(pdf_lookup_dict(A, key)); + } + } + + if (PDF_OBJ_STRINGTYPE(D)) + dest = (char *) pdf_string_value(D); +#if 0 + /* Names as destinations are not supported by dvipdfmx */ + else if (PDF_OBJ_NAMETYPE(D)) + dest = pdf_name_value(D); +#endif + else if (PDF_OBJ_ARRAYTYPE(D)) + goto cleanup; + else if (PDF_OBJ_UNDEFINED(D)) + goto undefined; + else + goto error; + + D_new = ht_lookup_table(&pdoc.gotos, dest, strlen(dest)); + if (!D_new) { + char buf[10]; + + /* We use hexadecimal notation for our numeric destinations. + * Other bases (e.g., 10+26 or 10+2*26) would be more efficient. + */ + sprintf(buf, "%lx", ht_table_size(&pdoc.gotos)); + D_new = pdf_new_string(buf, strlen(buf)); + ht_append_table(&pdoc.gotos, dest, strlen(dest), D_new); + } + + { + pdf_obj *key_obj = pdf_new_name(key); + if (!pdf_add_dict(dict, key_obj, pdf_link_obj(D_new))) + pdf_release_obj(key_obj); + } + + cleanup: + if (subtype) + pdf_release_obj(subtype); + if (A) + pdf_release_obj(A); + if (S) + pdf_release_obj(S); + if (D) + pdf_release_obj(D); + + return; + + error: + WARN("Unknown PDF annotation format. Output file may be broken."); + goto cleanup; + + undefined: + WARN("Cannot optimize PDF annotations. Output file may be broken." + " Please restart with option \"-C 0x10\"\n"); + goto cleanup; +} + +static void +warn_undef_dests (struct ht_table *dests, struct ht_table *gotos) +{ + struct ht_iter iter; + + if (ht_set_iter(gotos, &iter) < 0) + return; + + do { + int keylen; + char *key = ht_iter_getkey(&iter, &keylen); + if (!ht_lookup_table(dests, key, keylen)) { + char *dest = NEW(keylen+1, char); + memcpy(dest, key, keylen); + dest[keylen] = 0; + WARN("PDF destination \"%s\" not defined.", dest); + RELEASE(dest); + } + } while (ht_iter_next(&iter) >= 0); + + ht_clear_iter(&iter); +} + +static void +pdf_doc_close_names (pdf_doc *p) +{ + pdf_obj *tmp; + int i; + + for (i = 0; p->names[i].category != NULL; i++) { + if (p->names[i].data) { + struct ht_table *data = p->names[i].data; + pdf_obj *name_tree; + long count; + + if (!pdoc.check_gotos || strcmp(p->names[i].category, "Dests")) + name_tree = pdf_names_create_tree(data, &count, NULL); + else { + name_tree = pdf_names_create_tree(data, &count, &pdoc.gotos); + + if (verbose && count < data->count) + MESG("\nRemoved %ld unused PDF destinations\n", data->count-count); + + if (count < pdoc.gotos.count) + warn_undef_dests(data, &pdoc.gotos); + } + + if (name_tree) { + if (!p->root.names) + p->root.names = pdf_new_dict(); + pdf_add_dict(p->root.names, + pdf_new_name(p->names[i].category), + pdf_ref_obj(name_tree)); + pdf_release_obj(name_tree); + } + pdf_delete_name_tree(&p->names[i].data); + } + } + + if (p->root.names) { + tmp = pdf_lookup_dict(p->root.dict, "Names"); + if (!tmp) { + pdf_add_dict(p->root.dict, + pdf_new_name("Names"), + pdf_ref_obj (p->root.names)); + } else if (PDF_OBJ_DICTTYPE(tmp)) { + pdf_merge_dict(p->root.names, tmp); + pdf_add_dict(p->root.dict, + pdf_new_name("Names"), + pdf_ref_obj (p->root.names)); + } else { /* Maybe reference */ + /* What should I do? */ + WARN("Could not modify Names dictionary."); + } + pdf_release_obj(p->root.names); + p->root.names = NULL; + } + + RELEASE(p->names); + p->names = NULL; + + ht_clear_table(&p->gotos); + + return; +} + + +void +pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, + pdf_obj *annot_dict, int new_annot) +{ + pdf_doc *p = &pdoc; + pdf_page *page; + pdf_obj *rect_array; + double annot_grow = p->opt.annot_grow; + double xpos, ypos; + pdf_rect annbox; + + page = doc_get_page_entry(p, page_no); + if (!page->annots) + page->annots = pdf_new_array(); + + { + pdf_rect mediabox; + + pdf_doc_get_mediabox(page_no, &mediabox); + pdf_dev_get_coord(&xpos, &ypos); + annbox.llx = rect->llx - xpos; annbox.lly = rect->lly - ypos; + annbox.urx = rect->urx - xpos; annbox.ury = rect->ury - ypos; + + if (annbox.llx < mediabox.llx || annbox.urx > mediabox.urx || + annbox.lly < mediabox.lly || annbox.ury > mediabox.ury) { + WARN("Annotation out of page boundary."); + WARN("Current page's MediaBox: [%g %g %g %g]", + mediabox.llx, mediabox.lly, mediabox.urx, mediabox.ury); + WARN("Annotation: [%g %g %g %g]", + annbox.llx, annbox.lly, annbox.urx, annbox.ury); + WARN("Maybe incorrect paper size specified."); + } + if (annbox.llx > annbox.urx || annbox.lly > annbox.ury) { + WARN("Rectangle with negative width/height: [%g %g %g %g]", + annbox.llx, annbox.lly, annbox.urx, annbox.ury); + } + } + + rect_array = pdf_new_array(); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.llx - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.lly - annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.urx + annot_grow, 0.001))); + pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.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)); + + if (new_annot) + pdf_doc_add_goto(annot_dict); + + return; +} + + +/* + * PDF Article Thread + */ +static void +pdf_doc_init_articles (pdf_doc *p) +{ + p->root.threads = NULL; + + p->articles.num_entries = 0; + p->articles.max_entries = 0; + p->articles.entries = NULL; + + return; +} + +void +pdf_doc_begin_article (const char *article_id, pdf_obj *article_info) +{ + pdf_doc *p = &pdoc; + pdf_article *article; + + if (article_id == NULL || strlen(article_id) == 0) + ERROR("Article thread without internal identifier."); + + if (p->articles.num_entries >= p->articles.max_entries) { + p->articles.max_entries += PDFDOC_ARTICLE_ALLOC_SIZE; + p->articles.entries = RENEW(p->articles.entries, + p->articles.max_entries, struct pdf_article); + } + article = &(p->articles.entries[p->articles.num_entries]); + + article->id = NEW(strlen(article_id)+1, char); + strcpy(article->id, article_id); + article->info = article_info; + article->num_beads = 0; + article->max_beads = 0; + article->beads = NULL; + + p->articles.num_entries++; + + return; +} + +#if 0 +void +pdf_doc_end_article (const char *article_id) +{ + return; /* no-op */ +} +#endif + +static pdf_bead * +find_bead (pdf_article *article, const char *bead_id) +{ + pdf_bead *bead; + long i; + + bead = NULL; + for (i = 0; i < article->num_beads; i++) { + if (!strcmp(article->beads[i].id, bead_id)) { + bead = &(article->beads[i]); + break; + } + } + + return bead; +} + +void +pdf_doc_add_bead (const char *article_id, + const char *bead_id, long page_no, const pdf_rect *rect) +{ + pdf_doc *p = &pdoc; + pdf_article *article; + pdf_bead *bead; + long i; + + if (!article_id) { + ERROR("No article identifier specified."); + } + + article = NULL; + for (i = 0; i < p->articles.num_entries; i++) { + if (!strcmp(p->articles.entries[i].id, article_id)) { + article = &(p->articles.entries[i]); + break; + } + } + if (!article) { + ERROR("Specified article thread that doesn't exist."); + return; + } + + bead = bead_id ? find_bead(article, bead_id) : NULL; + if (!bead) { + if (article->num_beads >= article->max_beads) { + article->max_beads += PDFDOC_BEAD_ALLOC_SIZE; + article->beads = RENEW(article->beads, + article->max_beads, struct pdf_bead); + for (i = article->num_beads; i < article->max_beads; i++) { + article->beads[i].id = NULL; + article->beads[i].page_no = -1; + } + } + bead = &(article->beads[article->num_beads]); + if (bead_id) { + bead->id = NEW(strlen(bead_id)+1, char); + strcpy(bead->id, bead_id); + } else { + bead->id = NULL; + } + article->num_beads++; + } + bead->rect.llx = rect->llx; + bead->rect.lly = rect->lly; + bead->rect.urx = rect->urx; + bead->rect.ury = rect->ury; + bead->page_no = page_no; + + return; +} + +static pdf_obj * +make_article (pdf_doc *p, + pdf_article *article, + const char **bead_ids, int num_beads, + pdf_obj *article_info) +{ + pdf_obj *art_dict; + pdf_obj *first, *prev, *last; + long i, n; + + if (!article) + return NULL; + + art_dict = pdf_new_dict(); + first = prev = last = NULL; + /* + * The bead_ids represents logical order of beads in an article thread. + * If bead_ids is not given, we create an article thread in the order of + * beads appeared. + */ + n = bead_ids ? num_beads : article->num_beads; + for (i = 0; i < n; i++) { + pdf_bead *bead; + + bead = bead_ids ? find_bead(article, bead_ids[i]) : &(article->beads[i]); + if (!bead || bead->page_no < 0) { + continue; + } + last = pdf_new_dict(); + if (prev == NULL) { + first = last; + pdf_add_dict(first, + pdf_new_name("T"), pdf_ref_obj(art_dict)); + } else { + pdf_add_dict(prev, + pdf_new_name("N"), pdf_ref_obj(last)); + pdf_add_dict(last, + pdf_new_name("V"), pdf_ref_obj(prev)); + /* We must link first to last. */ + if (prev != first) + pdf_release_obj(prev); + } + + /* Realize bead now. */ + { + pdf_page *page; + pdf_obj *rect; + + page = doc_get_page_entry(p, bead->page_no); + if (!page->beads) { + page->beads = pdf_new_array(); + } + pdf_add_dict(last, pdf_new_name("P"), pdf_link_obj(page->page_ref)); + rect = pdf_new_array(); + pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.llx, 0.01))); + pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.lly, 0.01))); + pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.urx, 0.01))); + pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.ury, 0.01))); + pdf_add_dict (last, pdf_new_name("R"), rect); + pdf_add_array(page->beads, pdf_ref_obj(last)); + } + + prev = last; + } + + if (first && last) { + pdf_add_dict(last, + pdf_new_name("N"), pdf_ref_obj(first)); + pdf_add_dict(first, + pdf_new_name("V"), pdf_ref_obj(last)); + if (first != last) { + pdf_release_obj(last); + } + pdf_add_dict(art_dict, + pdf_new_name("F"), pdf_ref_obj(first)); + /* If article_info is supplied, we override article->info. */ + if (article_info) { + pdf_add_dict(art_dict, + pdf_new_name("I"), article_info); + } else if (article->info) { + pdf_add_dict(art_dict, + pdf_new_name("I"), pdf_ref_obj(article->info)); + pdf_release_obj(article->info); + article->info = NULL; /* We do not write as object reference. */ + } + pdf_release_obj(first); + } else { + pdf_release_obj(art_dict); + art_dict = NULL; + } + + return art_dict; +} + +static void +clean_article (pdf_article *article) +{ + if (!article) + return; + + if (article->beads) { + long i; + + for (i = 0; i < article->num_beads; i++) { + if (article->beads[i].id) + RELEASE(article->beads[i].id); + } + RELEASE(article->beads); + article->beads = NULL; + } + + if (article->id) + RELEASE(article->id); + article->id = NULL; + article->num_beads = 0; + article->max_beads = 0; + + return; +} + +static void +pdf_doc_close_articles (pdf_doc *p) +{ + int i; + + for (i = 0; i < p->articles.num_entries; i++) { + pdf_article *article; + + article = &(p->articles.entries[i]); + if (article->beads) { + pdf_obj *art_dict; + + art_dict = make_article(p, article, NULL, 0, NULL); + if (!p->root.threads) { + p->root.threads = pdf_new_array(); + } + pdf_add_array(p->root.threads, pdf_ref_obj(art_dict)); + pdf_release_obj(art_dict); + } + clean_article(article); + } + RELEASE(p->articles.entries); + p->articles.entries = NULL; + p->articles.num_entries = 0; + p->articles.max_entries = 0; + + if (p->root.threads) { + pdf_add_dict(p->root.dict, + pdf_new_name("Threads"), + pdf_ref_obj (p->root.threads)); + pdf_release_obj(p->root.threads); + p->root.threads = NULL; + } + + return; +} + +/* page_no = 0 for root page tree node. */ +void +pdf_doc_set_mediabox (unsigned page_no, const pdf_rect *mediabox) +{ + pdf_doc *p = &pdoc; + pdf_page *page; + + if (page_no == 0) { + p->pages.mediabox.llx = mediabox->llx; + p->pages.mediabox.lly = mediabox->lly; + p->pages.mediabox.urx = mediabox->urx; + p->pages.mediabox.ury = mediabox->ury; + } else { + page = doc_get_page_entry(p, page_no); + page->cropbox.llx = mediabox->llx; + page->cropbox.lly = mediabox->lly; + page->cropbox.urx = mediabox->urx; + page->cropbox.ury = mediabox->ury; + page->flags |= USE_MY_MEDIABOX; + } + + return; +} + +void +pdf_doc_get_mediabox (unsigned page_no, pdf_rect *mediabox) +{ + pdf_doc *p = &pdoc; + pdf_page *page; + + if (page_no == 0) { + mediabox->llx = p->pages.mediabox.llx; + mediabox->lly = p->pages.mediabox.lly; + mediabox->urx = p->pages.mediabox.urx; + mediabox->ury = p->pages.mediabox.ury; + } else { + page = doc_get_page_entry(p, page_no); + if (page->flags & USE_MY_MEDIABOX) { + mediabox->llx = page->cropbox.llx; + mediabox->lly = page->cropbox.lly; + mediabox->urx = page->cropbox.urx; + mediabox->ury = page->cropbox.ury; + } else { + mediabox->llx = p->pages.mediabox.llx; + mediabox->lly = p->pages.mediabox.lly; + mediabox->urx = p->pages.mediabox.urx; + mediabox->ury = p->pages.mediabox.ury; + } + } + + return; +} + +pdf_obj * +pdf_doc_current_page_resources (void) +{ + pdf_obj *resources; + pdf_doc *p = &pdoc; + pdf_page *currentpage; + + if (p->pending_forms) { + if (p->pending_forms->form.resources) { + resources = p->pending_forms->form.resources; + } else { + resources = p->pending_forms->form.resources = pdf_new_dict(); + } + } else { + currentpage = LASTPAGE(p); + if (currentpage->resources) { + resources = currentpage->resources; + } else { + resources = currentpage->resources = pdf_new_dict(); + } + } + + return resources; +} + +pdf_obj * +pdf_doc_get_dictionary (const char *category) +{ + pdf_doc *p = &pdoc; + pdf_obj *dict = NULL; + + ASSERT(category); + + if (!strcmp(category, "Names")) { + if (!p->root.names) + p->root.names = pdf_new_dict(); + dict = p->root.names; + } else if (!strcmp(category, "Pages")) { + if (!p->root.pages) + p->root.pages = pdf_new_dict(); + dict = p->root.pages; + } else if (!strcmp(category, "Catalog")) { + if (!p->root.dict) + p->root.dict = pdf_new_dict(); + dict = p->root.dict; + } else if (!strcmp(category, "Info")) { + if (!p->info) + p->info = pdf_new_dict(); + dict = p->info; + } else if (!strcmp(category, "@THISPAGE")) { + /* Sorry for this... */ + pdf_page *currentpage; + + currentpage = LASTPAGE(p); + dict = currentpage->page_obj; + } + + if (!dict) { + ERROR("Document dict. \"%s\" not exist. ", category); + } + + return dict; +} + +long +pdf_doc_current_page_number (void) +{ + pdf_doc *p = &pdoc; + + return (long) (PAGECOUNT(p) + 1); +} + +pdf_obj * +pdf_doc_ref_page (unsigned long page_no) +{ + pdf_doc *p = &pdoc; + pdf_page *page; + + page = doc_get_page_entry(p, page_no); + if (!page->page_obj) { + page->page_obj = pdf_new_dict(); + page->page_ref = pdf_ref_obj(page->page_obj); + } + + return pdf_link_obj(page->page_ref); +} + +pdf_obj * +pdf_doc_get_reference (const char *category) +{ + pdf_obj *ref = NULL; + long page_no; + + ASSERT(category); + + page_no = pdf_doc_current_page_number(); + if (!strcmp(category, "@THISPAGE")) { + ref = pdf_doc_ref_page(page_no); + } else if (!strcmp(category, "@PREVPAGE")) { + if (page_no <= 1) { + ERROR("Reference to previous page, but no pages have been completed yet."); + } + ref = pdf_doc_ref_page(page_no - 1); + } else if (!strcmp(category, "@NEXTPAGE")) { + ref = pdf_doc_ref_page(page_no + 1); + } + + if (!ref) { + ERROR("Reference to \"%s\" not exist. ", category); + } + + return ref; +} + +static void +pdf_doc_new_page (pdf_doc *p) +{ + pdf_page *currentpage; + + if (PAGECOUNT(p) >= MAXPAGES(p)) { + doc_resize_page_entries(p, MAXPAGES(p) + PDFDOC_PAGES_ALLOC_SIZE); + } + + /* + * This is confusing. pdf_doc_finish_page() have increased page count! + */ + currentpage = LASTPAGE(p); + /* Was this page already instantiated by a forward reference to it? */ + if (!currentpage->page_ref) { + currentpage->page_obj = pdf_new_dict(); + currentpage->page_ref = pdf_ref_obj(currentpage->page_obj); + } + + currentpage->background = NULL; + currentpage->contents = pdf_new_stream(STREAM_COMPRESS); + currentpage->resources = pdf_new_dict(); + + currentpage->annots = NULL; + currentpage->beads = NULL; + + return; +} + +/* This only closes contents and resources. */ +static void +pdf_doc_finish_page (pdf_doc *p) +{ + pdf_page *currentpage; + + if (p->pending_forms) { + ERROR("A pending form XObject at the end of page."); + } + + currentpage = LASTPAGE(p); + if (!currentpage->page_obj) + currentpage->page_obj = pdf_new_dict(); + + /* + * Make Contents array. + */ + + /* + * Global BOP content stream. + * pdf_ref_obj() returns reference itself when the object is + * indirect reference, not reference to the indirect reference. + * We keep bop itself but not reference to it since it is + * expected to be small. + */ + if (p->pages.bop && + pdf_stream_length(p->pages.bop) > 0) { + currentpage->content_refs[0] = pdf_ref_obj(p->pages.bop); + } else { + currentpage->content_refs[0] = NULL; + } + /* + * Current page background content stream. + */ + if (currentpage->background) { + if (pdf_stream_length(currentpage->background) > 0) { + currentpage->content_refs[1] = pdf_ref_obj(currentpage->background); + pdf_add_stream (currentpage->background, "\n", 1); + } + pdf_release_obj(currentpage->background); + currentpage->background = NULL; + } else { + currentpage->content_refs[1] = NULL; + } + + /* Content body of current page */ + currentpage->content_refs[2] = pdf_ref_obj(currentpage->contents); + pdf_add_stream (currentpage->contents, "\n", 1); + pdf_release_obj(currentpage->contents); + currentpage->contents = NULL; + + /* + * Global EOP content stream. + */ + if (p->pages.eop && + pdf_stream_length(p->pages.eop) > 0) { + currentpage->content_refs[3] = pdf_ref_obj(p->pages.eop); + } else { + currentpage->content_refs[3] = NULL; + } + + /* + * Page resources. + */ + if (currentpage->resources) { + pdf_obj *procset; + /* + * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. + */ + + procset = pdf_new_array (); + pdf_add_array(procset, pdf_new_name("PDF")); + pdf_add_array(procset, pdf_new_name("Text")); + pdf_add_array(procset, pdf_new_name("ImageC")); + pdf_add_array(procset, pdf_new_name("ImageB")); + pdf_add_array(procset, pdf_new_name("ImageI")); + pdf_add_dict(currentpage->resources, pdf_new_name("ProcSet"), procset); + + pdf_add_dict(currentpage->page_obj, + pdf_new_name("Resources"), + pdf_ref_obj(currentpage->resources)); + pdf_release_obj(currentpage->resources); + currentpage->resources = NULL; + } + + if (manual_thumb_enabled) { + char *thumb_filename; + pdf_obj *thumb_ref; + + thumb_filename = NEW(strlen(thumb_basename)+7, char); + sprintf(thumb_filename, "%s.%ld", + thumb_basename, (p->pages.num_entries % 99999) + 1L); + thumb_ref = read_thumbnail(thumb_filename); + RELEASE(thumb_filename); + if (thumb_ref) + pdf_add_dict(currentpage->page_obj, pdf_new_name("Thumb"), thumb_ref); + } + + p->pages.num_entries++; + + return; +} + +static pdf_color bgcolor = { 1, { 1.0 } }; + +void +pdf_doc_set_bgcolor (const pdf_color *color) +{ + if (color) + pdf_color_copycolor(&bgcolor, color); + else { /* as clear... */ + pdf_color_white(&bgcolor); + } +} + +static void +doc_fill_page_background (pdf_doc *p) +{ + pdf_page *currentpage; + pdf_rect r; + int cm; + pdf_obj *saved_content; + + cm = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); + if (!cm || pdf_color_is_white(&bgcolor)) { + return; + } + + pdf_doc_get_mediabox(pdf_doc_current_page_number(), &r); + + currentpage = LASTPAGE(p); + ASSERT(currentpage); + + if (!currentpage->background) + currentpage->background = pdf_new_stream(STREAM_COMPRESS); + + saved_content = currentpage->contents; + currentpage->contents = currentpage->background; + + pdf_dev_gsave(); + pdf_dev_set_nonstrokingcolor(&bgcolor); + pdf_dev_rectfill(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); + pdf_dev_grestore(); + + currentpage->contents = saved_content; + + return; +} + +void +pdf_doc_begin_page (double scale, double x_origin, double y_origin) +{ + pdf_doc *p = &pdoc; + pdf_tmatrix M; + + M.a = scale; M.b = 0.0; + M.c = 0.0 ; M.d = scale; + M.e = x_origin; + M.f = y_origin; + + /* pdf_doc_new_page() allocates page content stream. */ + pdf_doc_new_page(p); + pdf_dev_bop(&M); + + return; +} + +void +pdf_doc_end_page (void) +{ + pdf_doc *p = &pdoc; + + pdf_dev_eop(); + doc_fill_page_background(p); + + pdf_doc_finish_page(p); + + return; +} + +void +pdf_doc_add_page_content (const char *buffer, unsigned length) +{ + pdf_doc *p = &pdoc; + pdf_page *currentpage; + + if (p->pending_forms) { + pdf_add_stream(p->pending_forms->form.contents, buffer, length); + } else { + currentpage = LASTPAGE(p); + pdf_add_stream(currentpage->contents, buffer, length); + } + + return; +} + +static char *doccreator = NULL; /* Ugh */ + +void +pdf_open_document (const char *filename, + int do_encryption, + double media_width, double media_height, + double annot_grow_amount, int bookmark_open_depth, + int check_gotos) +{ + pdf_doc *p = &pdoc; + + pdf_out_init(filename, do_encryption); + + pdf_doc_init_catalog(p); + + p->opt.annot_grow = annot_grow_amount; + p->opt.outline_open_depth = bookmark_open_depth; + + pdf_init_resources(); + pdf_init_colors(); + pdf_init_fonts(); + /* Thumbnail want this to be initialized... */ + pdf_init_images(); + + pdf_doc_init_docinfo(p); + if (doccreator) { + pdf_add_dict(p->info, + pdf_new_name("Creator"), + pdf_new_string(doccreator, strlen(doccreator))); + RELEASE(doccreator); doccreator = NULL; + } + + pdf_doc_init_bookmarks(p, bookmark_open_depth); + pdf_doc_init_articles (p); + pdf_doc_init_names (p, check_gotos); + pdf_doc_init_page_tree(p, media_width, media_height); + + pdf_doc_set_bgcolor(NULL); + + if (do_encryption) { + pdf_obj *encrypt = pdf_encrypt_obj(); + pdf_set_encrypt(encrypt); + pdf_release_obj(encrypt); + } + pdf_set_id(pdf_enc_id_array()); + + /* Create a default name for thumbnail image files */ + if (manual_thumb_enabled) { + if (strlen(filename) > 4 && + !strncmp(".pdf", filename + strlen(filename) - 4, 4)) { + thumb_basename = NEW(strlen(filename)-4+1, char); + strncpy(thumb_basename, filename, strlen(filename)-4); + thumb_basename[strlen(filename)-4] = 0; + } else { + thumb_basename = NEW(strlen(filename)+1, char); + strcpy(thumb_basename, filename); + } + } + + p->pending_forms = NULL; + + return; +} + +void +pdf_doc_set_creator (const char *creator) +{ + if (!creator || + creator[0] == '\0') + return; + + doccreator = NEW(strlen(creator)+1, char); + strcpy(doccreator, creator); /* Ugh */ +} + + +void +pdf_close_document (void) +{ + pdf_doc *p = &pdoc; + + /* + * Following things were kept around so user can add dictionary items. + */ + pdf_doc_close_articles (p); + pdf_doc_close_names (p); + pdf_doc_close_bookmarks(p); + pdf_doc_close_page_tree(p); + pdf_doc_close_docinfo (p); + + pdf_doc_close_catalog (p); + + pdf_close_images(); + pdf_close_fonts (); + pdf_close_colors(); + + pdf_close_resources(); /* Should be at last. */ + + pdf_out_flush(); + + if (thumb_basename) + RELEASE(thumb_basename); + + return; +} + +/* + * All this routine does is give the form a name and add a unity scaling matrix. + * It fills in required fields. The caller must initialize the stream. + */ +static void +pdf_doc_make_xform (pdf_obj *xform, + pdf_rect *bbox, + pdf_tmatrix *matrix, + pdf_obj *resources, + pdf_obj *attrib) +{ + pdf_obj *xform_dict; + pdf_obj *tmp; + + xform_dict = pdf_stream_dict(xform); + pdf_add_dict(xform_dict, + pdf_new_name("Type"), pdf_new_name("XObject")); + pdf_add_dict(xform_dict, + pdf_new_name("Subtype"), pdf_new_name("Form")); + pdf_add_dict(xform_dict, + pdf_new_name("FormType"), pdf_new_number(1.0)); + + if (!bbox) + ERROR("No BoundingBox supplied."); + + tmp = pdf_new_array(); + pdf_add_array(tmp, pdf_new_number(ROUND(bbox->llx, .001))); + pdf_add_array(tmp, pdf_new_number(ROUND(bbox->lly, .001))); + pdf_add_array(tmp, pdf_new_number(ROUND(bbox->urx, .001))); + pdf_add_array(tmp, pdf_new_number(ROUND(bbox->ury, .001))); + pdf_add_dict(xform_dict, pdf_new_name("BBox"), tmp); + + if (matrix) { + tmp = pdf_new_array(); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->a, .00001))); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->b, .00001))); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->c, .00001))); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->d, .00001))); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->e, .001 ))); + pdf_add_array(tmp, pdf_new_number(ROUND(matrix->f, .001 ))); + pdf_add_dict(xform_dict, pdf_new_name("Matrix"), tmp); + } + + if (attrib) { + pdf_merge_dict(xform_dict, attrib); + } + + pdf_add_dict(xform_dict, pdf_new_name("Resources"), resources); + + return; +} + +/* + * begin_form_xobj creates an xobject with its "origin" at + * xpos and ypos that is clipped to the specified bbox. Note + * that the origin is not the lower left corner of the bbox. + */ +int +pdf_doc_begin_grabbing (const char *ident, + double ref_x, double ref_y, const pdf_rect *cropbox) +{ + int xobj_id = -1; + pdf_doc *p = &pdoc; + pdf_form *form; + struct form_list_node *fnode; + xform_info info; + + pdf_dev_push_gstate(); + + fnode = NEW(1, struct form_list_node); + + fnode->prev = p->pending_forms; + fnode->q_depth = pdf_dev_current_depth(); + form = &fnode->form; + + /* + * The reference point of an Xobject is at the lower left corner + * of the bounding box. Since we would like to have an arbitrary + * reference point, we use a transformation matrix, translating + * the reference point to (0,0). + */ + + form->matrix.a = 1.0; form->matrix.b = 0.0; + form->matrix.c = 0.0; form->matrix.d = 1.0; + form->matrix.e = -ref_x; + form->matrix.f = -ref_y; + + form->cropbox.llx = ref_x + cropbox->llx; + form->cropbox.lly = ref_y + cropbox->lly; + form->cropbox.urx = ref_x + cropbox->urx; + form->cropbox.ury = ref_y + cropbox->ury; + + form->contents = pdf_new_stream(STREAM_COMPRESS); + form->resources = pdf_new_dict(); + + pdf_ximage_init_form_info(&info); + + info.matrix.a = 1.0; info.matrix.b = 0.0; + info.matrix.c = 0.0; info.matrix.d = 1.0; + info.matrix.e = -ref_x; + info.matrix.f = -ref_y; + + info.bbox.llx = cropbox->llx; + info.bbox.lly = cropbox->lly; + info.bbox.urx = cropbox->urx; + info.bbox.ury = cropbox->ury; + + /* Use reference since content itself isn't available yet. */ + xobj_id = pdf_ximage_defineresource(ident, + PDF_XOBJECT_TYPE_FORM, + &info, pdf_ref_obj(form->contents)); + + p->pending_forms = fnode; + + /* + * Make sure the object is self-contained by adding the + * current font and color to the object stream. + */ + pdf_dev_reset_fonts(); + pdf_dev_reset_color(1); /* force color operators to be added to stream */ + + return xobj_id; +} + +void +pdf_doc_end_grabbing (pdf_obj *attrib) +{ + pdf_form *form; + pdf_obj *procset; + pdf_doc *p = &pdoc; + struct form_list_node *fnode; + + if (!p->pending_forms) { + WARN("Tried to close a nonexistent form XOject."); + return; + } + + fnode = p->pending_forms; + form = &fnode->form; + + pdf_dev_grestore_to(fnode->q_depth); + + /* + * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. + */ + procset = pdf_new_array(); + pdf_add_array(procset, pdf_new_name("PDF")); + pdf_add_array(procset, pdf_new_name("Text")); + pdf_add_array(procset, pdf_new_name("ImageC")); + pdf_add_array(procset, pdf_new_name("ImageB")); + pdf_add_array(procset, pdf_new_name("ImageI")); + pdf_add_dict (form->resources, pdf_new_name("ProcSet"), procset); + + pdf_doc_make_xform(form->contents, + &form->cropbox, &form->matrix, + pdf_ref_obj(form->resources), attrib); + pdf_release_obj(form->resources); + pdf_release_obj(form->contents); + if (attrib) pdf_release_obj(attrib); + + p->pending_forms = fnode->prev; + + pdf_dev_pop_gstate(); + + pdf_dev_reset_fonts(); + pdf_dev_reset_color(0); + + RELEASE(fnode); + + return; +} + +static struct +{ + int dirty; + int broken; + pdf_obj *annot_dict; + pdf_rect rect; +} breaking_state = {0, 0, NULL, {0.0, 0.0, 0.0, 0.0}}; + +static void +reset_box (void) +{ + breaking_state.rect.llx = breaking_state.rect.lly = HUGE_VAL; + breaking_state.rect.urx = breaking_state.rect.ury = -HUGE_VAL; + breaking_state.dirty = 0; +} + +void +pdf_doc_begin_annot (pdf_obj *dict) +{ + breaking_state.annot_dict = dict; + breaking_state.broken = 0; + reset_box(); +} + +void +pdf_doc_end_annot (void) +{ + pdf_doc_break_annot(); + breaking_state.annot_dict = NULL; +} + +void +pdf_doc_break_annot (void) +{ + if (breaking_state.dirty) { + pdf_obj *annot_dict; + + /* Copy dict */ + annot_dict = pdf_new_dict(); + pdf_merge_dict(annot_dict, breaking_state.annot_dict); + pdf_doc_add_annot(pdf_doc_current_page_number(), &(breaking_state.rect), + annot_dict, !breaking_state.broken); + pdf_release_obj(annot_dict); + + breaking_state.broken = 1; + } + reset_box(); +} + +void +pdf_doc_expand_box (const pdf_rect *rect) +{ + breaking_state.rect.llx = MIN(breaking_state.rect.llx, rect->llx); + breaking_state.rect.lly = MIN(breaking_state.rect.lly, rect->lly); + breaking_state.rect.urx = MAX(breaking_state.rect.urx, rect->urx); + breaking_state.rect.ury = MAX(breaking_state.rect.ury, rect->ury); + breaking_state.dirty = 1; +} + +#if 0 +/* This should be number tree */ +void +pdf_doc_set_pagelabel (long pg_start, + const char *type, + const void *prefix, int prfx_len, long start) +{ + pdf_doc *p = &pdoc; + pdf_obj *label_dict; + + if (!p->root.pagelabels) + p->root.pagelabels = pdf_new_array(); + + label_dict = pdf_new_dict(); + if (!type || type[0] == '\0') /* Set back to default. */ + pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name("D")); + else { + if (type) + pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name(type)); + if (prefix && prfx_len > 0) + pdf_add_dict(label_dict, + pdf_new_name("P"), + pdf_new_string(prefix, prfx_len)); + if (start != 1) + pdf_add_dict(label_dict, + pdf_new_name("St"), pdf_new_number(start)); + } + + pdf_add_array(p->root.pagelabels, pdf_new_number(pg_start)); + pdf_add_array(p->root.pagelabels, label_dict); + + return; +} +#endif diff --git a/Build/source/texk/dvipdfm-x/pdfdraw.c b/Build/source/texk/dvipdfm-x/pdfdraw.c new file mode 100644 index 00000000000..57eb283a141 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfdraw.c @@ -0,0 +1,2022 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "system.h" +#include "error.h" +#include "mem.h" +#include "mfileio.h" +#include "dpxutil.h" +#include "numbers.h" + +#include "pdfdoc.h" +#include "pdfdev.h" +#include "pdfcolor.h" + +#include "pdfdraw.h" + +#if 1 +typedef void pdf_dev; +#endif + + +/* + * Numbers are rounding to 0-5 fractional digits + * in output routine. + */ +#define detM(M) ((M).a * (M).d - (M).b * (M).c) +#define detP(M) ((M)->a * (M)->d - (M)->b * (M)->c) + + +static /* __inline__ */ int +inversematrix (pdf_tmatrix *W, const pdf_tmatrix *M) +{ + double det; + + det = detP(M); + if (fabs(det) < 1.e-8) { +#if 1 + WARN("Inverting matrix with zero determinant..."); +#endif + return -1; /* result is undefined. */ + } + + W->a = (M->d) / det; W->b = -(M->b) / det; + 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); + + return 0; +} + +/* pdf_coord as vector */ +#define vecprd(v,w) ((v).x * (w).x + (v).y * (w).y) +#define vecrot(v,w) ((v).x * (w).y - (v).y * (w).x) +#define dsign(v) (((v) >= 0.0) ? 1.0 : -1.0) +/* acos => [0, pi] */ +#define vecang(v,w) ( \ + dsign(vecrot((v),(w))) * \ + acos(vecprd((v),(w)) / sqrt(vecprd((v),(v)) * vecprd((w),(w)))) \ +) + +static /* __inline__ */ int +pdf_coord__equal (const pdf_coord *p1, const pdf_coord *p2) +{ + if (fabs(p1->x - p2->x) < 1.e-7 && + fabs(p1->y - p2->y) < 1.e-7) + return 1; + return 0; +} +#define COORD_EQUAL(p,q) pdf_coord__equal((p),(q)) + +#if 0 +static int +pdf_coord__sort_compar_X (const void *pp1, const void *pp2) +{ + pdf_coord *p1 = (pdf_coord *)pp1; + pdf_coord *p2 = (pdf_coord *)pp2; + + if (pdf_coord__equal(p1, p2)) + return 0; + else + return (int) dsign(p1->x - p2->x); + + return 1; +} + +static int +pdf_coord__sort_compar_Y (const void *pp1, const void *pp2) +{ + pdf_coord *p1 = (pdf_coord *)pp1; + pdf_coord *p2 = (pdf_coord *)pp2; + + if (pdf_coord__equal(p1, p2)) + return 0; + else + return (int) dsign(p1->y - p2->y); + + return 1; +} +#endif + + +static /* __inline__ */ int +pdf_coord__transform (pdf_coord *p, const pdf_tmatrix *M) +{ + double x, y; + + x = p->x; y = p->y; + p->x = x * M->a + y * M->c + M->e; + p->y = x * M->b + y * M->d + M->f; + + return 0; +} + +#if 0 +static /* __inline__ */ int +pdf_coord__itransform (pdf_coord *p, const pdf_tmatrix *M) +{ + pdf_tmatrix W; + double x, y; + int error; + + error = inversematrix(&W, M); + if (error) + return error; + + x = p->x; y = p->y; + p->x = x * W.a + y * W.c + W.e; + p->y = x * W.b + y * W.d + W.f; + + return 0; +} +#endif + +static /* __inline__ */ int +pdf_coord__dtransform (pdf_coord *p, const pdf_tmatrix *M) +{ + double x, y; + + x = p->x; y = p->y; + p->x = x * M->a + y * M->c; + p->y = x * M->b + y * M->d; + + return 0; +} + +static /* __inline__ */ int +pdf_coord__idtransform (pdf_coord *p, const pdf_tmatrix *M) +{ + pdf_tmatrix W; + double x, y; + int error; + + error = inversematrix(&W, M); + if (error) + return error; + + x = p->x; y = p->y; + p->x = x * W.a + y * W.c; + p->y = x * W.b + y * W.d; + + return 0; +} + + +/* Modify M itself */ +void +pdf_invertmatrix (pdf_tmatrix *M) +{ + pdf_tmatrix W; + double det; + + ASSERT(M); + + det = detP(M); + if (fabs(det) < 1.e-8) { + WARN("Inverting matrix with zero determinant..."); + W.a = 1.0; W.c = 0.0; + W.b = 0.0; W.d = 1.0; + W.e = 0.0; W.f = 0.0; + } else { + W.a = (M->d) / det; W.b = -(M->b) / det; + 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); + + return; +} + + +typedef struct pa_elem_ +{ + int type; + pdf_coord p[3]; +} pa_elem; + +/* each subpath delimitted by moveto */ +struct pdf_path_ +{ + int num_paths; + int max_paths; + pa_elem *path; +}; + +static const struct { + char opchr; /* PDF operator char */ + int n_pts; /* number of *points* */ + const char *strkey; +} petypes[] = { +#define PE_TYPE__INVALID -1 +#define PE_TYPE__MOVETO 0 + {'m', 1, "moveto" }, +#define PE_TYPE__LINETO 1 + {'l', 1, "lineto" }, +#define PE_TYPE__CURVETO 2 + {'c', 3, "curveto" }, + /* no PS correspondence for v and y */ +#define PE_TYPE__CURVETO_V 3 + {'v', 2, "vcurveto"}, /* current point replicated */ +#define PE_TYPE__CURVETO_Y 4 + {'y', 2, "ycurveto"}, /* last point replicated */ +#define PE_TYPE__CLOSEPATH 5 + {'h', 0, "closepath"}, +#define PE_TYPE__TERMINATE 6 + {' ', 0, NULL} +}; + +#define PE_VALID(p) ((p) && \ + (p)->type > PE_TYPE__INVALID && (p)->type < PE_TYPE__TERMINATE) +#define PE_N_PTS(p) (PE_VALID((p)) ? petypes[(p)->type].n_pts : 0) +#define PE_OPCHR(p) (PE_VALID((p)) ? petypes[(p)->type].opchr : ' ') + +#define PA_LENGTH(pa) ((pa)->num_paths) + +#define GS_FLAG_CURRENTPOINT_SET (1 << 0) + + +static char fmt_buf[1024]; /* FIXME */ +#define FORMAT_BUFF_PTR(p) fmt_buf +#define FORMAT_BUFF_LEN(p) 1024 + +static void +init_a_path (pdf_path *p) +{ + ASSERT(p); + + p->num_paths = 0; + p->max_paths = 0; + p->path = NULL; + + return; +} + +static void +pdf_path__clearpath (pdf_path *p) +{ + ASSERT(p); + + p->num_paths = 0; + + return; +} + +static int +pdf_path__growpath (pdf_path *p, int max_pe) +{ + if (max_pe < p->max_paths) + return 0; + + p->max_paths = MAX(p->max_paths + 8, max_pe); + p->path = RENEW(p->path, p->max_paths, pa_elem); + + return 0; +} + +static void +clear_a_path (pdf_path *p) +{ + ASSERT(p); + + if (p->path) + RELEASE(p->path); + p->path = NULL; + p->num_paths = 0; + p->max_paths = 0; + + return; +} + +static int +pdf_path__copypath (pdf_path *p1, const pdf_path *p0) +{ + pa_elem *pe0, *pe1; + int i; + + pdf_path__growpath(p1, PA_LENGTH(p0)); + for (i = 0; i < PA_LENGTH(p0); i++) { + pe1 = &(p1->path[i]); + pe0 = &(p0->path[i]); + /* FIXME */ + pe1->type = pe0->type; + pe1->p[0].x = pe0->p[0].x; + pe1->p[0].y = pe0->p[0].y; + pe1->p[1].x = pe0->p[1].x; + pe1->p[1].y = pe0->p[1].y; + pe1->p[2].x = pe0->p[2].x; + pe1->p[2].y = pe0->p[2].y; + } + p1->num_paths = PA_LENGTH(p0); + + return 0; +} + + +/* start new subpath */ +static int +pdf_path__moveto (pdf_path *pa, + pdf_coord *cp, + const pdf_coord *p0) +{ + pa_elem *pe; + + pdf_path__growpath(pa, PA_LENGTH(pa) + 1); + if (PA_LENGTH(pa) > 0) { + pe = &pa->path[pa->num_paths-1]; + if (pe->type == PE_TYPE__MOVETO) { + pe->p[0].x = cp->x = p0->x; + pe->p[0].y = cp->y = p0->y; + return 0; + } + } + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x = p0->x; + pe->p[0].y = cp->y = p0->y; + + return 0; +} + +/* Do 'compression' of path while adding new path elements. + * Sequantial moveto command will be replaced with a + * single moveto. If cp is not equal to the last point in pa, + * then moveto is inserted (starting new subpath). + * FIXME: + * 'moveto' must be used to enforce starting new path. + * This affects how 'closepath' is treated. + */ +static pa_elem * +pdf_path__next_pe (pdf_path *pa, const pdf_coord *cp) +{ + pa_elem *pe; + + pdf_path__growpath(pa, PA_LENGTH(pa) + 2); + if (PA_LENGTH(pa) == 0) { + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + + return &pa->path[pa->num_paths++]; + } + + pe = &pa->path[pa->num_paths-1]; + switch (pe->type) { + case PE_TYPE__MOVETO: + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + break; + case PE_TYPE__LINETO: + if (!COORD_EQUAL(&pe->p[0], cp)) { + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + } + break; + case PE_TYPE__CURVETO: + if (!COORD_EQUAL(&pe->p[2], cp)) { + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + } + break; + case PE_TYPE__CURVETO_Y: + case PE_TYPE__CURVETO_V: + if (!COORD_EQUAL(&pe->p[1], cp)) { + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + } + break; + case PE_TYPE__CLOSEPATH: + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__MOVETO; + pe->p[0].x = cp->x; + pe->p[0].y = cp->y; + break; + } + + return &pa->path[pa->num_paths++]; +} + +static int +pdf_path__transform (pdf_path *pa, const pdf_tmatrix *M) +{ + pa_elem *pe; + int n = 0, i; + + ASSERT(pa && M); + + for (i = 0; i < PA_LENGTH(pa); i++) { + pe = &(pa->path[i]); + n = PE_N_PTS(pe); + while (n-- > 0) + pdf_coord__transform(&(pe->p[n]), M); + } + + return 0; +} + + +/* Path Construction */ +static int +pdf_path__lineto (pdf_path *pa, + pdf_coord *cp, + const pdf_coord *p0) +{ + pa_elem *pe; + + pe = pdf_path__next_pe(pa, cp); + pe->type = PE_TYPE__LINETO; + pe->p[0].x = cp->x = p0->x; + pe->p[0].y = cp->y = p0->y; + + return 0; +} + +static int +pdf_path__curveto (pdf_path *pa, + pdf_coord *cp, + const pdf_coord *p0, + const pdf_coord *p1, + const pdf_coord *p2 + ) +{ + pa_elem *pe; + + pe = pdf_path__next_pe(pa, cp); + if (COORD_EQUAL(cp, p0)) { + pe->type = PE_TYPE__CURVETO_V; + pe->p[0].x = p1->x; + pe->p[0].y = p1->y; + pe->p[1].x = cp->x = p2->x; + pe->p[1].y = cp->y = p2->y; + } else if (COORD_EQUAL(p1, p2)) { + pe->type = PE_TYPE__CURVETO_Y; + pe->p[0].x = p0->x; + pe->p[0].y = p0->y; + pe->p[1].x = cp->x = p1->x; + pe->p[1].y = cp->y = p1->y; + } else { + pe->type = PE_TYPE__CURVETO; + pe->p[0].x = p0->x; + pe->p[0].y = p0->y; + pe->p[1].x = p1->x; + pe->p[1].y = p1->y; + pe->p[2].x = cp->x = p2->x; + pe->p[2].y = cp->y = p2->y; + } + + return 0; +} + +#if 0 +#define QB_TWO_THIRD (2.0/3.0) +#define QB_ONE_THIRD (1.0/3.0) + +static int +pdf_path__curveto_QB (pdf_path *pa, + pdf_coord *cp, + const pdf_coord *p0, + const pdf_coord *p1 + ) +{ + pdf_coord q0, q1; + + q0.x = cp->x + QB_TWO_THIRD * (p0->x - cp->x); + q0.y = cp->y + QB_TWO_THIRD * (p0->y - cp->y); + q1.x = p0->x + QB_ONE_THIRD * (p1->x - p0->x); + q1.y = p0->y + QB_ONE_THIRD * (p1->y - p0->y); + /* q2 == p1 */ + + return pdf_path__curveto(pa, cp, &q0, &q1, p1); +} +#endif + + +/* This isn't specified as cp to somewhere. */ +static int +pdf_path__elliptarc (pdf_path *pa, + pdf_coord *cp, + const pdf_coord *ca, /* ellipsis center */ + double r_x, /* x radius */ + double r_y, /* y radius */ + double xar, /* x-axis-rotation (deg!) */ + double a_0, /* start angle */ + double a_1, /* stop angle */ + int a_d /* arc orientation */ + ) +{ + double b, b_x, b_y; + double d_a, q; + pdf_coord p0, p1, p2, p3; + pdf_coord e0, e1; + pdf_tmatrix T; + int n_c; /* number of segments */ + int i, error = 0; + + if (fabs(r_x) < 1.e-8 || + fabs(r_y) < 1.e-8) + return -1; + + if (a_d < 0) { + for ( ; a_1 > a_0; a_1 -= 360.0); + } else { + for ( ; a_1 < a_0; a_0 -= 360.0); + } + + d_a = a_1 - a_0; + for (n_c = 1; fabs(d_a) > 90.0 * n_c; n_c++); + d_a /= n_c; + if (fabs(d_a) < 1.e-8) + return -1; + + a_0 *= M_PI / 180.0; + a_1 *= M_PI / 180.0; + d_a *= M_PI / 180.0; + xar *= M_PI / 180.0; + T.a = cos(xar); T.c = -sin(xar); + T.b = -T.c ; T.d = T.a; + T.e = 0.0 ; T.f = 0.0; + + /* A parameter that controls cb-curve (off-curve) points */ + b = 4.0 * (1.0 - cos(.5 * d_a)) / (3.0 * sin(.5 * d_a)); + b_x = r_x * b; + b_y = r_y * b; + + p0.x = r_x * cos(a_0); + p0.y = r_y * sin(a_0); + pdf_coord__transform(&p0, &T); + p0.x += ca->x; p0.y += ca->y; + if (PA_LENGTH(pa) == 0) { + pdf_path__moveto(pa, cp, &p0); + } else if (!COORD_EQUAL(cp, &p0)) { + pdf_path__lineto(pa, cp, &p0); /* add line seg */ + } + for (i = 0; !error && i < n_c; i++) { + q = a_0 + i * d_a; + e0.x = cos(q); e0.y = sin(q); + e1.x = cos(q + d_a); e1.y = sin(q + d_a); + + /* Condition for tangent vector requirs + * d1 = p1 - p0 = f ( sin a, -cos a) + * d2 = p2 - p3 = g ( sin b, -cos b) + * and from symmetry + * g^2 = f^2 + */ + p0.x = r_x * e0.x; /* s.p. */ + p0.y = r_y * e0.y; + p3.x = r_x * e1.x; /* e.p. */ + p3.y = r_y * e1.y; + + p1.x = -b_x * e0.y; + p1.y = b_y * e0.x; + p2.x = b_x * e1.y; + p2.y = -b_y * e1.x; + + pdf_coord__transform(&p0, &T); + pdf_coord__transform(&p1, &T); + pdf_coord__transform(&p2, &T); + pdf_coord__transform(&p3, &T); + p0.x += ca->x; p0.y += ca->y; + p3.x += ca->x; p3.y += ca->y; + p1.x += p0.x ; p1.y += p0.y ; + p2.x += p3.x ; p2.y += p3.y ; + + error = pdf_path__curveto(pa, &p0, &p1, &p2, &p3); + cp->x = p3.x; cp->y = p3.y; + } + + return error; +} + +static int +pdf_path__closepath (pdf_path *pa, pdf_coord *cp /* no arg */) +{ + pa_elem *pe = NULL; + int i; + + /* search for start point of the last subpath */ + for (i = PA_LENGTH(pa) - 1; i >= 0; i--) { + pe = &pa->path[i]; + if (pe->type == PE_TYPE__MOVETO) + break; + } + + if (!pe || i < 0) + return -1; /* No path or no start point(!) */ + + cp->x = pe->p[0].x; + cp->y = pe->p[0].y; + + pdf_path__growpath(pa, PA_LENGTH(pa) + 1); + + /* NOTE: + * Manually closed path without closepath is not + * affected by linejoin. A path with coincidental + * starting and ending point is not the same as + * 'closed' path. + */ + pe = &pa->path[pa->num_paths++]; + pe->type = PE_TYPE__CLOSEPATH; + + return 0; +} + +/* + * x y width height re + * + * is equivalent to + * + * x y m + * (x + width) y l + * (x + width) (y + height) l + * x (y + height) l + * h + */ +/* Just for quick test */ +static /* __inline__ */ int +pdf_path__isarect (pdf_path *pa, + int f_ir /* fill-rule is ignorable */ + ) +{ + pa_elem *pe0, *pe1, *pe2, *pe3, *pe4; + + if (PA_LENGTH(pa) == 5) { + pe0 = &(pa->path[0]); + pe1 = &(pa->path[1]); + pe2 = &(pa->path[2]); + pe3 = &(pa->path[3]); + pe4 = &(pa->path[4]); + if (pe0->type == PE_TYPE__MOVETO && + pe1->type == PE_TYPE__LINETO && + pe2->type == PE_TYPE__LINETO && + pe3->type == PE_TYPE__LINETO && + pe4->type == PE_TYPE__CLOSEPATH) { + if (pe1->p[0].y - pe0->p[0].y == 0 && + pe2->p[0].x - pe1->p[0].x == 0 && + pe3->p[0].y - pe2->p[0].y == 0) { + if (pe1->p[0].x - pe0->p[0].x + == pe2->p[0].x - pe3->p[0].x) { + return 1; + } + /* Winding number is different but ignore it here. */ + } else if (f_ir && + pe1->p[0].x - pe0->p[0].x == 0 && + pe2->p[0].y - pe1->p[0].y == 0 && + pe3->p[0].x - pe2->p[0].x == 0) { + if (pe1->p[0].y - pe0->p[0].y + == pe2->p[0].y - pe3->p[0].y) { + return 1; + } + } + } + } + + return 0; +} + +/* Path Painting */ +/* F is obsoleted */ +#define PT_OP_VALID(c) ( \ + (c) == 'f' || (c) == 'F' || \ + (c) == 's' || (c) == 'S' || \ + (c) == 'b' || (c) == 'B' || \ + (c) == 'W' || (c) == ' ' \ +) + +static /* __inline__ */ int +INVERTIBLE_MATRIX (const pdf_tmatrix *M) +{ + if (fabs(detP(M)) < 1.e-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; + } + return 0; +} + +/* rectfill, rectstroke, rectclip, recteoclip + * + * Draw isolated rectangle without actually doing + * gsave/grestore operation. + * + * TODO: + * linestyle, fill-opacity, stroke-opacity,.... + * As this routine draw a single graphics object + * each time, there should be options for specifying + * various drawing styles, which might inherite + * current graphcs state parameter. + */ +static int +pdf_dev__rectshape (pdf_dev *P, + const pdf_rect *r, + const pdf_tmatrix *M, + char opchr + ) +{ + char *buf = FORMAT_BUFF_PTR(P); + int len = 0; + int isclip = 0; + pdf_coord p; + double wd, ht; + + ASSERT(r && PT_OP_VALID(opchr)); + + isclip = (opchr == 'W' || opchr == ' ') ? 1 : 0; + + /* disallow matrix for clipping. + * q ... clip Q does nothing and + * n M cm ... clip n alter CTM. + */ + if (M && (isclip || + !INVERTIBLE_MATRIX(M))) + return -1; + + graphics_mode(); + + buf[len++] = ' '; + if (!isclip) { + buf[len++] = 'q'; + if (M) { + buf[len++] = ' '; + len += pdf_sprint_matrix(buf + len, M); + buf[len++] = ' '; + buf[len++] = 'c'; buf[len++] = 'm'; + } + buf[len++] = ' '; + } + buf[len++] = 'n'; + + p.x = r->llx; p.y = r->lly; + wd = r->urx - r->llx; + ht = r->ury - r->lly; + buf[len++] = ' '; + len += pdf_sprint_coord (buf + len, &p); + buf[len++] = ' '; + len += pdf_sprint_length(buf + len, wd); + buf[len++] = ' '; + len += pdf_sprint_length(buf + len, ht); + buf[len++] = ' '; + buf[len++] = 'r'; buf[len++] = 'e'; + + if (opchr != ' ') { + buf[len++] = ' '; + buf[len++] = opchr; + + buf[len++] = ' '; + buf[len++] = isclip ? 'n' : 'Q'; + } + + pdf_doc_add_page_content(buf, len); /* op: q cm n re Q */ + + return 0; +} + +static int path_added = 0; + +/* FIXME */ +static int +pdf_dev__flushpath (pdf_dev *P, + pdf_path *pa, + char opchr, + int rule, + int ignore_rule) +{ + pa_elem *pe, *pe1; + char *b = FORMAT_BUFF_PTR(P); + long b_len = FORMAT_BUFF_LEN(P); + pdf_rect r; /* FIXME */ + pdf_coord *pt; + int n_pts, n_seg; + int len = 0; + int isclip = 0; + int isrect, i, j; + + ASSERT(pa && PT_OP_VALID(opchr)); + + 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) { + pe = &(pa->path[0]); + pe1 = &(pa->path[2]); + + r.llx = pe->p[0].x; + r.lly = pe->p[0].y; + r.urx = pe1->p[0].x - pe->p[0].x; /* width... */ + r.ury = pe1->p[0].y - pe->p[0].y; /* height... */ + + b[len++] = ' '; + len += pdf_sprint_rect(b + len, &r); + b[len++] = ' '; + b[len++] = 'r'; + b[len++] = 'e'; + pdf_doc_add_page_content(b, len); /* op: re */ + len = 0; + } else { + n_seg = PA_LENGTH(pa); + for (i = 0, len = 0, pe = &pa->path[0]; + i < n_seg; pe++, i++) { + n_pts = PE_N_PTS(pe); + for (j = 0, pt = &pe->p[0]; + j < n_pts; j++, pt++) { + b[len++] = ' '; + len += pdf_sprint_coord(b + len, pt); + } + b[len++] = ' '; + b[len++] = PE_OPCHR(pe); + if (len + 128 > b_len) { + pdf_doc_add_page_content(b, len); /* op: m l c v y h */ + len = 0; + } + } + if (len > 0) { + pdf_doc_add_page_content(b, len); /* op: m l c v y h */ + len = 0; + } + } + + b[len++] = ' '; + 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); /* op: f F s S b B W f* F* s* S* b* B* W* */ + + return 0; +} + + +/* Graphics State */ +typedef struct pdf_gstate_ +{ + pdf_coord cp; + + pdf_tmatrix matrix; /* cm, - */ + + pdf_color strokecolor; + pdf_color fillcolor; + /* colorspace here */ + + struct { + int num_dash; + double pattern[PDF_DASH_SIZE_MAX]; + double offset; + } linedash; /* d, D */ + + double linewidth; /* w, LW */ + + int linecap; /* J, LC */ + int linejoin; /* j, LJ */ + double miterlimit; /* M, ML */ + + int flatness; /* i, FL, 0 to 100 (0 for use device-default) */ + + /* internal */ + pdf_path path; + long flags; + /* bookkeeping the origin of the last transform applied */ + pdf_coord pt_fixee; +} pdf_gstate; + + +typedef struct m_stack_elem +{ + void *data; + struct m_stack_elem *prev; +} m_stack_elem; + +typedef struct m_stack +{ + int size; + m_stack_elem *top; + m_stack_elem *bottom; +} m_stack; + +static void +m_stack_init (m_stack *stack) +{ + ASSERT(stack); + + stack->size = 0; + stack->top = NULL; + stack->bottom = NULL; + + return; +} + +static void +m_stack_push (m_stack *stack, void *data) +{ + m_stack_elem *elem; + + ASSERT(stack); + + elem = NEW(1, m_stack_elem); + elem->prev = stack->top; + elem->data = data; + + stack->top = elem; + if (stack->size == 0) + stack->bottom = elem; + + stack->size++; + + return; +} + +static void * +m_stack_pop (m_stack *stack) +{ + m_stack_elem *elem; + void *data; + + ASSERT(stack); + + if (stack->size == 0) + return NULL; + + data = stack->top->data; + elem = stack->top; + stack->top = elem->prev; + if (stack->size == 1) + stack->bottom = NULL; + RELEASE(elem); + + stack->size--; + + return data; +} + +static void * +m_stack_top (m_stack *stack) +{ + void *data; + + ASSERT(stack); + + if (stack->size == 0) + return NULL; + + data = stack->top->data; + + return data; +} + +#define m_stack_depth(s) ((s)->size) + +static m_stack gs_stack; + +static void +init_a_gstate (pdf_gstate *gs) +{ + gs->cp.x = 0.0; + gs->cp.y = 0.0; + + pdf_setmatrix(&gs->matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); + + pdf_color_black(&gs->strokecolor); + pdf_color_black(&gs->fillcolor); + + gs->linedash.num_dash = 0; + gs->linedash.offset = 0; + gs->linecap = 0; + gs->linejoin = 0; + gs->linewidth = 1.0; + gs->miterlimit = 10.0; + + gs->flatness = 1; /* default to 1 in PDF */ + + /* Internal variables */ + gs->flags = 0; + init_a_path(&gs->path); + gs->pt_fixee.x = 0; + gs->pt_fixee.y = 0; + + return; +} + +static void +clear_a_gstate (pdf_gstate *gs) +{ + clear_a_path(&gs->path); + memset(gs, 0, sizeof(pdf_gstate)); + + return; +} + +static void +copy_a_gstate (pdf_gstate *gs1, pdf_gstate *gs2) +{ + int i; + + ASSERT(gs1 && gs2); + + gs1->cp.x = gs2->cp.x; + gs1->cp.y = gs2->cp.y; + + pdf_copymatrix(&gs1->matrix, &gs2->matrix); + + /* TODO: + * Path should be linked list and gsave only + * record starting point within path rather than + * copying whole path. + */ + pdf_path__copypath(&gs1->path, &gs2->path); + + gs1->linedash.num_dash = gs2->linedash.num_dash; + for (i = 0; i < gs2->linedash.num_dash; i++) { + gs1->linedash.pattern[i] = gs2->linedash.pattern[i]; + } + gs1->linedash.offset = gs2->linedash.offset; + + gs1->linecap = gs2->linecap; + gs1->linejoin = gs2->linejoin; + gs1->linewidth = gs2->linewidth; + gs1->miterlimit = gs2->miterlimit; + gs1->flatness = gs2->flatness; + + 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; +} + +void +pdf_dev_init_gstates (void) +{ + pdf_gstate *gs; + + m_stack_init(&gs_stack); + + gs = NEW(1, pdf_gstate); + init_a_gstate(gs); + + m_stack_push(&gs_stack, gs); /* Initial state */ + + return; +} + +void +pdf_dev_clear_gstates (void) +{ + pdf_gstate *gs; + + 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(&gs_stack)) != NULL) { + clear_a_gstate(gs); + RELEASE(gs); + } + return; +} + +int +pdf_dev_gsave (void) +{ + pdf_gstate *gs0, *gs1; + + gs0 = m_stack_top(&gs_stack); + gs1 = NEW(1, pdf_gstate); + init_a_gstate(gs1); + copy_a_gstate(gs1, gs0); + m_stack_push(&gs_stack, gs1); + + pdf_doc_add_page_content(" q", 2); /* op: q */ + + return 0; +} + +int +pdf_dev_grestore (void) +{ + pdf_gstate *gs; + + if (m_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ + WARN("Too many grestores."); + return -1; + } + + gs = m_stack_pop(&gs_stack); + clear_a_gstate(gs); + RELEASE(gs); + + pdf_doc_add_page_content(" Q", 2); /* op: Q */ + + pdf_dev_reset_fonts(); + + return 0; +} + + +int +pdf_dev_push_gstate (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs0; + + gs0 = NEW(1, pdf_gstate); + + init_a_gstate(gs0); + + m_stack_push(gss, gs0); + + return 0; +} + + +int +pdf_dev_pop_gstate (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs; + + if (m_stack_depth(gss) <= 1) { /* Initial state at bottom */ + WARN("Too many grestores."); + return -1; + } + + gs = m_stack_pop(gss); + clear_a_gstate(gs); + RELEASE(gs); + + return 0; +} + + +int +pdf_dev_current_depth (void) +{ + return (m_stack_depth(&gs_stack) - 1); /* 0 means initial state */ +} + +void +pdf_dev_grestore_to (int depth) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs; + + ASSERT(depth >= 0); + + if (m_stack_depth(gss) > depth + 1) { + WARN("Closing pending transformations at end of page/XObject."); + } + + while (m_stack_depth(gss) > depth + 1) { + pdf_doc_add_page_content(" Q", 2); /* op: Q */ + gs = m_stack_pop(gss); + clear_a_gstate(gs); + RELEASE(gs); + } + pdf_dev_reset_fonts(); + + return; +} + +int +pdf_dev_currentpoint (pdf_coord *p) +{ + m_stack *gss = &gs_stack; + 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 = &gs_stack; + 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) +{ + 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 */ + +#ifdef XETEX +#define FORMAT_BUF_SIZE 4096 +static char format_buffer[FORMAT_BUF_SIZE]; + +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; +} +#else +/* + * mask == 0 means stroking color, mask == 0x20 nonstroking color + * + * force == 1 means that operators will be generated even if + * the color is the same as the current graphics state color + */ +void +pdf_dev_set_color (const pdf_color *color, char mask, int force) +{ + int len; + + pdf_gstate *gs = m_stack_top(&gs_stack); + pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; + + ASSERT(pdf_color_is_valid(color)); + + if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && + (force || pdf_color_compare(color, current)))) + /* If "color" is already the current color, then do nothing + * unless a color operator is forced + */ + return; + + graphics_mode(); + len = pdf_color_to_string(color, fmt_buf); + fmt_buf[len++] = ' '; + switch (pdf_color_type(color)) { + case PDF_COLORSPACE_TYPE_RGB: + fmt_buf[len++] = 'R' | mask; + fmt_buf[len++] = 'G' | mask; + break; + case PDF_COLORSPACE_TYPE_CMYK: + fmt_buf[len++] = 'K' | mask; + break; + case PDF_COLORSPACE_TYPE_GRAY: + fmt_buf[len++] = 'G' | mask; + break; + default: /* already verified the given color */ + break; + } + pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g */ + + pdf_color_copycolor(current, color); +} +#endif + +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 = {0, 0, 0, 0, 0, 0}; /* Init to avoid compiler warning */ + 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); /* op: cm */ + + pdf_concatmatrix(CTM, M); + } + inversematrix(&W, M); + + pdf_path__transform (cpa, &W); + pdf_coord__transform(cpt, &W); + + return 0; +} + +/* + * num w LW linewidth (g.t. 0) + * int J LC linecap + * int j LJ linejoin + * num M ML miter limit (g.t. 0) + * array num d D line dash + * int ri RI renderint intnet + * int i FL flatness tolerance (0-100) + * name gs -- name: res. name of ExtGState dict. + */ +int +pdf_dev_setmiterlimit (double mlimit) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + + if (gs->miterlimit != mlimit) { + buf[len++] = ' '; + len += pdf_sprint_length(buf + len, mlimit); + buf[len++] = ' '; + buf[len++] = 'M'; + pdf_doc_add_page_content(buf, len); /* op: M */ + gs->miterlimit = mlimit; + } + + return 0; +} + +int +pdf_dev_setlinecap (int capstyle) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + + if (gs->linecap != capstyle) { + len = sprintf(buf, " %d J", capstyle); + pdf_doc_add_page_content(buf, len); /* op: J */ + gs->linecap = capstyle; + } + + return 0; +} + +int +pdf_dev_setlinejoin (int joinstyle) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + + if (gs->linejoin != joinstyle) { + len = sprintf(buf, " %d j", joinstyle); + pdf_doc_add_page_content(buf, len); /* op: j */ + gs->linejoin = joinstyle; + } + + return 0; +} + +int +pdf_dev_setlinewidth (double width) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + + if (gs->linewidth != width) { + buf[len++] = ' '; + len += pdf_sprint_length(buf + len, width); + buf[len++] = ' '; + buf[len++] = 'w'; + pdf_doc_add_page_content(buf, len); /* op: w */ + gs->linewidth = width; + } + + return 0; +} + +int +pdf_dev_setdash (int count, double *pattern, double offset) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + int i; + + gs->linedash.num_dash = count; + gs->linedash.offset = offset; + pdf_doc_add_page_content(" [", 2); /* op: */ + for (i = 0; i < count; i++) { + buf[0] = ' '; + len = pdf_sprint_length (buf + 1, pattern[i]); + pdf_doc_add_page_content(buf, len + 1); /* op: */ + gs->linedash.pattern[i] = pattern[i]; + } + pdf_doc_add_page_content("] ", 2); /* op: */ + len = pdf_sprint_length (buf, offset); + pdf_doc_add_page_content(buf, len); /* op: */ + pdf_doc_add_page_content(" d", 2); /* op: d */ + + return 0; +} + +#if 0 +int +pdf_dev_setflat (int flatness) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + int len = 0; + char *buf = FORMAT_BUFF_PTR(NULL); + + if (flatness < 0 || flatness > 100) + return -1; + + if (gs->flatness != flatness) { + gs->flatness = flatness; + len = sprintf(buf, " %d i", flatness); + pdf_doc_add_page_content(buf, len); /* op: i */ + } + + return 0; +} +#endif + +/* ZSYUEDVEDEOF */ +int +pdf_dev_clip (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + + return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_NONZERO, 0); +} + +int +pdf_dev_eoclip (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + + return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_EVENODD, 0); +} + +int +pdf_dev_flushpath (char p_op, int fill_rule) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + int error = 0; + + /* last arg 'ignore_rule' is only for single object + * that can be converted to a rect where fill rule + * is inessential. + */ + error = pdf_dev__flushpath(NULL, cpa, p_op, fill_rule, 1); + pdf_path__clearpath(cpa); + + gs->flags &= ~GS_FLAG_CURRENTPOINT_SET; + + return error; +} + +int +pdf_dev_newpath (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *p = &gs->path; + + if (PA_LENGTH(p) > 0) { + pdf_path__clearpath (p); + } + /* The following is required for "newpath" operator in mpost.c. */ + pdf_doc_add_page_content(" n", 2); /* op: n */ + + return 0; +} + +int +pdf_dev_moveto (double x, double y) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord p; + + p.x = x; p.y = y; + return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ +} + +int +pdf_dev_rmoveto (double x, double y) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord p; + + p.x = cpt->x + x; + p.y = cpt->y + y; + return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ +} + +int +pdf_dev_lineto (double x, double y) +{ + 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; + + p0.x = x; p0.y = y; + + return pdf_path__lineto(cpa, cpt, &p0); +} + +int +pdf_dev_rlineto (double x, double y) +{ + 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; + + p0.x = x + cpt->x; p0.y = y + cpt->y; + + return pdf_path__lineto(cpa, cpt, &p0); +} + +int +pdf_dev_curveto (double x0, double y0, + double x1, double y1, + double x2, double y2) +{ + 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, p2; + + p0.x = x0; p0.y = y0; + p1.x = x1; p1.y = y1; + p2.x = x2; p2.y = y2; + + return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); +} + +#ifdef XETEX +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); +} +#endif + +int +pdf_dev_rcurveto (double x0, double y0, + double x1, double y1, + double x2, double y2) +{ + 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, p2; + + p0.x = x0 + cpt->x; p0.y = y0 + cpt->y; + p1.x = x1 + cpt->x; p1.y = y1 + cpt->y; + p2.x = x2 + cpt->x; p2.y = y2 + cpt->y; + + return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); +} + + +int +pdf_dev_closepath (void) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_coord *cpt = &gs->cp; + pdf_path *cpa = &gs->path; + + return pdf_path__closepath(cpa, cpt); +} + + +void +pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_tmatrix *CTM = &gs->matrix; + + ASSERT(p); + + pdf_coord__dtransform(p, (M ? M : CTM)); + + return; +} + +void +pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_tmatrix *CTM = &gs->matrix; + + ASSERT(p); + + pdf_coord__idtransform(p, (M ? M : CTM)); + + return; +} + +void +pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_tmatrix *CTM = &gs->matrix; + + ASSERT(p); + + pdf_coord__transform(p, (M ? M : CTM)); + + return; +} + +#if 0 +void +pdf_dev_itransform (pdf_coord *p, const pdf_tmatrix *M) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_tmatrix *CTM = &gs->matrix; + + ASSERT(p); + + pdf_coord__itransform(p, (M ? M : CTM)); + + return; +} +#endif + +int +pdf_dev_arc (double c_x , double c_y, double r, + double a_0 , double a_1) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord c; + + c.x = c_x; c.y = c_y; + + return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, +1); +} + +/* *negative* arc */ +int +pdf_dev_arcn (double c_x , double c_y, double r, + double a_0 , double a_1) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord c; + + c.x = c_x; c.y = c_y; + + return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, -1); +} + +int +pdf_dev_arcx (double c_x , double c_y, + double r_x , double r_y, + double a_0 , double a_1, + int a_d , + double xar) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord c; + + c.x = c_x; c.y = c_y; + + return pdf_path__elliptarc(cpa, cpt, &c, r_x, r_y, xar, a_0, a_1, a_d); +} + +/* Required by Tpic */ +int +pdf_dev_bspline (double x0, double y0, + double x1, double y1, double x2, double y2) +{ + m_stack *gss = &gs_stack; + pdf_gstate *gs = m_stack_top(gss); + pdf_path *cpa = &gs->path; + pdf_coord *cpt = &gs->cp; + pdf_coord p1, p2, p3; + + p1.x = x0 + 2.0 * (x1 - x0) / 3.0; + p1.y = y0 + 2.0 * (y1 - y0) / 3.0; + p2.x = x1 + (x2 - x1) / 3.0; + p2.y = y1 + (y2 - y1) / 3.0; + p3.x = x2; + p3.y = y2; + + return pdf_path__curveto(cpa, cpt, &p1, &p2, &p3); +} + +#if 0 +int +pdf_dev_rectstroke (double x, double y, + double w, double h, + const pdf_tmatrix *M /* optional */ + ) +{ + pdf_rect r; + + r.llx = x; + r.lly = y; + r.urx = x + w; + r.ury = y + h; + + return pdf_dev__rectshape(NULL, &r, M, 'S'); +} +#endif + +int +pdf_dev_rectfill (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; + + return pdf_dev__rectshape(NULL, &r, NULL, 'f'); +} + +int +pdf_dev_rectclip (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; + + 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/dvipdfm-x/pdfdraw.h b/Build/source/texk/dvipdfm-x/pdfdraw.h index 5849428bdb6..b3399ed8c69 100644 --- a/Build/source/texk/dvipdfm-x/pdfdraw.h +++ b/Build/source/texk/dvipdfm-x/pdfdraw.h @@ -171,11 +171,14 @@ extern int pdf_dev_currentcolor (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); -#ifndef XETEX +#ifdef XETEX +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); +#else extern void pdf_dev_set_color (const pdf_color *color, char mask, int force); #define pdf_dev_set_strokingcolor(c) pdf_dev_set_color(c, 0, 0); #define pdf_dev_set_nonstrokingcolor(c) pdf_dev_set_color(c, 0x20, 0); -extern void pdf_dev_reset_color (int force); #endif #endif /* _PDF_DRAW_H_ */ diff --git a/Build/source/texk/dvipdfm-x/pdfnames.c b/Build/source/texk/dvipdfm-x/pdfnames.c new file mode 100644 index 00000000000..894382a2591 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfnames.c @@ -0,0 +1,584 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "numbers.h" + +/* Hash */ +#include "dpxutil.h" + +#include "pdfobj.h" + +#include "pdfnames.h" + +#include "dvipdfmx.h" + +struct obj_data +{ + pdf_obj *object; + pdf_obj *object_ref; + int reserve; /* 1 if object is not actually defined. */ + int closed; /* 1 if object is closed */ +}; + +char * +printable_key (const char *key, int keylen) +{ +#define MAX_KEY 32 + static char pkey[MAX_KEY+4]; + int i, len; + unsigned char hi, lo; + + for (i = 0, len = 0; + i < keylen && len < MAX_KEY; i++) { + if (isprint(key[i])) { + pkey[len++] = key[i]; + } else { + hi = (key[i] >> 4) & 0xff; + lo = key[i] & 0xff; + pkey[len++] = '#'; + pkey[len++] = (hi < 10) ? hi + '0' : (hi - 10) + 'A'; + pkey[len++] = (lo < 10) ? lo + '0' : (lo - 10) + 'A'; + } + } + pkey[len] = '\0'; + + return (char *) pkey; +} + +static void CDECL +hval_free (void *hval) +{ + struct obj_data *value; + + value = (struct obj_data *) hval; + + if (value->object) { + pdf_release_obj(value->object); + value->object = NULL; + } + if (value->object_ref) { + pdf_release_obj(value->object_ref); + value->object_ref = NULL; + } + value->reserve = 0; + value->closed = 0; + + RELEASE(value); + + return; +} + +struct ht_table * +pdf_new_name_tree (void) +{ + struct ht_table *names; + + names = NEW(1, struct ht_table); + ht_init_table(names, hval_free); + + return names; +} + +#ifdef XETEX +static void +flush_objects (struct ht_table *ht_tab) +{ + struct ht_iter iter; + + if (ht_set_iter(ht_tab, &iter) >= 0) { + do { + char *key; + int keylen; + struct obj_data *value; + + key = ht_iter_getkey(&iter, &keylen); + value = ht_iter_getval(&iter); + if (value->reserve) { + WARN("Unresolved object reference \"%s\" found!!!", + printable_key(key, keylen)); + } + if (value->object) { + pdf_release_obj(value->object); + } + if (value->object_ref) { + pdf_release_obj(value->object_ref); + } + value->object = NULL; + value->object_ref = NULL; + value->reserve = 0; + } while (ht_iter_next(&iter) >= 0); + ht_clear_iter(&iter); + } +} +#else +static void +check_objects_defined (struct ht_table *ht_tab) +{ + struct ht_iter iter; + + if (ht_set_iter(ht_tab, &iter) >= 0) { + do { + char *key; + int keylen; + struct obj_data *value; + + key = ht_iter_getkey(&iter, &keylen); + value = ht_iter_getval(&iter); + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + pdf_names_add_object(ht_tab, key, keylen, pdf_new_null()); + WARN("Object @%s used, but not defined. Replaced by null.", + printable_key(key, keylen)); + } + } while (ht_iter_next(&iter) >= 0); + ht_clear_iter(&iter); + } +} +#endif + +void +pdf_delete_name_tree (struct ht_table **names) +{ + ASSERT(names && *names); + +#ifdef XETEX + flush_objects (*names); +#else + check_objects_defined(*names); +#endif + + ht_clear_table(*names); + RELEASE(*names); + *names = NULL; +} + +int +pdf_names_add_object (struct ht_table *names, + const void *key, int keylen, pdf_obj *object) +{ + struct obj_data *value; + + ASSERT(names && object); + + if (!key || keylen < 1) { + WARN("Null string used for name tree key."); + return -1; + } + + value = ht_lookup_table(names, key, keylen); + if (!value) { + value = NEW(1, struct obj_data); + value->object = object; + value->object_ref = NULL; + value->reserve = 0; + value->closed = 0; + ht_append_table(names, key, keylen, value); + } else { +#ifdef XETEX + if (value->reserve) { + /* null object is used for undefined objects */ + pdf_copy_object(value->object, object); + pdf_release_obj(object); /* PLEASE FIX THIS!!! */ +#else + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + pdf_transfer_label(object, value->object); + pdf_release_obj(value->object); + value->object = object; +#endif + } else { +#ifdef XETEX + if (value->object || value->object_ref) { + if (pdf_obj_get_verbose()) { + WARN("Object reference with key \"%s\" is in use.", printable_key(key, keylen)); + } + pdf_release_obj(object); + return -1; + } else { + value->object = object; + } +#else + WARN("Object @%s already defined.", printable_key(key, keylen)); + pdf_release_obj(object); + return -1; +#endif + } + value->reserve = 0; + } + + return 0; +} + +#ifdef XETEX +int +pdf_names_add_reference (struct ht_table *names, + const void *key, int keylen, pdf_obj *object_ref) +{ + struct obj_data *value; + + ASSERT(names); + + if (!PDF_OBJ_INDIRECTTYPE(object_ref)) { + WARN("Invalid type: @%s is not reference...", + printable_key(key, keylen)); + return -1; + } + + value = ht_lookup_table(names, key, keylen); + if (!value) { + value = NEW(1, struct obj_data); + value->object = NULL; + value->object_ref = object_ref; + value->reserve = 0; + ht_append_table(names, key, keylen, value); + } else { + if (value->object || value->object_ref) { + WARN("Object reference \"%s\" is in use.", + printable_key(key, keylen)); + WARN("Please close it before redefining."); + return -1; + } else { + value->object = NULL; + value->object_ref = object_ref; + } + value->reserve = 0; + } + + return 0; +} +#endif + +/* + * The following routine returns copies, not the original object. + */ +pdf_obj * +pdf_names_lookup_reference (struct ht_table *names, + const void *key, int keylen) +{ + struct obj_data *value; +#ifndef XETEX + pdf_obj *object; +#endif + + ASSERT(names); + + value = ht_lookup_table(names, key, keylen); + +#ifdef XETEX + if (!value) { + /* Reserve object label */ + value = NEW(1, struct obj_data); + value->object = pdf_new_null(); /* dummy */ + value->object_ref = NULL; + value->reserve = 1; + ht_append_table(names, key, keylen, value); + } + + if (!value->object_ref) { + if (value->object) + value->object_ref = pdf_ref_obj(value->object); + else { + WARN("Object @%s not defined or already closed.", + printable_key(key, keylen)); + } + } + + return pdf_link_obj(value->object_ref); +#else + if (value) { + object = value->object; + } else { + /* A null object as dummy would create problems because as value + * of a dictionary entry, a null object is be equivalent to no entry + * at all. This matters for optimization of PDF destinations. + */ + object = pdf_new_undefined(); + pdf_names_add_object(names, key, keylen, object); + } + + return pdf_ref_obj(object); +#endif +} + +pdf_obj * +pdf_names_lookup_object (struct ht_table *names, + const void *key, int keylen) +{ + struct obj_data *value; + + ASSERT(names); + + value = ht_lookup_table(names, key, keylen); + if (!value || PDF_OBJ_UNDEFINED(value->object)) + return NULL; + if (!value->object) + ERROR("Object @%s not defined or already closed.", + printable_key(key, keylen)); + + return value->object; +} + +int +pdf_names_close_object (struct ht_table *names, + const void *key, int keylen) +{ + struct obj_data *value; + + ASSERT(names); + + value = ht_lookup_table(names, key, keylen); + if (!value) { + WARN("Tried to release nonexistent reference: %s", + printable_key(key, keylen)); + return -1; + } + if (PDF_OBJ_UNDEFINED(value->object) ) { + WARN("Cannot close undefined object @%s.", printable_key(key, keylen)); + return -1; + } + if (!value->object || value->closed) { + WARN("Object @%s already closed.", printable_key(key, keylen)); + return -1; + } + + pdf_release_obj(value->object); + value->object = NULL; + value->closed = 1; + + return 0; +} + +struct named_object +{ + char *key; + int keylen; + pdf_obj *value; +}; + +static int CDECL +cmp_key (const void *d1, const void *d2) +{ + const struct named_object *sd1, *sd2; + int keylen, cmp; + + sd1 = (const struct named_object *) d1; + sd2 = (const struct named_object *) d2; + + if (!sd1->key) + cmp = -1; + else if (!sd2->key) + cmp = 1; + else { + keylen = MIN(sd1->keylen, sd2->keylen); + cmp = memcmp(sd1->key, sd2->key, keylen); + if (!cmp) { + cmp = sd1->keylen - sd2->keylen; + } + } + + return cmp; +} + +#define NAME_CLUSTER 4 +static pdf_obj * +build_name_tree (struct named_object *first, long num_leaves, int is_root) +{ + pdf_obj *result; + int i; + + result = pdf_new_dict(); + /* + * According to PDF Refrence, Third Edition (p.101-102), a name tree + * always has exactly one root node, which contains a SINGLE entry: + * either Kids or Names but not both. If the root node has a Names + * entry, it is the only node in the tree. If it has a Kids entry, + * then each of the remaining nodes is either an intermediate node, + * containing a Limits entry and a Kids entry, or a leaf node, + * containing a Limits entry and a Names entry. + */ + if (!is_root) { + struct named_object *last; + pdf_obj *limits; + + limits = pdf_new_array(); + last = &first[num_leaves - 1]; + pdf_add_array(limits, pdf_new_string(first->key, first->keylen)); + pdf_add_array(limits, pdf_new_string(last->key , last->keylen )); + pdf_add_dict (result, pdf_new_name("Limits"), limits); + } + + if (num_leaves > 0 && + num_leaves <= 2 * NAME_CLUSTER) { + pdf_obj *names; + + /* Create leaf nodes. */ + names = pdf_new_array(); + for (i = 0; i < num_leaves; i++) { + struct named_object *cur; + + cur = &first[i]; + pdf_add_array(names, pdf_new_string(cur->key, cur->keylen)); + switch (PDF_OBJ_TYPEOF(cur->value)) { + case PDF_ARRAY: + case PDF_DICT: + case PDF_STREAM: + case PDF_STRING: + pdf_add_array(names, pdf_ref_obj(cur->value)); + break; + case PDF_OBJ_INVALID: + ERROR("Invalid object...: %s", printable_key(cur->key, cur->keylen)); + default: + pdf_add_array(names, pdf_link_obj(cur->value)); + break; + } + pdf_release_obj(cur->value); + cur->value = NULL; + } + pdf_add_dict(result, pdf_new_name("Names"), names); + } else if (num_leaves > 0) { + pdf_obj *kids; + + /* Intermediate node */ + kids = pdf_new_array(); + for (i = 0; i < NAME_CLUSTER; i++) { + pdf_obj *subtree; + long start, end; + + start = (i*num_leaves) / NAME_CLUSTER; + end = ((i+1)*num_leaves) / NAME_CLUSTER; + subtree = build_name_tree(&first[start], (end - start), 0); + pdf_add_array (kids, pdf_ref_obj(subtree)); + pdf_release_obj(subtree); + } + pdf_add_dict(result, pdf_new_name("Kids"), kids); + } + + return result; +} + +static struct named_object * +flat_table (struct ht_table *ht_tab, long *num_entries, + struct ht_table *filter) +{ + struct named_object *objects; + struct ht_iter iter; + long count; + + ASSERT(ht_tab); + + objects = NEW(ht_tab->count, struct named_object); + count = 0; + if (ht_set_iter(ht_tab, &iter) >= 0) { + do { + char *key; + int keylen; + struct obj_data *value; + + key = ht_iter_getkey(&iter, &keylen); + + if (filter) { + pdf_obj *new_obj = ht_lookup_table(filter, key, keylen); + + if (!new_obj) + continue; + + key = pdf_string_value(new_obj); + keylen = pdf_string_length(new_obj); + } + + value = ht_iter_getval(&iter); +#ifdef XETEX + if (value->reserve) { + WARN("Named object \"%s\" not defined!!!", +#else + ASSERT(value->object); + if (PDF_OBJ_UNDEFINED(value->object)) { + WARN("Object @%s\" not defined!!!", +#endif + printable_key(key, keylen)); + WARN("Replacing with null."); + objects[count].key = (char *) key; + objects[count].keylen = keylen; + objects[count].value = pdf_new_null(); + } else if (value->object_ref) { + objects[count].key = (char *) key; + objects[count].keylen = keylen; + objects[count].value = pdf_link_obj(value->object_ref); + } else if (value->object) { + objects[count].key = (char *) key; + objects[count].keylen = keylen; + objects[count].value = pdf_link_obj(value->object); +#ifdef XETEX + } else { + WARN("Named object \"%s\" not defined!!!", + printable_key(key, keylen)); + WARN("Replacing with null."); + objects[count].key = (char *) key; + objects[count].keylen = keylen; + objects[count].value = pdf_new_null(); +#endif + } + } while (ht_iter_next(&iter) >= 0); + ht_clear_iter(&iter); + } + + *num_entries = count; + objects = RENEW(objects, count, struct named_object); + + return objects; +} + +pdf_obj * +pdf_names_create_tree (struct ht_table *names, long *count, + struct ht_table *filter) +{ + pdf_obj *name_tree; + struct named_object *flat; + + flat = flat_table(names, count, filter); + if (!flat) + name_tree = NULL; + else { + if (is_xetex && *count < 1) + name_tree = NULL; + else { + qsort(flat, *count, sizeof(struct named_object), cmp_key); + name_tree = build_name_tree(flat, *count, 1); + } + RELEASE(flat); + } + + return name_tree; +} diff --git a/Build/source/texk/dvipdfm-x/pdfobj.c b/Build/source/texk/dvipdfm-x/pdfobj.c new file mode 100644 index 00000000000..81537f699f2 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfobj.c @@ -0,0 +1,3294 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" +#include "dpxutil.h" +#include "pdflimits.h" +#include "pdfencrypt.h" +#include "pdfparse.h" + +#ifdef HAVE_ZLIB +#include +#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 +{ + int type; + + unsigned long label; /* Only used for indirect objects + 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; +}; + +struct pdf_boolean +{ + char value; +}; + +struct pdf_number +{ + double value; +}; + +struct pdf_string +{ + unsigned char *string; + unsigned short length; +}; + +struct pdf_name +{ + char *name; +}; + +struct pdf_array +{ + unsigned long max; + unsigned long size; + struct pdf_obj **values; +}; + +struct pdf_dict +{ + struct pdf_obj *key; + struct pdf_obj *value; + struct pdf_dict *next; +}; + +struct pdf_stream +{ + struct pdf_obj *dict; + unsigned char *stream; + long *objstm_data; /* used for object streams */ + unsigned long stream_length; + unsigned long max_length; + unsigned char _flags; +}; + +struct pdf_indirect +{ + pdf_file *pf; + unsigned long label; + unsigned short generation; +}; + +typedef void pdf_null; +typedef struct pdf_boolean pdf_boolean; +typedef struct pdf_number pdf_number; +typedef struct pdf_string pdf_string; +typedef struct pdf_name pdf_name; +typedef struct pdf_array pdf_array; +typedef struct pdf_dict pdf_dict; +typedef struct pdf_stream pdf_stream; +typedef struct pdf_indirect pdf_indirect; + +static FILE *pdf_output_file = NULL; + +static long pdf_output_file_position = 0; +static long pdf_output_line_position = 0; +static long compression_saved = 0; + +#define FORMAT_BUF_SIZE 4096 +static char format_buffer[FORMAT_BUF_SIZE]; + +typedef struct xref_entry +{ + unsigned char type; /* object storage type */ + unsigned long field2; /* offset in file or object stream */ + unsigned short field3; /* generation or index */ + pdf_obj *direct; /* used for imported objects */ + pdf_obj *indirect; /* used for imported objects */ +} xref_entry; + +static xref_entry *output_xref; + +static unsigned long pdf_max_ind_objects; +static unsigned long next_label; + +static unsigned long startxref; + +struct pdf_file +{ + FILE *file; + pdf_obj *trailer; + xref_entry *xref_table; + pdf_obj *catalog; + long num_obj; + long file_size; + int version; +}; + +static pdf_obj *output_stream; + +#define OBJSTM_MAX_OBJS 200 +/* the limit is only 100 for linearized PDF */ + +static int enc_mode; +static int doc_enc_mode; + +static pdf_obj *trailer_dict; +static pdf_obj *xref_stream; + +/* Internal static routines */ + +static int check_for_pdf_version (FILE *file); + +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 set_objstm_data (pdf_obj *objstm, long *data); +static long *get_objstm_data (pdf_obj *objstm); +static void release_objstm (pdf_obj *objstm); + +static void pdf_out_char (FILE *file, char c); +static void pdf_out (FILE *file, const void *buffer, long length); + +static void release_indirect (pdf_indirect *data); +static void write_indirect (pdf_indirect *indirect, FILE *file); + +static void release_boolean (pdf_obj *data); +static void write_boolean (pdf_boolean *data, FILE *file); + +static void release_null (pdf_null *data); +static void write_null (pdf_null *data, FILE *file); + +static void release_number (pdf_number *number); +static void write_number (pdf_number *number, FILE *file); + +static void write_string (pdf_string *str, FILE *file); +static void release_string (pdf_string *str); + +static void write_name (pdf_name *name, FILE *file); +static void release_name (pdf_name *name); + +static void write_array (pdf_array *array, FILE *file); +static void release_array (pdf_array *array); + +static void write_dict (pdf_dict *dict, FILE *file); +static void release_dict (pdf_dict *dict); + +static void write_stream (pdf_stream *stream, FILE *file); +static void release_stream (pdf_stream *stream); + +static int verbose = 0; +static char compression_level = 9; + +void +pdf_set_compression (int level) +{ +#ifndef HAVE_ZLIB + ERROR("You don't have compression compiled in. Possibly libz wasn't found by configure."); +#else +#ifndef HAVE_ZLIB_COMPRESS2 + if (level != 0) + WARN("Unable to set compression level -- your zlib doesn't have compress2()."); +#endif + if (level >= 0 && level <= 9) + compression_level = level; + else { + ERROR("set_compression: invalid compression level: %d", level); + } +#endif /* !HAVE_ZLIB */ + + return; +} + +static unsigned pdf_version = PDF_VERSION_DEFAULT; + +void +pdf_set_version (unsigned version) +{ + /* Don't forget to update CIDFont_stdcc_def[] in cid.c too! */ + if (version >= PDF_VERSION_MIN && version <= PDF_VERSION_MAX) { + pdf_version = version; + } +} + +unsigned +pdf_get_version (void) +{ + return pdf_version; +} + +int +pdf_obj_get_verbose(void) +{ + return verbose; +} + +void +pdf_obj_set_verbose(void) +{ + verbose++; +} + +static pdf_obj *current_objstm = NULL; +static int do_objstm; + +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, xref_entry); + } + + output_xref[label].type = type; + output_xref[label].field2 = field2; + output_xref[label].field3 = field3; + output_xref[label].direct = NULL; + output_xref[label].indirect = NULL; +} + +#define BINARY_MARKER "%\344\360\355\370\n" +void +pdf_out_init (const char *filename, int do_encryption) +{ + char v; + + 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")); + do_objstm = 1; + } else { + xref_stream = NULL; + trailer_dict = pdf_new_dict(); + do_objstm = 0; + } + + output_stream = NULL; + +#ifdef XETEX + if (filename == NULL) { /* no filename: writing to stdout */ +#ifdef WIN32 + setmode(fileno(stdout), _O_BINARY); +#endif + pdf_output_file = stdout; + } else +#endif + { + pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE); + if (!pdf_output_file) { + if (strlen(filename) < 128) + ERROR("Unable to open \"%s\".", filename); + else + ERROR("Unable to open file."); + } + } + pdf_out(pdf_output_file, "%PDF-1.", strlen("%PDF-1.")); + v = '0' + pdf_version; + 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_table (void) +{ + long length; + unsigned long i; + + 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); + + /* + * 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. + */ + 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); + } +} + +static void +dump_trailer_dict (void) +{ + pdf_out(pdf_output_file, "trailer\n", 8); + enc_mode = 0; + write_dict(trailer_dict->data, pdf_output_file); + pdf_release_obj(trailer_dict); + pdf_out_char(pdf_output_file, '\n'); +} + +/* + * 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; + + /* 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; + unsigned short f3; + buf[0] = output_xref[i].type; + pos = output_xref[i].field2; + for (j = poslen; j--; ) { + buf[1+j] = (unsigned char) pos; + pos >>= 8; + } + 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_release_obj(xref_stream); +} + +void +pdf_out_flush (void) +{ + if (pdf_output_file) { + long length; + + /* Flush current object stream */ + if (current_objstm) { + release_objstm(current_objstm); + current_objstm =NULL; + } + + /* + * Label xref stream - we need the number of correct objects + * for the xref stream dictionary (= trailer). + * Labelling it in pdf_out_init (with 1) does not work (why?). + */ + if (xref_stream) + pdf_label_obj(xref_stream); + + /* 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 (xref_stream) + 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 saved %ld bytes%s\n", compression_saved, + pdf_version < 5 ? ". Try \"-V 5\" for better compression" : ""); + } + } + MESG("%ld bytes written", pdf_output_file_position); + + MFCLOSE(pdf_output_file); + } +} + +void +pdf_error_cleanup (void) +{ + /* + * This routine is the cleanup required for an abnormal exit. + * For now, simply close the file. + */ + if (pdf_output_file) + MFCLOSE(pdf_output_file); +} + + +void +pdf_set_root (pdf_obj *object) +{ + if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) { + ERROR("Root object already set!"); + } + /* 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_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) { + ERROR ("Info object already set!"); + } +} + +void +pdf_set_id (pdf_obj *id) +{ + if (pdf_add_dict(trailer_dict, pdf_new_name("ID"), id)) { + ERROR ("ID already set!"); + } +} + +void +pdf_set_encrypt (pdf_obj *encrypt) +{ + if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) { + ERROR("Encrypt object already set!"); + } + encrypt->flags |= OBJ_NO_ENCRYPT; +} + +static +void pdf_out_char (FILE *file, char c) +{ + 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; + } + } +} + +static char xchar[] = "0123456789abcdef"; + +#define pdf_out_xchar(f,c) do {\ + pdf_out_char((f), xchar[((c) >> 4) & 0x0f]);\ + pdf_out_char((f), xchar[(c) & 0x0f]);\ +} while (0) + +static +void pdf_out (FILE *file, const void *buffer, long length) +{ + 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 && + ((const char *)buffer)[length-1] == '\n') + 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) +{ + if (file == pdf_output_file && pdf_output_line_position >= 80) { + pdf_out_char(file, '\n'); + } else { + pdf_out_char(file, ' '); + } +} + +#define TYPECHECK(o,t) if (!(o) || (o)->type != (t)) {\ + ERROR("typecheck: Invalid object type: %d %d (line %d)", (o) ? (o)->type : -1, (t), __LINE__);\ +} + +#define INVALIDOBJ(o) ((o) == NULL || (o)->type <= 0 || (o)->type > PDF_UNDEFINED) + +static pdf_obj * +pdf_new_obj(int type) +{ + pdf_obj *result; + + if (type >= PDF_UNDEFINED || type < 0) + ERROR("Invalid object type: %d", type); + + result = NEW(1, pdf_obj); + result->type = type; + result->data = NULL; + result->label = 0; + result->generation = 0; + result->refcount = 1; + result->flags = 0; + + return result; +} + +int +pdf_obj_typeof (pdf_obj *object) +{ + if (INVALIDOBJ(object)) + return PDF_OBJ_INVALID; + + return object->type; +} + +static void +pdf_label_obj (pdf_obj *object) +{ + if (INVALIDOBJ(object)) + ERROR("pdf_label_obj(): passed invalid object."); + + /* + * Don't change label on an already labeled object. Ignore such calls. + */ + if (object->label == 0) { + object->label = next_label++; + object->generation = 0; + } +} + +#ifndef XETEX +/* + * Transfer the label assigned to the object src to the object dst. + * The object dst must not yet have been labeled. + */ +void +pdf_transfer_label (pdf_obj *dst, pdf_obj *src) +{ + ASSERT(dst && !dst->label && src); + + dst->label = src->label; + dst->generation = src->generation; + src->label = 0; + src->generation = 0; +} +#endif + +/* + * This doesn't really copy the object, but allows it to be used without + * fear that somebody else will free it. + */ +pdf_obj * +pdf_link_obj (pdf_obj *object) +{ + if (INVALIDOBJ(object)) + ERROR("pdf_link_obj(): passed invalid object."); + + object->refcount += 1; + + return object; +} + + +pdf_obj * +pdf_ref_obj (pdf_obj *object) +{ + if (INVALIDOBJ(object)) + ERROR("pdf_ref_obj(): passed invalid object."); + + if (object->refcount == 0) { + MESG("\nTrying to refer already released object!!!\n"); + pdf_write_obj(object, stderr); + ERROR("Cannot continue..."); + } + + if (PDF_OBJ_INDIRECTTYPE(object)) { + return pdf_link_obj(object); + } else { + if (object->label == 0) { + pdf_label_obj(object); + } + return pdf_new_indirect(NULL, object->label, object->generation); + } +} + +static void +release_indirect (pdf_indirect *data) +{ + RELEASE(data); +} + +static void +write_indirect (pdf_indirect *indirect, FILE *file) +{ + long length; + + ASSERT(!indirect->pf); + + length = sprintf(format_buffer, "%lu %hu R", indirect->label, indirect->generation); + pdf_out(file, format_buffer, length); +} + +#ifndef XETEX +/* The undefined object is used as a placeholder in pdfnames.c + * for objects which are referenced before they are defined. + */ +pdf_obj * +pdf_new_undefined (void) +{ + pdf_obj *result; + + result = pdf_new_obj(PDF_UNDEFINED); + result->data = NULL; + + return result; +} +#endif + +pdf_obj * +pdf_new_null (void) +{ + pdf_obj *result; + + result = pdf_new_obj(PDF_NULL); + result->data = NULL; + + return result; +} + +static void +release_null (pdf_null *obj) +{ + return; +} + +static void +write_null (pdf_null *obj, FILE *file) +{ + pdf_out(file, "null", 4); +} + +pdf_obj * +pdf_new_boolean (char value) +{ + pdf_obj *result; + pdf_boolean *data; + + result = pdf_new_obj(PDF_BOOLEAN); + data = NEW(1, pdf_boolean); + data->value = value; + result->data = data; + + return result; +} + +static void +release_boolean (pdf_obj *data) +{ + RELEASE (data); +} + +static void +write_boolean (pdf_boolean *data, FILE *file) +{ + if (data->value) { + pdf_out(file, "true", 4); + } else { + pdf_out(file, "false", 5); + } +} + +#ifdef XETEX +void +pdf_set_boolean (pdf_obj *object, char value) +{ + pdf_boolean *data; + + TYPECHECK(object, PDF_BOOLEAN); + + data = object->data; + data->value = value; +} +#endif + +char +pdf_boolean_value (pdf_obj *object) +{ + pdf_boolean *data; + + TYPECHECK(object, PDF_BOOLEAN); + + data = object->data; + + return data->value; +} + +pdf_obj * +pdf_new_number (double value) +{ + pdf_obj *result; + pdf_number *data; + + result = pdf_new_obj(PDF_NUMBER); + data = NEW(1, pdf_number); + data->value = value; + result->data = data; + + return result; +} + +static void +release_number (pdf_number *data) +{ + RELEASE (data); +} + +static void +write_number (pdf_number *number, FILE *file) +{ + int count; + + count = pdf_sprint_number(format_buffer, number->value); + + pdf_out(file, format_buffer, count); +} + + +void +pdf_set_number (pdf_obj *object, double value) +{ + pdf_number *data; + + TYPECHECK(object, PDF_NUMBER); + + data = object->data; + data->value = value; +} + +double +pdf_number_value (pdf_obj *object) +{ + pdf_number *data; + + TYPECHECK(object, PDF_NUMBER); + + data = object->data; + + return data->value; +} + +pdf_obj * +pdf_new_string (const void *str, unsigned length) +{ + pdf_obj *result; + pdf_string *data; + + ASSERT(str); + + result = pdf_new_obj(PDF_STRING); + data = NEW(1, pdf_string); + result->data = data; + data->length = length; + + if (length) { + data->string = NEW(length+1, unsigned char); + memcpy(data->string, str, length); + /* Shouldn't assume NULL terminated. */ + data->string[length] = '\0'; + } else + data->string = NULL; + + return result; +} + +void * +pdf_string_value (pdf_obj *object) +{ + pdf_string *data; + + TYPECHECK(object, PDF_STRING); + + data = object->data; + + return data->string; +} + +unsigned +pdf_string_length (pdf_obj *object) +{ + pdf_string *data; + + TYPECHECK(object, PDF_STRING); + + data = object->data; + + return (unsigned) (data->length); +} + +/* + * This routine escapes non printable characters and control + * characters in an output string. + */ +int +pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len) +{ + int result = 0; + int i; + + for (i = 0; i < len; i++) { + unsigned char ch; + + ch = s[i]; + if (result > bufsize - 4) + ERROR("pdfobj_escape_str: Buffer overflow"); + + /* + * We always write three octal digits. Optimization only gives few Kb + * smaller size for most documents when zlib compressed. + */ + if (ch < 32 || ch > 126) { + buffer[result++] = '\\'; +#if 0 + if (i < len - 1 && !isdigit(s[i+1])) + result += sprintf(buffer+result, "%o", ch); + else + result += sprintf(buffer+result, "%03o", ch); +#endif + result += sprintf(buffer+result, "%03o", ch); + } else { + switch (ch) { + case '(': + buffer[result++] = '\\'; + buffer[result++] = '('; + break; + case ')': + buffer[result++] = '\\'; + buffer[result++] = ')'; + break; + case '\\': + buffer[result++] = '\\'; + buffer[result++] = '\\'; + break; + default: + buffer[result++] = ch; + break; + } + } + } + + return result; +} + +static void +write_string (pdf_string *str, FILE *file) +{ + unsigned char *s; + char wbuf[FORMAT_BUF_SIZE]; /* Shouldn't use format_buffer[]. */ + int nescc = 0, i, count; + + s = str->string; + + if (enc_mode) + pdf_encrypt_data(s, str->length); + + /* + * Count all ASCII non-printable characters. + */ + for (i = 0; i < str->length; i++) { + if (!isprint(s[i])) + nescc++; + } + /* + * If the string contains much escaped chars, then we write it as + * ASCII hex string. + */ + if (nescc > str->length / 3) { + pdf_out_char(file, '<'); + for (i = 0; i < str->length; i++) { + pdf_out_xchar(file, s[i]); + } + pdf_out_char(file, '>'); + } else { + pdf_out_char(file, '('); + /* + * This section of code probably isn't speed critical. Escaping the + * characters in the string one at a time may seem slow, but it's + * safe if the formatted string length exceeds FORMAT_BUF_SIZE. + * Occasionally you see some long strings in PDF. pdfobj_escape_str + * is also used for strings of text with no kerning. These must be + * handled as quickly as possible since there are so many of them. + */ + for (i = 0; i < str->length; i++) { + count = pdfobj_escape_str(wbuf, FORMAT_BUF_SIZE, &(s[i]), 1); + pdf_out(file, wbuf, count); + } + pdf_out_char(file, ')'); + } +} + +static void +release_string (pdf_string *data) +{ + if (data->string != NULL) { + RELEASE(data->string); + data->string = NULL; + } + RELEASE(data); +} + +void +pdf_set_string (pdf_obj *object, unsigned char *str, unsigned length) +{ + pdf_string *data; + + TYPECHECK(object, PDF_STRING); + + data = object->data; + if (data->string != 0) { + RELEASE(data->string); + } + if (length != 0) { + data->length = length; + data->string = NEW(length + 1, unsigned char); + memcpy(data->string, str, length); + data->string[length] = '\0'; + } else { + data->length = 0; + data->string = NULL; + } +} + +/* Name does *not* include the /. */ +pdf_obj * +pdf_new_name (const char *name) +{ + pdf_obj *result; + unsigned length; + pdf_name *data; + + result = pdf_new_obj(PDF_NAME); + data = NEW (1, pdf_name); + result->data = data; + length = strlen(name); + if (length != 0) { + data->name = NEW(length+1, char); + memcpy(data->name, name, length); + data->name[length] = '\0'; + } else { + data->name = NULL; + } + + return result; +} + +static void +write_name (pdf_name *name, FILE *file) +{ + char *s; + int i, length; + + s = name->name; + length = name->name ? strlen(name->name) : 0; + /* + * From PDF Reference, 3rd ed., p.33: + * + * Beginning with PDF 1.2, any character except null (character code 0) + * may be included in a name by writing its 2-digit hexadecimal code, + * preceded bythe number sign character (#); see implementation notes 3 + * and 4 in Appendix H. This syntax is required in order to represent + * any of the delimiter or white-space characters or the number sign + * character itself; it is recommended but not required for characters + * whose codes are outside the range 33 (!) to 126 (~). + */ +#ifndef is_delim + /* Avoid '{' and '}' for PostScript compatibility? */ +#define is_delim(c) ((c) == '(' || (c) == '/' || \ + (c) == '<' || (c) == '>' || \ + (c) == '[' || (c) == ']' || \ + (c) == '{' || (c) == '}' || \ + (c) == '%') +#endif + pdf_out_char(file, '/'); + for (i = 0; i < length; i++) { + if (s[i] < '!' || s[i] > '~' || s[i] == '#' || is_delim(s[i])) { + /* ^ "space" is here. */ + pdf_out_char (file, '#'); + pdf_out_xchar(file, s[i]); + } else { + pdf_out_char (file, s[i]); + } + } +} + +static void +release_name (pdf_name *data) +{ + if (data->name != NULL) { + RELEASE(data->name); + data->name = NULL; + } + RELEASE(data); +} + +#ifdef XETEX +void +pdf_set_name (pdf_obj *object, const char *name) +{ + pdf_name *data; + unsigned length; + + TYPECHECK(object, PDF_NAME); + + length = strlen(name); + data = object->data; + if (data->name != NULL) { + RELEASE(data->name); + } + if (length != 0) { + data->name = NEW(length+1, char); + memcpy(data->name, name, length); + data->name[length] = 0; + } else { + data->name = NULL; + } +} +#endif + +char * +pdf_name_value (pdf_obj *object) +{ + pdf_name *data; + + TYPECHECK(object, PDF_NAME); + + data = object->data; + + return data->name; +} + +/* + * We do not have pdf_name_length() since '\0' is not allowed + * in PDF name object. + */ + +pdf_obj * +pdf_new_array (void) +{ + pdf_obj *result; + pdf_array *data; + + result = pdf_new_obj(PDF_ARRAY); + data = NEW(1, pdf_array); + data->values = NULL; + data->max = 0; + data->size = 0; + result->data = data; + + return result; +} + +static void +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 (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_out_char(file, ']'); +} + +pdf_obj * +pdf_get_array (pdf_obj *array, long idx) +{ + pdf_obj *result = NULL; + pdf_array *data; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (idx < 0) + result = data->values[idx + data->size]; + else if (idx < data->size) { + result = data->values[idx]; + } + + return result; +} + +unsigned int +pdf_array_length (pdf_obj *array) +{ + pdf_array *data; + + TYPECHECK(array, PDF_ARRAY); + + data = (pdf_array *) array->data; + + return (unsigned int) data->size; +} + +static void +release_array (pdf_array *data) +{ + unsigned long i; + + if (data->values) { + for (i = 0; i < data->size; i++) { + pdf_release_obj(data->values[i]); + data->values[i] = NULL; + } + RELEASE(data->values); + data->values = NULL; + } + RELEASE(data); +} + +/* + * The name pdf_add_array is misleading. It behaves differently than + * pdf_add_dict(). This should be pdf_push_array(). + */ +void +pdf_add_array (pdf_obj *array, pdf_obj *object) +{ + pdf_array *data; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (data->size >= data->max) { + data->max += ARRAY_ALLOC_SIZE; + data->values = RENEW(data->values, data->max, pdf_obj *); + } + data->values[data->size] = object; + data->size++; + + return; +} + +#if 0 +void +pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object) +{ + pdf_array *data; + long i; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (idx + 1 > data->max) { + data->max += ARRAY_ALLOC_SIZE; + data->values = RENEW(data->values, data->max, pdf_obj *); + } + /* + * Rangecheck error in PostScript interpreters if + * idx > data->size - 1. But pdf_new_array() doesn't set + * array size, pdf_add_array() dynamically increases size + * of array. This might confusing... + */ + if (idx + 1 > data->size) { + for (i = data->size; i < idx; i++) + data->values[i] = pdf_new_null(); /* release_array() won't work without this */ + data->values[idx] = object; + data->size = idx + 1; + } else { + if (data->values[idx]) + pdf_release_obj(data->values[idx]); + data->values[idx] = object; + } +} + +/* Easily leaks memory... */ +pdf_obj * +pdf_shift_array (pdf_obj *array) +{ + pdf_obj *result = NULL; + pdf_array *data; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (data->size > 0) { + int i; + + result = data->values[0]; + for (i = 1; i < data->size; i++) + data->values[i-1] = data->values[i]; + data->size--; + } + + return result; +} +#endif + +/* Prepend an object to an array */ +void +pdf_unshift_array (pdf_obj *array, pdf_obj *object) +{ + pdf_array *data; + int i; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (data->size >= data->max) { + data->max += ARRAY_ALLOC_SIZE; + data->values = RENEW(data->values, data->max, pdf_obj *); + } + for (i = 0; i < data->size; i++) + data->values[i+1] = data->values[i]; + data->values[0] = object; + data->size++; +} + +#if 0 +pdf_obj * +pdf_pop_array (pdf_obj *array) +{ + pdf_obj *result; + pdf_array *data; + + TYPECHECK(array, PDF_ARRAY); + + data = array->data; + if (data->size > 0) { + result = data->values[data->size - 1]; + data->size--; + } else { + result = NULL; + } + + return result; +} +#endif + +static void +write_dict (pdf_dict *dict, FILE *file) +{ +#ifdef XETEX + pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */ +#else + pdf_out (file, "<<", 2); +#endif + while (dict->key != NULL) { + pdf_write_obj(dict->key, file); + if (pdf_need_white(PDF_NAME, (dict->value)->type)) { + pdf_out_white(file); + } + pdf_write_obj(dict->value, file); +#ifdef XETEX + pdf_out_char (file, '\n'); /* removing this saves few kb. */ +#endif + dict = dict->next; + } + pdf_out(file, ">>", 2); +} + +pdf_obj * +pdf_new_dict (void) +{ + pdf_obj *result; + pdf_dict *data; + + result = pdf_new_obj(PDF_DICT); + data = NEW(1, pdf_dict); + data->key = NULL; + data->value = NULL; + data->next = NULL; + result->data = data; + + return result; +} + +static void +release_dict (pdf_dict *data) +{ + pdf_dict *next; + + while (data != NULL && data->key != NULL) { + pdf_release_obj(data->key); + pdf_release_obj(data->value); + data->key = NULL; + data->value = NULL; + next = data->next; + RELEASE(data); + data = next; + } + RELEASE(data); +} + +/* Array is ended by a node with NULL this pointer */ +/* 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, *new_node; + + TYPECHECK(dict, PDF_DICT); + TYPECHECK(key, PDF_NAME); + + /* It seems that NULL is sometimes used for null object... */ + if (value != NULL && INVALIDOBJ(value)) + ERROR("pdf_add_dict(): Passed invalid value"); + + /* If this key already exists, simply replace the value */ + 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; + return 1; + } + } + /* + * We didn't find the key. We build a new "end" node and add + * the new key just before the end + */ + 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; +} + +#if 0 +void +pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value) +{ + pdf_dict *data; + + TYPECHECK(dict, PDF_DICT); + + if (!key) { + ERROR("pdf_put_dict(): Passed invalid key."); + } + /* It seems that NULL is sometimes used for null object... */ + if (value != NULL && INVALIDOBJ(value)) { + ERROR("pdf_add_dict(): Passed invalid value."); + } + + data = dict->data; + + while (data->key != NULL) { + if (!strcmp(key, pdf_name_value(data->key))) { + pdf_release_obj(data->value); + data->value = value; + break; + } + data = data->next; + } + + /* + * If we didn't find the key, 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 = pdf_new_name(key); + data->value = value; + } +} +#endif + +/* pdf_merge_dict makes a link for each item in dict2 before stealing it */ +void +pdf_merge_dict (pdf_obj *dict1, pdf_obj *dict2) +{ + pdf_dict *data; + + TYPECHECK(dict1, PDF_DICT); + TYPECHECK(dict2, PDF_DICT); + + data = dict2->data; + while (data->key != NULL) { + pdf_add_dict(dict1, pdf_link_obj(data->key), pdf_link_obj(data->value)); + data = data->next; + } +} + +int +pdf_foreach_dict (pdf_obj *dict, + int (*proc) (pdf_obj *, pdf_obj *, void *), void *pdata) +{ + int error = 0; + pdf_dict *data; + + ASSERT(proc); + + TYPECHECK(dict, PDF_DICT); + + data = dict->data; + while (!error && + data->key != NULL) { + error = proc(data->key, data->value, pdata); + data = data->next; + } + + return error; +} + +#define pdf_match_name(o,s) ((o) && (s) && !strcmp(((pdf_name *)(o)->data)->name, (s))) +pdf_obj * +pdf_lookup_dict (pdf_obj *dict, const char *name) +{ + pdf_dict *data; + + ASSERT(name); + + TYPECHECK(dict, PDF_DICT); + + data = dict->data; + while (data->key != NULL) { + if (!strcmp(name, pdf_name_value(data->key))) { + return data->value; + } + data = data->next; + } + + return NULL; +} + +/* Returns array of dictionary keys */ +pdf_obj * +pdf_dict_keys (pdf_obj *dict) +{ + pdf_obj *keys; + pdf_dict *data; + + TYPECHECK(dict, PDF_DICT); + + keys = pdf_new_array(); + for (data = dict->data; (data && + data->key != NULL); data = data->next) { + /* We duplicate name object rather than linking keys. + * If we forget to free keys, broken PDF is generated. + */ + pdf_add_array(keys, pdf_new_name(pdf_name_value(data->key))); + } + + return keys; +} + +void +pdf_remove_dict (pdf_obj *dict, const char *name) +{ + pdf_dict *data, **data_p; + + TYPECHECK(dict, PDF_DICT); + + data = dict->data; + data_p = (pdf_dict **) (void *) &(dict->data); + while (data->key != NULL) { + if (pdf_match_name(data->key, name)) { + pdf_release_obj(data->key); + pdf_release_obj(data->value); + *data_p = data->next; + RELEASE(data); + break; + } + data_p = &(data->next); + data = data->next; + } +} + +pdf_obj * +pdf_new_stream (int flags) +{ + pdf_obj *result; + pdf_stream *data; + + result = pdf_new_obj(PDF_STREAM); + data = NEW(1, pdf_stream); + /* + * Although we are using an arbitrary pdf_object here, it must have + * type=PDF_DICT and cannot be an indirect reference. This will be + * checked by the output routine. + */ + data->dict = pdf_new_dict(); + data->_flags = flags; + data->stream = NULL; + data->stream_length = 0; + data->max_length = 0; + data->objstm_data = NULL; + + result->data = data; + result->flags |= OBJ_NO_OBJSTM; + + return result; +} + +static void +write_stream (pdf_stream *stream, FILE *file) +{ + unsigned char *filtered; + unsigned long filtered_length; + unsigned long buffer_length; + unsigned char *buffer; + + /* + * Always work from a copy of the stream. All filters read from + * "filtered" and leave their result in "filtered". + */ +#if 0 + filtered = NEW(stream->stream_length + 1, unsigned char); +#endif + filtered = NEW(stream->stream_length, unsigned char); + memcpy(filtered, stream->stream, stream->stream_length); + filtered_length = stream->stream_length; + +#if 0 + if (stream->stream_length < 10) + stream->_flags &= ^STREAM_COMPRESS; +#endif + +#ifdef HAVE_ZLIB + /* Apply compression filter if requested */ + if (stream->stream_length > 0 && + (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 *filter_name = pdf_new_name("FlateDecode"); + + 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, + filtered_length, compression_level)) { + ERROR("Zlib error"); + } +#else + if (compress(buffer, &buffer_length, filtered, + filtered_length)) { + ERROR ("Zlib error"); + } +#endif /* HAVE_ZLIB_COMPRESS2 */ + RELEASE(filtered); + compression_saved += filtered_length - buffer_length + - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n")); + + filtered = buffer; + filtered_length = buffer_length; + } +#endif /* HAVE_ZLIB */ + +#if 0 + /* + * An optional end-of-line marker preceding the "endstream" is + * not part of stream data. See, PDF Reference 4th ed., p. 38. + */ + /* Add a '\n' if the last character wasn't one */ + if (filtered_length > 0 && + filtered[filtered_length-1] != '\n') { + filtered[filtered_length] = '\n'; + filtered_length++; + } +#endif + pdf_add_dict(stream->dict, + pdf_new_name("Length"), pdf_new_number(filtered_length)); + + pdf_write_obj(stream->dict, file); + + pdf_out(file, "\nstream\n", 8); + + if (enc_mode) + pdf_encrypt_data(filtered, filtered_length); + + if (filtered_length > 0) { + pdf_out(file, filtered, filtered_length); + } + RELEASE(filtered); + + /* + * This stream length "object" gets reset every time write_stream is + * called for the stream object. + * If this stream gets written more than once with different + * filters, this could be a problem. + */ + + pdf_out(file, "\n", 1); + pdf_out(file, "endstream", 9); +} + +static void +release_stream (pdf_stream *stream) +{ + pdf_release_obj(stream->dict); + stream->dict = NULL; + + if (stream->stream) { + RELEASE(stream->stream); + stream->stream = NULL; + } + + if (stream->objstm_data) { + RELEASE(stream->objstm_data); + stream->objstm_data = NULL; + } + + RELEASE(stream); +} + +pdf_obj * +pdf_stream_dict (pdf_obj *stream) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + data = stream->data; + + return data->dict; +} + +const void * +pdf_stream_dataptr (pdf_obj *stream) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + data = stream->data; + + return (const void *) data->stream; +} + +long +pdf_stream_length (pdf_obj *stream) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + data = stream->data; + + return (long) data->stream_length; +} + +static void +set_objstm_data (pdf_obj *objstm, long *data) { + TYPECHECK(objstm, PDF_STREAM); + + ((pdf_stream *) objstm->data)->objstm_data = data; +} + +static long * +get_objstm_data (pdf_obj *objstm) { + TYPECHECK(objstm, PDF_STREAM); + + return ((pdf_stream *) objstm->data)->objstm_data; +} + +void +pdf_add_stream (pdf_obj *stream, const void *stream_data, long length) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + if (length < 1) + return; + data = stream->data; + if (data->stream_length + length > data->max_length) { + data->max_length += length + STREAM_ALLOC_SIZE; + data->stream = RENEW(data->stream, data->max_length, unsigned char); + } + memcpy(data->stream + data->stream_length, stream_data, length); + data->stream_length += length; +} + +#if HAVE_ZLIB +#define WBUF_SIZE 4096 +int +pdf_add_stream_flate (pdf_obj *dst, const void *data, long len) +{ + z_stream z; + Bytef wbuf[WBUF_SIZE]; + + z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; + + z.next_in = (Bytef *) data; z.avail_in = len; + z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; + + if (inflateInit(&z) != Z_OK) { + WARN("inflateInit() failed."); + return -1; + } + + for (;;) { + int status; + status = inflate(&z, Z_NO_FLUSH); + if (status == Z_STREAM_END) + break; + else if (status != Z_OK) { + WARN("inflate() failed. Broken PDF file?"); + inflateEnd(&z); + return -1; + } + + if (z.avail_out == 0) { + pdf_add_stream(dst, wbuf, WBUF_SIZE); + z.next_out = wbuf; + z.avail_out = WBUF_SIZE; + } + } + + if (WBUF_SIZE - z.avail_out > 0) + pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); + + return (inflateEnd(&z) == Z_OK ? 0 : -1); +} +#endif + + +int +pdf_concat_stream (pdf_obj *dst, pdf_obj *src) +{ + const char *stream_data; + long stream_length; + pdf_obj *stream_dict; + pdf_obj *filter; + + if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) + ERROR("Invalid type."); + + stream_data = pdf_stream_dataptr(src); + stream_length = pdf_stream_length (src); + stream_dict = pdf_stream_dict (src); + + if (pdf_lookup_dict(stream_dict, "DecodeParms")) { + WARN("Streams with DecodeParams not supported."); + return -1; + } + + filter = pdf_lookup_dict(stream_dict, "Filter"); + if (!filter) { + pdf_add_stream(dst, stream_data, stream_length); + return 0; +#if HAVE_ZLIB + } else { + char *filter_name; + if (PDF_OBJ_NAMETYPE(filter)) { + filter_name = pdf_name_value(filter); + if (filter_name && !strcmp(filter_name, "FlateDecode")) + return pdf_add_stream_flate(dst, stream_data, stream_length); + else { + WARN("DecodeFilter \"%s\" not supported.", filter_name); + return -1; + } + } else if (PDF_OBJ_ARRAYTYPE(filter)) { + if (pdf_array_length(filter) > 1) { + WARN("Multiple DecodeFilter not supported."); + return -1; + } else { + filter_name = pdf_name_value(pdf_get_array(filter, 0)); + if (filter_name && !strcmp(filter_name, "FlateDecode")) + return pdf_add_stream_flate(dst, stream_data, stream_length); + else { + WARN("DecodeFilter \"%s\" not supported.", filter_name); + return -1; + } + } + } else + ERROR("Broken PDF file?"); +#endif /* HAVE_ZLIB */ + } + + return -1; +} + +static pdf_obj * +pdf_stream_uncompress (pdf_obj *src) { + pdf_obj *dst = pdf_new_stream(0); + + TYPECHECK(src, PDF_STREAM); + + pdf_merge_dict(pdf_stream_dict(dst), pdf_stream_dict(src)); + pdf_remove_dict(pdf_stream_dict(dst), "Length"); + pdf_concat_stream(dst, src); + + return dst; +} + +#if 0 +void +pdf_stream_set_flags (pdf_obj *stream, int flags) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + data = stream->data; + data->_flags = flags; +} + +int +pdf_stream_get_flags (pdf_obj *stream) +{ + pdf_stream *data; + + TYPECHECK(stream, PDF_STREAM); + + data = stream->data; + + return data->_flags; +} +#endif + +static void +pdf_write_obj (pdf_obj *object, FILE *file) +{ + if (object == NULL) { + write_null(NULL, file); + return; + } + + if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object)) + ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type); + + if (file == stderr) + fprintf(stderr, "{%d}", object->refcount); + + switch (object->type) { + case PDF_BOOLEAN: + write_boolean(object->data, file); + break; + case PDF_NUMBER: + write_number (object->data, file); + break; + case PDF_STRING: + write_string (object->data, file); + break; + case PDF_NAME: + write_name(object->data, file); + break; + case PDF_ARRAY: + write_array(object->data, file); + break; + case PDF_DICT: + write_dict (object->data, file); + break; + case PDF_STREAM: + write_stream(object->data, file); + break; + case PDF_NULL: + write_null(NULL, file); + break; + case PDF_INDIRECT: + write_indirect(object->data, file); + break; + } +} + +/* Write the object to the file */ +static void +pdf_flush_obj (pdf_obj *object, FILE *file) +{ + long length; + + /* + * Record file position + */ + 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); + pdf_write_obj(object, file); + pdf_out(file, "\nendobj\n", 8); +} + +static long +pdf_add_objstm (pdf_obj *objstm, pdf_obj *object) +{ + long *data, pos; + + TYPECHECK(objstm, PDF_STREAM); + + data = get_objstm_data(objstm); + pos = ++data[0]; + + data[2*pos] = object->label; + data[2*pos+1] = pdf_stream_length(objstm); + + add_xref_entry(object->label, 2, objstm->label, pos-1); + + /* redirect output into objstm */ + output_stream = objstm; + enc_mode = 0; + pdf_write_obj(object, pdf_output_file); + pdf_out_char(pdf_output_file, '\n'); + output_stream = NULL; + + return pos; +} + +static void +release_objstm (pdf_obj *objstm) +{ + long *data = get_objstm_data(objstm); + long pos = data[0]; + pdf_obj *dict; + pdf_stream *stream; + unsigned char *old_buf; + unsigned long old_length; + stream = (pdf_stream *) objstm->data; + + /* Precede stream data by offset table */ + old_buf = stream->stream; + 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; + + { + long i = 2*pos, *val = data+2; + while (i--) { + long length = sprintf(format_buffer, "%ld ", *(val++)); + pdf_add_stream(objstm, format_buffer, length); + } + } + + dict = pdf_stream_dict(objstm); + 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(objstm, old_buf, old_length); + RELEASE(old_buf); + pdf_release_obj(objstm); +} + +void +pdf_release_obj (pdf_obj *object) +{ + if (object == NULL) + return; + if (INVALIDOBJ(object) || object->refcount <= 0) { + MESG("\npdf_release_obj: object=%p, type=%d, refcount=%d\n", + object, object->type, object->refcount); + pdf_write_obj(object, stderr); + ERROR("pdf_release_obj: Called with invalid object."); + } + object->refcount -= 1; + if (object->refcount == 0) { + /* + * 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) { + if (!do_objstm || object->flags & OBJ_NO_OBJSTM + || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT) + || object->generation) + pdf_flush_obj(object, pdf_output_file); + else { + if (!current_objstm) { + long *data = NEW(2*OBJSTM_MAX_OBJS+2, long); + data[0] = data[1] = 0; + current_objstm = pdf_new_stream(STREAM_COMPRESS); + set_objstm_data(current_objstm, data); + pdf_label_obj(current_objstm); + } + if (pdf_add_objstm(current_objstm, object) == OBJSTM_MAX_OBJS) { + release_objstm(current_objstm); + current_objstm = NULL; + } + } + } + switch (object->type) { + case PDF_BOOLEAN: + release_boolean(object->data); + break; + case PDF_NULL: + release_null(object->data); + break; + case PDF_NUMBER: + release_number(object->data); + break; + case PDF_STRING: + release_string(object->data); + break; + case PDF_NAME: + release_name(object->data); + break; + case PDF_ARRAY: + release_array(object->data); + break; + case PDF_DICT: + release_dict(object->data); + break; + case PDF_STREAM: + release_stream(object->data); + break; + case PDF_INDIRECT: + release_indirect(object->data); + break; + } + /* This might help detect freeing already freed objects */ + object->type = -1; + object->data = NULL; + RELEASE(object); + } +} + +#ifdef XETEX +/* Copy object data without changing object label. */ +void +pdf_copy_object (pdf_obj *dst, pdf_obj *src) +{ + if (!dst || !src) + return; + + switch (dst->type) { + case PDF_BOOLEAN: release_boolean(dst->data); break; + case PDF_NULL: release_null(dst->data); break; + case PDF_NUMBER: release_number(dst->data); break; + case PDF_STRING: release_string(dst->data); break; + case PDF_NAME: release_name(dst->data); break; + case PDF_ARRAY: release_array(dst->data); break; + case PDF_DICT: release_dict(dst->data); break; + case PDF_STREAM: release_stream(dst->data); break; + case PDF_INDIRECT: release_indirect(dst->data); break; + } + + dst->type = src->type; + switch (src->type) { + case PDF_BOOLEAN: + dst->data = NEW(1, pdf_boolean); + pdf_set_boolean(dst, pdf_boolean_value(src)); + break; + case PDF_NULL: + dst->data = NULL; + break; + case PDF_NUMBER: + dst->data = NEW(1, pdf_number); + pdf_set_number(dst, pdf_number_value(src)); + break; + case PDF_STRING: + dst->data = NEW(1, pdf_string); + pdf_set_string(dst, + pdf_string_value(src), + pdf_string_length(src)); + break; + case PDF_NAME: + dst->data = NEW(1, pdf_name); + pdf_set_name(dst, pdf_name_value(src)); + break; + case PDF_ARRAY: + { + pdf_array *data; + unsigned long i; + + dst->data = data = NEW(1, pdf_array); + data->size = 0; + data->max = 0; + data->values = NULL; + for (i = 0; i < pdf_array_length(src); i++) { + pdf_add_array(dst, pdf_link_obj(pdf_get_array(src, i))); + } + } + break; + case PDF_DICT: + { + pdf_dict *data; + + dst->data = data = NEW(1, pdf_dict); + data->key = NULL; + data->value = NULL; + data->next = NULL; + pdf_merge_dict(dst, src); + } + break; + case PDF_STREAM: + { + pdf_stream *data; + + dst->data = data = NEW(1, pdf_stream); + data->dict = pdf_new_dict(); + data->_flags = ((pdf_stream *)src->data)->_flags; + data->stream_length = 0; + data->max_length = 0; + + pdf_add_stream(dst, pdf_stream_dataptr(src), pdf_stream_length(src)); + pdf_merge_dict(data->dict, pdf_stream_dict(src)); + } + break; + case PDF_INDIRECT: + { + pdf_indirect *data; + + dst->data = data = NEW(1, pdf_indirect); + data->pf = ((pdf_indirect *) (src->data))->pf; + data->label = ((pdf_indirect *) (src->data))->label; + data->generation = ((pdf_indirect *) (src->data))->generation; + } + break; + } + + return; +} +#endif + +static int +backup_line (FILE *pdf_input_file) +{ + int ch = -1; + + /* + * Note: this code should work even if \r\n is eol. It could fail on a + * machine where \n is eol and there is a \r in the stream --- Highly + * unlikely in the last few bytes where this is likely to be used. + */ + if (tell_position(pdf_input_file) > 1) + do { + seek_relative (pdf_input_file, -2); + } while (tell_position(pdf_input_file) > 0 && + (ch = fgetc(pdf_input_file)) >= 0 && + (ch != '\n' && ch != '\r' )); + if (ch < 0) { + return 0; + } + + return 1; +} + +static long +find_xref (FILE *pdf_input_file) +{ + long xref_pos; + int tries = 10; + + do { + long currentpos; + + if (!backup_line(pdf_input_file)) { + tries = 0; + break; + } + currentpos = tell_position(pdf_input_file); + fread(work_buffer, sizeof(char), strlen("startxref"), pdf_input_file); + seek_absolute(pdf_input_file, currentpos); + tries--; + } while (tries > 0 && + strncmp(work_buffer, "startxref", strlen("startxref"))); + if (tries <= 0) + return 0; + + /* Skip rest of this line */ + mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); + /* Next line of input file should contain actual xref location */ + mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); + + { + const char *start, *end; + char *number; + + start = work_buffer; + end = start + strlen(work_buffer); + skip_white(&start, end); + number = parse_number(&start, end); + xref_pos = (long) atof(number); + RELEASE(number); + } + + return xref_pos; +} + +/* + * This routine must be called with the file pointer located + * at the start of the trailer. + */ +static pdf_obj * +parse_trailer (pdf_file *pf) +{ + pdf_obj *result; + /* + * Fill work_buffer and hope trailer fits. This should + * be made a bit more robust sometime. + */ + if (fread(work_buffer, sizeof(char), + WORK_BUFFER_SIZE, pf->file) == 0 || + strncmp(work_buffer, "trailer", strlen("trailer"))) { + WARN("No trailer. Are you sure this is a PDF file?"); + WARN("buffer:\n->%s<-\n", work_buffer); + result = NULL; + } else { + const char *p = work_buffer + strlen("trailer"); + skip_white(&p, work_buffer + WORK_BUFFER_SIZE); + result = parse_pdf_dict(&p, work_buffer + WORK_BUFFER_SIZE, pf); + } + + return result; +} + +/* + * This routine tries to estimate an upper bound for character position + * of the end of the object, so it knows how big the buffer must be. + * The parsing routines require that the entire object be read into + * memory. It would be a major pain to rewrite them. The worst case + * is that an object before an xref table will grab the whole table + * :-( + */ +static long +next_object_offset (pdf_file *pf, unsigned long obj_num) +{ + long next = pf->file_size; /* Worst case */ + long i, curr; + + curr = pf->xref_table[obj_num].field2; + /* Check all other type 1 objects to find next one */ + for (i = 0; i < pf->num_obj; i++) { + if (pf->xref_table[i].type == 1 && + pf->xref_table[i].field2 > curr && + pf->xref_table[i].field2 < next) + next = pf->xref_table[i].field2; + } + + return next; +} + +#define checklabel(pf, n, g) ((n) > 0 && (n) < (pf)->num_obj && ( \ + ((pf)->xref_table[(n)].type == 1 && (pf)->xref_table[(n)].field3 == (g)) || \ + ((pf)->xref_table[(n)].type == 2 && !(g)))) + +pdf_obj * +pdf_new_indirect (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) +{ + pdf_obj *result; + pdf_indirect *indirect; + + indirect = NEW(1, pdf_indirect); + indirect->pf = pf; + indirect->label = obj_num; + indirect->generation = obj_gen; + + result = pdf_new_obj(PDF_INDIRECT); + result->data = indirect; + + return result; +} + +static pdf_obj * +pdf_read_object (unsigned long obj_num, unsigned short obj_gen, + pdf_file *pf, long offset, long limit) +{ + long length; + char *buffer; + const char *p, *endptr; + pdf_obj *result; + + length = limit - offset; + + if (length <= 0) + return NULL; + + buffer = NEW(length + 1, char); + + seek_absolute(pf->file, offset); + fread(buffer, sizeof(char), length, pf->file); + + p = buffer; + endptr = p + length; + + /* Check for obj_num and obj_gen */ + { + const char *q = p; /* <== p */ + char *sp; + unsigned long n, g; + + skip_white(&q, endptr); + sp = parse_unsigned(&q, endptr); + if (!sp) { + RELEASE(buffer); + return NULL; + } + n = strtoul(sp, NULL, 10); + RELEASE(sp); + + skip_white(&q, endptr); + sp = parse_unsigned(&q, endptr); + if (!sp) { + RELEASE(buffer); + return NULL; + } + g = strtoul(sp, NULL, 10); + RELEASE(sp); + + if (obj_num && (n != obj_num || g != obj_gen)) { + RELEASE(buffer); + return NULL; + } + + p = q; /* ==> p */ + } + + + skip_white(&p, endptr); + if (memcmp(p, "obj", strlen("obj"))) { + WARN("Didn't find \"obj\"."); + RELEASE(buffer); + return NULL; + } + p += strlen("obj"); + + result = parse_pdf_object(&p, endptr, pf); + + skip_white(&p, endptr); + if (memcmp(p, "endobj", strlen("endobj"))) { + WARN("Didn't find \"endobj\"."); + if (result) + pdf_release_obj(result); + result = NULL; + } + RELEASE(buffer); + + return result; +} + +static pdf_obj * +read_objstm (pdf_file *pf, unsigned long num) +{ + unsigned long offset = pf->xref_table[num].field2; + unsigned short gen = pf->xref_table[num].field3; + long limit = next_object_offset(pf, num), n, first, *header = NULL; + char *data = NULL, *q; + const char *p, *endptr; + int i; + + pdf_obj *objstm, *dict, *type, *n_obj, *first_obj; + + objstm = pdf_read_object(num, gen, pf, offset, limit); + + if (!PDF_OBJ_STREAMTYPE(objstm)) + goto error; + + { + pdf_obj *tmp = pdf_stream_uncompress(objstm); + if (!tmp) + goto error; + pdf_release_obj(objstm); + objstm = tmp; + } + + dict = pdf_stream_dict(objstm); + + type = pdf_lookup_dict(dict, "Type"); + if (!PDF_OBJ_NAMETYPE(type) || + strcmp(pdf_name_value(type), "ObjStm")) + goto error; + + n_obj = pdf_lookup_dict(dict, "N"); + if (!PDF_OBJ_NUMBERTYPE(n_obj)) + goto error; + n = (long) pdf_number_value(n_obj); + + first_obj = pdf_lookup_dict(dict, "First"); + if (!PDF_OBJ_NUMBERTYPE(first_obj)) + goto error; + first = (long) pdf_number_value(first_obj); + /* reject object streams without object data */ + if (first >= pdf_stream_length(objstm)) + goto error; + + header = NEW(2*(n+1), long); + set_objstm_data(objstm, header); + *(header++) = n; + *(header++) = first; + + /* avoid parsing beyond offset table */ + data = NEW(first + 1, char); + memcpy(data, pdf_stream_dataptr(objstm), first); + data[first] = 0; + + p = data; + endptr = p + first; + i = 2*n; + while (i--) { + *(header++) = strtoul(p, &q, 10); + if (q == p) + goto error; + p = q; + } + + /* Any garbage after last entry? */ + skip_white(&p, endptr); + if (p != endptr) + goto error; + RELEASE(data); + + return pf->xref_table[num].direct = objstm; + + error: + WARN("Cannot parse object stream."); + if (data) + RELEASE(data); + if (objstm) + pdf_release_obj(objstm); + return NULL; +} + +/* Label without corresponding object definition are replaced by the + * null object, as required by the PDF spec. This is important to parse + * several cross-reference sections. + */ +static pdf_obj * +pdf_get_object (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) +{ + pdf_obj *result; + + if (!checklabel(pf, obj_num, obj_gen)) { + WARN("Trying to read nonexistent or deleted object: %lu %u", + obj_num, obj_gen); + return pdf_new_null(); + } + + if ((result = pf->xref_table[obj_num].direct)) { + return pdf_link_obj(result); + } + + if (pf->xref_table[obj_num].type == 1) { + /* type == 1 */ + unsigned long offset; + long limit; + offset = pf->xref_table[obj_num].field2; + limit = next_object_offset(pf, obj_num); + result = pdf_read_object(obj_num, obj_gen, pf, offset, limit); + } else { + /* type == 2 */ + unsigned long objstm_num = pf->xref_table[obj_num].field2; + unsigned short index = pf->xref_table[obj_num].field3; + pdf_obj *objstm; + long *data, n, first, length; + const char *p, *q; + + if (objstm_num >= pf->num_obj || + pf->xref_table[objstm_num].type != 1 || + !((objstm = pf->xref_table[objstm_num].direct) || + (objstm = read_objstm(pf, objstm_num)))) + goto error; + + data = get_objstm_data(objstm); + n = *(data++); + first = *(data++); + + if (index >= n || data[2*index] != obj_num) + goto error; + + length = pdf_stream_length(objstm); + p = (const char *) pdf_stream_dataptr(objstm) + first + data[2*index+1]; + q = p + (index == n-1 ? length : first+data[2*index+3]); + result = parse_pdf_object(&p, q, pf); + if (!result) + goto error; + } + + /* Make sure the caller doesn't free this object */ + pf->xref_table[obj_num].direct = pdf_link_obj(result); + + return result; + + error: + WARN("Could not read object from object stream."); + return pdf_new_null(); +} + +#define OBJ_FILE(o) (((pdf_indirect *)((o)->data))->pf) +#define OBJ_NUM(o) (((pdf_indirect *)((o)->data))->label) +#define OBJ_GEN(o) (((pdf_indirect *)((o)->data))->generation) + +/* pdf_deref_obj always returns a link instead of the original */ +/* It never return the null object, but the NULL pointer instead */ +pdf_obj * +pdf_deref_obj (pdf_obj *obj) +{ + int count = PDF_OBJ_MAX_DEPTH; + + if (obj) + obj = pdf_link_obj(obj); + + while (PDF_OBJ_INDIRECTTYPE(obj) && --count) { + pdf_file *pf = OBJ_FILE(obj); + unsigned long obj_num = OBJ_NUM(obj); + unsigned short obj_gen = OBJ_GEN(obj); + if (!pf) + ERROR("Tried to deref a non-file object"); + pdf_release_obj(obj); + obj = pdf_get_object(pf, obj_num, obj_gen); + } + + if (!count) + ERROR("Loop in object hierarchy detected. Broken PDF file?"); + + if (PDF_OBJ_NULLTYPE(obj)) { + pdf_release_obj(obj); + return NULL; + } else + return obj; +} + +static void +extend_xref (pdf_file *pf, long new_size) +{ + unsigned long i; + + pf->xref_table = RENEW(pf->xref_table, new_size, xref_entry); + for (i = pf->num_obj; i < new_size; i++) { + pf->xref_table[i].direct = NULL; + pf->xref_table[i].indirect = NULL; + pf->xref_table[i].type = 0; + pf->xref_table[i].field3 = 0; + pf->xref_table[i].field2 = 0L; + } + pf->num_obj = new_size; +} + +static int +parse_xref_table (pdf_file *pf, long xref_pos) +{ + FILE *pdf_input_file = pf->file; + unsigned long first, size; + unsigned long i, offset; + unsigned int obj_gen; + char flag; + int r; + + /* + * This routine reads one xref segment. It may be called multiple times + * on the same file. xref tables sometimes come in pieces. + */ + + seek_absolute(pf->file, xref_pos); + + mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); + if (memcmp(work_buffer, "xref", strlen("xref"))) { + /* Might be an xref stream and not an xref table */ + return 0; + } + /* Next line in file has first item and size of table */ + for (;;) { + unsigned long current_pos; + + current_pos = tell_position(pdf_input_file); + if (mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file) == NULL) { + WARN("Premature end of PDF file while parsing xref table."); + return -1; + } + if (!strncmp(work_buffer, "trailer", strlen ("trailer"))) { + /* + * Backup... This is ugly, but it seems like the safest thing to + * do. It is possible the trailer dictionary starts on the same + * logical line as the word trailer. In that case, the mfgets + * call might have started to read the trailer dictionary and + * parse_trailer would fail. + */ + seek_absolute(pdf_input_file, current_pos); + break; + } + sscanf(work_buffer, "%lu %lu", &first, &size); + if (pf->num_obj < first + size) { + extend_xref(pf, first + size); + } + + for (i = first; i < first + size; i++) { + fread(work_buffer, sizeof(char), 20, pdf_input_file); + /* + * Don't overwrite positions that have already been set by a + * modified xref table. We are working our way backwards + * through the reference table, so we only set "position" + * if it hasn't been set yet. + */ + work_buffer[19] = 0; + offset = 0UL; obj_gen = 0; flag = 0; + r = sscanf(work_buffer, "%010lu %05u %c", &offset, &obj_gen, &flag); + if ( r != 3 || + ((flag != 'n' && flag != 'f') || + (flag == 'n' && + (offset >= pf->file_size || (offset > 0 && offset < 4))))) { + WARN("Invalid xref table entry [%lu]. PDF file is corrupt...", i); + return -1; + } + if (!pf->xref_table[i].field2) { + pf->xref_table[i].type = (flag == 'n'); + pf->xref_table[i].field2 = offset; + pf->xref_table[i].field3 = obj_gen; + } + } + } + + return 1; +} + +static unsigned long +parse_xrefstm_field (const char **p, int length, unsigned long def) +{ + unsigned long val = 0; + + if (!length) + return def; + + while (length--) { + val <<= 8; + val |= (unsigned char) *((*p)++); + } + + return val; +} + +static int +parse_xrefstm_subsec (pdf_file *pf, + const char **p, long *length, + int *W, int wsum, + long first, long size) { + xref_entry *e; + + if ((*length -= wsum*size) < 0) + return -1; + + if (pf->num_obj < first+size) + extend_xref(pf, first+size); /* TODO: change! why? */ + + e = pf->xref_table + first; + while (size--) { + unsigned char type; + unsigned long field2; + unsigned short field3; + + type = (unsigned char) parse_xrefstm_field(p, W[0], 1); + if (type > 2) + WARN("Unknown cross-reference stream entry type."); + else if (!W[1] || (type != 1 && !W[2])) + return -1; + + field2 = (unsigned long) parse_xrefstm_field(p, W[1], 0); + field3 = (unsigned short) parse_xrefstm_field(p, W[2], 0); + + if (!e->field2) { + e->type = type; + e->field2 = field2; + e->field3 = field3; + } + e++; + } + + return 0; +} + +static int +parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) +{ + pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj; + unsigned long size; + long length; + int W[3], i, wsum = 0; + const char *p; + + xrefstm = pdf_read_object(0, 0, pf, xref_pos, pf->file_size); + if (!PDF_OBJ_STREAMTYPE(xrefstm)) + goto error; + + { + pdf_obj *tmp = pdf_stream_uncompress(xrefstm); + if (!tmp) + goto error; + pdf_release_obj(xrefstm); + xrefstm = tmp; + } + + *trailer = pdf_link_obj(pdf_stream_dict(xrefstm)); + + size_obj = pdf_lookup_dict(*trailer, "Size"); + if (!PDF_OBJ_NUMBERTYPE(size_obj)) + goto error; + size = (unsigned long) pdf_number_value(size_obj); + + length = pdf_stream_length(xrefstm); + + W_obj = pdf_lookup_dict(*trailer, "W"); + if (!PDF_OBJ_ARRAYTYPE(W_obj) || pdf_array_length(W_obj) != 3) + goto error; + + for (i = 0; i < 3; i++) { + pdf_obj *tmp = pdf_get_array(W_obj, i); + if (!PDF_OBJ_NUMBERTYPE(tmp)) + goto error; + wsum += (W[i] = (int) pdf_number_value(tmp)); + } + + p = pdf_stream_dataptr(xrefstm); + + index_obj = pdf_lookup_dict(*trailer, "Index"); + if (index_obj) { + unsigned int index_len; + if (!PDF_OBJ_ARRAYTYPE(index_obj) || + ((index_len = pdf_array_length(index_obj)) % 2 )) + goto error; + + i = 0; + while (i < index_len) { + pdf_obj *first = pdf_get_array(index_obj, i++); + size_obj = pdf_get_array(index_obj, i++); + if (!PDF_OBJ_NUMBERTYPE(first) || + !PDF_OBJ_NUMBERTYPE(size_obj) || + parse_xrefstm_subsec(pf, &p, &length, W, wsum, + (long) pdf_number_value(first), + (long) pdf_number_value(size_obj))) + goto error; + } + } else if (parse_xrefstm_subsec(pf, &p, &length, W, wsum, 0, size)) + goto error; + + if (length) + WARN("Garbage in xref stream."); + + pdf_release_obj(xrefstm); + + return 1; + + error: + WARN("Cannot parse cross-reference stream."); + if (xrefstm) + pdf_release_obj(xrefstm); + if (*trailer) { + pdf_release_obj(*trailer); + *trailer = NULL; + } + return 0; +} + +/* TODO: parse Version entry */ +static pdf_obj * +read_xref (pdf_file *pf) +{ + pdf_obj *trailer = NULL, *main_trailer = NULL; + long xref_pos; + + if (!(xref_pos = find_xref(pf->file))) + goto error; + + while (xref_pos) { + pdf_obj *prev; + + int res = parse_xref_table(pf, xref_pos); + if (res > 0) { + /* cross-reference table */ + pdf_obj *xrefstm; + + if (!(trailer = parse_trailer(pf))) + goto error; + + if (!main_trailer) + main_trailer = pdf_link_obj(trailer); + + if ((xrefstm = pdf_lookup_dict(trailer, "XRefStm"))) { + pdf_obj *new_trailer = NULL; + if (PDF_OBJ_NUMBERTYPE(xrefstm) && + parse_xref_stream(pf, (long) pdf_number_value(xrefstm), + &new_trailer)) + pdf_release_obj(new_trailer); + else + WARN("Skipping hybrid reference section."); + /* Many PDF 1.5 xref streams use DecodeParms, which we cannot + parse. This way we can use at least xref tables in hybrid + documents. Or should we better stop parsing the file? + */ + } + + } else if (!res && parse_xref_stream(pf, xref_pos, &trailer)) { + /* cross-reference stream */ + if (!main_trailer) + main_trailer = pdf_link_obj(trailer); + } else + goto error; + + if ((prev = pdf_lookup_dict(trailer, "Prev"))) { + if (PDF_OBJ_NUMBERTYPE(prev)) + xref_pos = (long) pdf_number_value(prev); + else + goto error; + } else + xref_pos = 0; + + pdf_release_obj(trailer); + } + +#if 0 + if (!pdf_lookup_dict(main_trailer, "Root")) { + WARN("Trailer doesn't have catalog. Is this a correct PDF file?"); + goto error; + } +#endif + + return main_trailer; + + error: + WARN("Error while parsing PDF file."); + if (trailer) + pdf_release_obj(trailer); + if (main_trailer) + pdf_release_obj(main_trailer); + return NULL; +} + +static struct ht_table *pdf_files = NULL; + +static pdf_file * +pdf_file_new (FILE *file) +{ + pdf_file *pf; + ASSERT(file); + pf = NEW(1, pdf_file); + pf->file = file; + pf->trailer = NULL; + pf->xref_table = NULL; + pf->catalog = NULL; + pf->num_obj = 0; + pf->version = 0; + + seek_end(file); + pf->file_size = tell_position(file); + + return pf; +} + +static void +pdf_file_free (pdf_file *pf) +{ + unsigned long i; + + if (!pf) { + return; + } + + for (i = 0; i < pf->num_obj; i++) { + if (pf->xref_table[i].direct) + pdf_release_obj(pf->xref_table[i].direct); + if (pf->xref_table[i].indirect) + pdf_release_obj(pf->xref_table[i].indirect); + } + + RELEASE(pf->xref_table); + if (pf->trailer) + pdf_release_obj(pf->trailer); + if (pf->catalog) + pdf_release_obj(pf->catalog); + + RELEASE(pf); +} + +void +pdf_files_init (void) +{ + pdf_files = NEW(1, struct ht_table); + ht_init_table(pdf_files, (void (*)(void *)) pdf_file_free); +} + +int +pdf_file_get_version (pdf_file *pf) +{ + ASSERT(pf); + return pf->version; +} + +#ifdef XETEX +pdf_obj * +pdf_file_get_trailer (pdf_file *pf) +{ + ASSERT(pf); + return pdf_link_obj(pf->trailer); +} +#endif + +pdf_obj * +pdf_file_get_catalog (pdf_file *pf) +{ + ASSERT(pf); + return pf->catalog; +} + +pdf_file * +pdf_open (const char *ident, FILE *file) +{ + pdf_file *pf = NULL; + + ASSERT(pdf_files); + + if (ident) + pf = (pdf_file *) ht_lookup_table(pdf_files, ident, strlen(ident)); + + if (pf) { + pf->file = file; + } else { +#ifndef XETEX + pdf_obj *new_version; +#endif + int version = check_for_pdf_version(file); + + if (version < 1 || version > pdf_version) { + WARN("pdf_open: Not a PDF 1.[1-%u] file.", pdf_version); + return NULL; + } + + pf = pdf_file_new(file); + pf->version = version; + + if (!(pf->trailer = read_xref(pf))) + goto error; + +#ifndef XETEX + if (pdf_lookup_dict(pf->trailer, "Encrypt")) { + WARN("PDF document is encrypted."); + goto error; + } + + pf->catalog = pdf_deref_obj(pdf_lookup_dict(pf->trailer, "Root")); + if (!PDF_OBJ_DICTTYPE(pf->catalog)) { + WARN("Cannot read PDF document catalog. Broken PDF file?"); + goto error; + } + + new_version = pdf_deref_obj(pdf_lookup_dict(pf->catalog, "Version")); + if (new_version) { + unsigned int minor; + + if (!PDF_OBJ_NAMETYPE(new_version) || + sscanf(pdf_name_value(new_version), "1.%u", &minor) != 1) { + pdf_release_obj(new_version); + WARN("Illegal Version entry in document catalog. Broken PDF file?"); + goto error; + } + + if (pf->version < minor) + pf->version = minor; + + pdf_release_obj(new_version); + } +#endif + + if (ident) + ht_append_table(pdf_files, ident, strlen(ident), pf); + } + + return pf; + + error: + pdf_file_free(pf); + return NULL; +} + +void +pdf_close (pdf_file *pf) +{ + if (pf) + pf->file = NULL; +} + +void +pdf_files_close (void) +{ + ASSERT(pdf_files); + ht_clear_table(pdf_files); + RELEASE(pdf_files); +} + +static int +check_for_pdf_version (FILE *file) +{ + unsigned int minor; + + rewind(file); + + return (ungetc(fgetc(file), file) == '%' && + fscanf(file, "%%PDF-1.%u", &minor) == 1) ? minor : -1; +} + +int +check_for_pdf (FILE *file) +{ + int version = check_for_pdf_version(file); + + if (version < 0) /* not a PDF file */ + return 0; + + if (version <= pdf_version) + return 1; + + WARN("Version of PDF file (1.%c) is newer than version limit specification.", + pdf_version); + return 0; +} + +static int CDECL +import_dict (pdf_obj *key, pdf_obj *value, void *pdata) +{ + pdf_obj *copy; + pdf_obj *tmp; + + copy = (pdf_obj *) pdata; + + tmp = pdf_import_object(value); + if (!tmp) { + return -1; + } + pdf_add_dict(copy, pdf_link_obj(key), tmp); + + return 0; +} + +static pdf_obj loop_marker = { PDF_OBJ_INVALID, 0, 0, 0, 0, NULL }; + +static pdf_obj * +pdf_import_indirect (pdf_obj *object) +{ + pdf_file *pf = OBJ_FILE(object); + unsigned long obj_num = OBJ_NUM(object); + unsigned short obj_gen = OBJ_GEN(object); + + pdf_obj *ref; + + ASSERT(pf); + + if (!checklabel(pf, obj_num, obj_gen)) { + WARN("Can't resolve object: %lu %u", obj_num, obj_gen); + return pdf_new_null(); + } + + if ((ref = pf->xref_table[obj_num].indirect)) { + if (ref == &loop_marker) + ERROR("Loop in object hierarchy detected. Broken PDF file?"); + return pdf_link_obj(ref); + } else { + pdf_obj *obj, *tmp; + + obj = pdf_get_object(pf, obj_num, obj_gen); + if (!obj) { + WARN("Could not read object: %lu %u", obj_num, obj_gen); + return NULL; + } + + /* We mark the reference to be able to detect loops */ + pf->xref_table[obj_num].indirect = &loop_marker; + + tmp = pdf_import_object(obj); + + pf->xref_table[obj_num].indirect = ref = pdf_ref_obj(tmp); + + pdf_release_obj(tmp); + pdf_release_obj(obj); + + return pdf_link_obj(ref); + } +} + +/* + * pdf_import_object recursively copies the object and those + * referenced by it and changes the indirect references so that + * they refer to the current output file. New indirect references + * are remembered, which avoids duplicating objects when they + * are imported several times. + */ +pdf_obj * +pdf_import_object (pdf_obj *object) +{ + pdf_obj *imported; + pdf_obj *tmp; + int i; + + switch (pdf_obj_typeof(object)) { + + case PDF_INDIRECT: + if (OBJ_FILE(object)) { + imported = pdf_import_indirect(object); + } else { + imported = pdf_link_obj(object); + } + break; + + case PDF_STREAM: + { + pdf_obj *stream_dict; + + tmp = pdf_import_object(pdf_stream_dict(object)); + if (!tmp) + return NULL; + + imported = pdf_new_stream(0); + stream_dict = pdf_stream_dict(imported); + pdf_merge_dict(stream_dict, tmp); + pdf_release_obj(tmp); + pdf_add_stream(imported, + pdf_stream_dataptr(object), + pdf_stream_length(object)); + } + break; + + case PDF_DICT: + + imported = pdf_new_dict(); + if (pdf_foreach_dict(object, import_dict, imported) < 0) { + pdf_release_obj(imported); + return NULL; + } + + break; + + case PDF_ARRAY: + + imported = pdf_new_array(); + for (i = 0; i < pdf_array_length(object); i++) { + tmp = pdf_import_object(pdf_get_array(object, i)); + if (!tmp) { + pdf_release_obj(imported); + return NULL; + } + pdf_add_array(imported, tmp); + } + break; + + default: + imported = pdf_link_obj(object); + } + + return imported; +} + + +/* returns 0 if indirect references point to the same object */ +int +pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2) +{ + pdf_indirect *data1, *data2; + + ASSERT(PDF_OBJ_INDIRECTTYPE(ref1) && PDF_OBJ_INDIRECTTYPE(ref2)); + + data1 = (pdf_indirect *) ref1->data; + data2 = (pdf_indirect *) ref2->data; + + return data1->pf != data2->pf || data1->label != data2->label + || data1->generation != data2->generation; +} diff --git a/Build/source/texk/dvipdfm-x/pdfximage.c b/Build/source/texk/dvipdfm-x/pdfximage.c new file mode 100644 index 00000000000..1288516c454 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/pdfximage.c @@ -0,0 +1,970 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "error.h" +#include "mem.h" + +#include "dpxfile.h" + +#include "pdfobj.h" + +#include "pdfdoc.h" +#include "pdfdev.h" +#include "pdfdraw.h" + +#include "epdf.h" +#include "mpost.h" +#include "pngimage.h" +#include "jpegimage.h" +#include "bmpimage.h" + +#include "pdfximage.h" + +/* From psimage.h */ +static int check_for_ps (FILE *fp); +static int ps_include_page (pdf_ximage *ximage, const char *file_name); + + +#define IMAGE_TYPE_UNKNOWN -1 +#define IMAGE_TYPE_PDF 0 +#define IMAGE_TYPE_JPEG 1 +#define IMAGE_TYPE_PNG 2 +#define IMAGE_TYPE_MPS 4 +#define IMAGE_TYPE_EPS 5 +#define IMAGE_TYPE_BMP 6 + + +struct attr_ +{ + long width, height; + double xdensity, ydensity; + pdf_rect bbox; +}; + +struct pdf_ximage_ +{ + char *ident; + char res_name[16]; + long page_no, page_count; + + int subtype; + + struct attr_ attr; + + char *filename; + pdf_obj *reference; + pdf_obj *resource; + pdf_obj *attr_dict; + + char tempfile; +}; + + +/* verbose, verbose, verbose... */ +struct opt_ +{ + int verbose; + char *cmdtmpl; +}; + +static struct opt_ _opts = { + 0, NULL +}; + +void pdf_ximage_set_verbose (void) { _opts.verbose++; } + + +struct ic_ +{ + int count, capacity; + pdf_ximage *ximages; +}; + +static struct ic_ _ic = { + 0, 0, NULL +}; + +static void +pdf_init_ximage_struct (pdf_ximage *I, + const char *ident, const char *filename, + long page_no, pdf_obj *dict) +{ + if (ident) { + I->ident = NEW(strlen(ident)+1, char); + strcpy(I->ident, ident); + } else + I ->ident = NULL; + I->page_no = page_no; + I->page_count = 0; + if (filename) { + I->filename = NEW(strlen(filename)+1, char); + strcpy(I->filename, filename); + } else + I->filename = NULL; + I->subtype = -1; + memset(I->res_name, 0, 16); + I->reference = NULL; + I->resource = NULL; + I->attr_dict = dict; + + 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->tempfile = 0; +} + +static void +pdf_set_ximage_tempfile (pdf_ximage *I, const char *filename) +{ + if (I->filename) + RELEASE(I->filename); + I->filename = NEW(strlen(filename)+1, char); + strcpy(I->filename, filename); + I->tempfile = 1; +} + +static void +pdf_clean_ximage_struct (pdf_ximage *I) +{ + if (I->ident) + RELEASE(I->ident); + if (I->filename) + RELEASE(I->filename); + if (I->reference) + pdf_release_obj(I->reference); + if (I->resource) + pdf_release_obj(I->resource); + if (I->attr_dict) + pdf_release_obj(I->attr_dict); + pdf_init_ximage_struct(I, NULL, NULL, 0, NULL); +} + + +void +pdf_init_images (void) +{ + struct ic_ *ic = &_ic; + ic->count = 0; + ic->capacity = 0; + ic->ximages = NULL; +} + +void +pdf_close_images (void) +{ + struct ic_ *ic = &_ic; + if (ic->ximages) { + int i; + for (i = 0; i < ic->count; i++) { + pdf_ximage *I = ic->ximages+i; + if (I->tempfile) { + /* + * It is important to remove temporary files at the end because + * we cache file names. Since we use mkstemp to create them, we + * might get the same file name again if we delete the first file. + * (This happens on NetBSD, reported by Jukka Salmi.) + * We also use this to convert a PS file only once if multiple + * pages are imported from that file. + */ + if (_opts.verbose > 1 && keep_cache != 1) + MESG("pdf_image>> deleting temporary file \"%s\"\n", I->filename); + dpx_delete_temp_file(I->filename, false); /* temporary filename freed here */ + I->filename = NULL; + } + pdf_clean_ximage_struct(I); + } + RELEASE(ic->ximages); + ic->ximages = NULL; + ic->count = ic->capacity = 0; + } + + if (_opts.cmdtmpl) + RELEASE(_opts.cmdtmpl); + _opts.cmdtmpl = NULL; +} + +static int +source_image_type (FILE *fp) +{ + int format = IMAGE_TYPE_UNKNOWN; + + rewind(fp); + /* + * Make sure we check for PS *after* checking for MP since + * MP is a special case of PS. + */ + if (check_for_jpeg(fp)) + { + format = IMAGE_TYPE_JPEG; + } +#ifdef HAVE_LIBPNG + else if (check_for_png(fp)) + { + format = IMAGE_TYPE_PNG; + } +#endif + else if (check_for_bmp(fp)) + { + format = IMAGE_TYPE_BMP; + } else if (check_for_pdf(fp)) { + format = IMAGE_TYPE_PDF; + } else if (check_for_mp(fp)) { + format = IMAGE_TYPE_MPS; + } else if (check_for_ps(fp)) { + format = IMAGE_TYPE_EPS; + } else { + format = IMAGE_TYPE_UNKNOWN; + } + rewind(fp); + + return format; +} + +static int +load_image (const char *ident, const char *fullname, int format, FILE *fp, + long page_no, pdf_obj *dict) +{ + struct ic_ *ic = &_ic; + int id = -1; /* ret */ + pdf_ximage *I; + + id = ic->count; + if (ic->count >= ic->capacity) { + ic->capacity += 16; + ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); + } + + I = &ic->ximages[id]; + pdf_init_ximage_struct(I, ident, fullname, page_no, dict); + + switch (format) { + case IMAGE_TYPE_JPEG: + if (_opts.verbose) + MESG("[JPEG]"); + if (jpeg_include_image(I, fp) < 0) + goto error; + I->subtype = PDF_XOBJECT_TYPE_IMAGE; + break; +#ifdef HAVE_LIBPNG + case IMAGE_TYPE_PNG: + if (_opts.verbose) + MESG("[PNG]"); + if (png_include_image(I, fp) < 0) + goto error; + I->subtype = PDF_XOBJECT_TYPE_IMAGE; + break; +#endif + case IMAGE_TYPE_BMP: + if (_opts.verbose) + MESG("[BMP]"); + if (bmp_include_image(I, fp) < 0) + goto error; + I->subtype = PDF_XOBJECT_TYPE_IMAGE; + break; + case IMAGE_TYPE_PDF: + if (_opts.verbose) + MESG("[PDF]"); + { + int result = pdf_include_page(I, fp, fullname); + if (result > 0) + /* PDF version too recent */ + result = ps_include_page(I, fullname); + if (result < 0) + goto error; + } + if (_opts.verbose) + MESG(",Page:%ld", I->page_no); + I->subtype = PDF_XOBJECT_TYPE_FORM; + break; + // case IMAGE_TYPE_EPS: + default: + if (_opts.verbose) + MESG(format == IMAGE_TYPE_EPS ? "[PS]" : "[UNKNOWN]"); + if (ps_include_page(I, fullname) < 0) + goto error; + if (_opts.verbose) + MESG(",Page:%ld", I->page_no); + I->subtype = PDF_XOBJECT_TYPE_FORM; + } + + switch (I->subtype) { + case PDF_XOBJECT_TYPE_IMAGE: + sprintf(I->res_name, "Im%d", id); + break; + case PDF_XOBJECT_TYPE_FORM: + sprintf(I->res_name, "Fm%d", id); + break; + default: + ERROR("Unknown XObject subtype: %d", I->subtype); + goto error; + } + + ic->count++; + + return id; + + error: + pdf_clean_ximage_struct(I); + return -1; +} + + +#define dpx_find_file(n,d,s) (kpse_find_pict((n))) +#define dpx_fopen(n,m) (MFOPEN((n),(m))) +#define dpx_fclose(f) (MFCLOSE((f))) + +int +pdf_ximage_findresource (const char *ident, long page_no, pdf_obj *dict) +{ + struct ic_ *ic = &_ic; + int id = -1; + pdf_ximage *I; + char *fullname, *f = NULL; + int format; + FILE *fp; + + for (id = 0; id < ic->count; id++) { + I = &ic->ximages[id]; + if (I->ident && !strcmp(ident, I->ident)) { + f = I->filename; + if (I->page_no == page_no + (page_no < 0 ? I->page_count+1 : 0) && + I->attr_dict == dict) { + return id; + } + } + } + + if (f) { + /* we already have converted this file; f is the temporary file name */ + fullname = NEW(strlen(f)+1, char); + strcpy(fullname, f); + } else { + /* try loading image */ + fullname = dpx_find_file(ident, "_pic_", ""); + if (!fullname) { + WARN("Error locating image file \"%s\"", ident); + return -1; + } + } + + fp = dpx_fopen(fullname, FOPEN_RBIN_MODE); + if (!fp) { + WARN("Error opening image file \"%s\"", fullname); + RELEASE(fullname); + return -1; + } + if (_opts.verbose) { + MESG("(Image:%s", ident); + if (_opts.verbose > 1) + MESG("[%s]", fullname); + } + + format = source_image_type(fp); + switch (format) { + case IMAGE_TYPE_MPS: + if (_opts.verbose) + MESG("[MPS]"); + id = mps_include_page(ident, fp); + if (id < 0) { + WARN("Try again with the distiller."); + format = IMAGE_TYPE_EPS; + rewind(fp); + } else + break; + default: + id = load_image(ident, fullname, format, fp, page_no, dict); + break; + } + dpx_fclose(fp); + + RELEASE(fullname); + + if (_opts.verbose) + MESG(")"); + + if (id < 0) + WARN("pdf: image inclusion failed for \"%s\".", ident); + + 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) +{ + info->flags = 0; + info->bbox.llx = 0; + info->bbox.lly = 0; + info->bbox.urx = 0; + info->bbox.ury = 0; + info->matrix.a = 1.0; + info->matrix.b = 0.0; + info->matrix.c = 0.0; + info->matrix.d = 1.0; + info->matrix.e = 0.0; + 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) +{ + info->flags = 0; + info->width = 0; + info->height = 0; + info->bits_per_component = 0; + info->num_components = 0; + info->min_dpi = 0; + info->xdensity = info->ydensity = 1.0; +} + +#ifdef XETEX +char * +pdf_ximage_get_ident (pdf_ximage *I) +{ + return I->ident; +} +#endif + +void +pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) +{ + pdf_obj *dict; + ximage_info *info = image_info; + + if (!PDF_OBJ_STREAMTYPE(resource)) + ERROR("Image XObject must be of stream type."); + + I->subtype = PDF_XOBJECT_TYPE_IMAGE; + + 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); + + dict = pdf_stream_dict(resource); + pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("XObject")); + pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image")); + pdf_add_dict(dict, pdf_new_name("Width"), pdf_new_number(info->width)); + pdf_add_dict(dict, pdf_new_name("Height"), pdf_new_number(info->height)); + pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), + pdf_new_number(info->bits_per_component)); + if (I->attr_dict) + pdf_merge_dict(dict, I->attr_dict); + + pdf_release_obj(resource); /* Caller don't know we are using reference. */ + I->resource = NULL; +} + +void +pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) +{ + 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; +} + +#define CHECK_ID(c,n) do {\ + if ((n) < 0 || (n) >= (c)->count) {\ + ERROR("Invalid XObject ID: %d", (n));\ + }\ +} while (0) +#define GET_IMAGE(c,n) (&((c)->ximages[(n)])) + +pdf_obj * +pdf_ximage_get_reference (int id) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + if (!I->reference) + I->reference = pdf_ref_obj(I->resource); + + 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; + + id = ic->count; + if (ic->count >= ic->capacity) { + ic->capacity += 16; + ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); + } + + I = &ic->ximages[id]; + + pdf_init_ximage_struct(I, ident, NULL, 0, NULL); + + switch (subtype) { + case PDF_XOBJECT_TYPE_IMAGE: + pdf_ximage_set_image(I, info, resource); + sprintf(I->res_name, "Im%d", id); + break; + case PDF_XOBJECT_TYPE_FORM: + pdf_ximage_set_form (I, info, resource); + sprintf(I->res_name, "Fm%d", id); + break; + default: + ERROR("Unknown XObject subtype: %d", subtype); + } + ic->count++; + + return id; +} + + +char * +pdf_ximage_get_resname (int id) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + + return I->res_name; +} + +int +pdf_ximage_get_subtype (int id) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + + return I->subtype; +} + +void +pdf_ximage_set_attr (int id, long width, long height, double xdensity, double ydensity, double llx, double lly, double urx, double ury) +{ + struct ic_ *ic = &_ic; + pdf_ximage *I; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, id); + I->attr.width = width; + I->attr.height = height; + I->attr.xdensity = xdensity; + I->attr.ydensity = ydensity; + I->attr.bbox.llx = llx; + I->attr.bbox.lly = lly; + I->attr.bbox.urx = urx; + I->attr.bbox.ury = ury; +} + +/* 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 + +static void +scale_to_fit_I (pdf_tmatrix *T, + transform_info *p, + pdf_ximage *I) +{ + double s_x, s_y, d_x, d_y; + double wd0, ht0, dp, xscale, yscale; + + 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; + } + + if (wd0 == 0.0) { + WARN("Image width=0.0!"); + wd0 = 1.0; + } + if (ht0 == 0.0) { + WARN("Image height=0.0!"); + ht0 = 1.0; + } + + if ( (p->flags & INFO_HAS_WIDTH ) && + (p->flags & INFO_HAS_HEIGHT) ) { + 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) * yscale; + s_x = s_y * ((double)I->attr.width / I->attr.height); + dp = p->depth * yscale; + } else { + 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 = d_x * s_x / xscale; T->f = d_y * s_y / yscale - dp; + + return; +} + + +static void +scale_to_fit_F (pdf_tmatrix *T, + transform_info *p, + pdf_ximage *I) +{ + double s_x, s_y, d_x, d_y; + double wd0, ht0, dp; + + if (p->flags & INFO_HAS_USER_BBOX) { + wd0 = p->bbox.urx - p->bbox.llx; + ht0 = p->bbox.ury - p->bbox.lly; + d_x = -p->bbox.llx; + d_y = -p->bbox.lly; + } else { + wd0 = I->attr.bbox.urx - I->attr.bbox.llx; + ht0 = I->attr.bbox.ury - I->attr.bbox.lly; + d_x = 0.0; + d_y = 0.0; + } + + if (wd0 == 0.0) { + WARN("Image width=0.0!"); + wd0 = 1.0; + } + if (ht0 == 0.0) { + WARN("Image height=0.0!"); + ht0 = 1.0; + } + + if ( (p->flags & INFO_HAS_WIDTH ) && + (p->flags & INFO_HAS_HEIGHT) ) { + s_x = p->width / wd0; + s_y = (p->height + p->depth) / ht0; + dp = p->depth; + } else if ( p->flags & INFO_HAS_WIDTH ) { + s_x = p->width / wd0; + s_y = s_x; + dp = 0.0; + } else if ( p->flags & INFO_HAS_HEIGHT) { + s_y = (p->height + p->depth) / ht0; + s_x = s_y; + dp = p->depth; + } else { + s_x = s_y = 1.0; + dp = 0.0; + } + + T->a = s_x; T->c = 0.0; + T->b = 0.0; T->d = s_y; + T->e = s_x * d_x; T->f = s_y * d_y - dp; + + return; +} + + +/* called from pdfdev.c and spc_html.c */ +int +pdf_ximage_scale_image (int id, + 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; + + CHECK_ID(ic, id); + + I = GET_IMAGE(ic, 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); + 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) { + r->llx = p->bbox.llx; + r->lly = p->bbox.lly; + r->urx = p->bbox.urx; + r->ury = p->bbox.ury; + } 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; + r->ury = I->attr.bbox.ury; + } + break; + } + + return 0; +} + + +/* Migrated from psimage.c */ + +void set_distiller_template (char *s) +{ + if (_opts.cmdtmpl) + RELEASE(_opts.cmdtmpl); + if (!s || *s == '\0') + _opts.cmdtmpl = NULL; + else { + _opts.cmdtmpl = NEW(strlen(s) + 1, char); + strcpy(_opts.cmdtmpl, s); + } + return; +} + +#ifdef XETEX +char *get_distiller_template (void) +{ + return _opts.cmdtmpl; +} +#endif + +static int +ps_include_page (pdf_ximage *ximage, const char *filename) +{ + char *distiller_template = _opts.cmdtmpl; + char *temp; + FILE *fp; + int error = 0; + struct stat stat_o, stat_t; + + if (!distiller_template) { + WARN("No image converter available for converting file \"%s\" to PDF format.", filename); + WARN(">> Please check if you have 'D' option in config file."); + return -1; + } + + temp = dpx_create_fix_temp_file(filename); + if (!temp) { + WARN("Failed to create temporary file for image conversion: %s", filename); + return -1; + } + +#ifdef MIKTEX + { + char *p; + for (p = (char *)filename; *p; p++) { + if (*p == '\\') *p = '/'; + } + for (p = (char *)temp; *p; p++) { + if (*p == '\\') *p = '/'; + } + } +#endif + + if (keep_cache != -1 && stat(temp, &stat_t)==0 && stat(filename, &stat_o)==0 + && stat_t.st_mtime > stat_o.st_mtime) { + /* cache exist */ + /*printf("\nLast file modification: %s", ctime(&stat_o.st_mtime)); + printf("Last file modification: %s", ctime(&stat_t.st_mtime));*/ + ; + } else { + if (_opts.verbose > 1) { + MESG("\n"); + MESG("pdf_image>> Converting file \"%s\" --> \"%s\" via:\n", filename, temp); + MESG("pdf_image>> %s\n", distiller_template); + MESG("pdf_image>> ..."); + } + error = dpx_file_apply_filter(distiller_template, filename, temp, + (unsigned char) pdf_get_version()); + if (error) { + WARN("Image format conversion for \"%s\" failed...", filename); + dpx_delete_temp_file(temp, true); + return error; + } + } + + fp = MFOPEN(temp, FOPEN_RBIN_MODE); + if (!fp) { + WARN("Could not open conversion result \"%s\" for image \"%s\". Why?", temp, filename); + dpx_delete_temp_file(temp, true); + return -1; + } + pdf_set_ximage_tempfile(ximage, temp); +#if 0 + error = pdf_include_page(ximage, fp, 0, pdfbox_crop); +#endif + error = pdf_include_page(ximage, fp, temp); + MFCLOSE(fp); + + /* See pdf_close_images for why we cannot delete temporary files here. */ + + RELEASE(temp); + + if (error) { + WARN("Failed to include image file \"%s\"", filename); + WARN(">> Please check if"); + WARN(">> %s", distiller_template); + WARN(">> %%o = output filename, %%i = input filename, %%b = input filename without suffix"); + WARN(">> can really convert \"%s\" to PDF format image.", filename); + } + + return error; +} + +static int check_for_ps (FILE *image_file) +{ + rewind (image_file); + mfgets (work_buffer, WORK_BUFFER_SIZE, image_file); + if (!strncmp (work_buffer, "%!", 2)) + return 1; + return 0; +} diff --git a/Build/source/texk/dvipdfm-x/spc_pdfm.c b/Build/source/texk/dvipdfm-x/spc_pdfm.c new file mode 100644 index 00000000000..e5ae24f1294 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/spc_pdfm.c @@ -0,0 +1,2143 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" + +#include "numbers.h" + +#include "fontmap.h" +#include "dpxfile.h" +#include "dpxutil.h" + +#include "pdfobj.h" +#include "pdfparse.h" + +#include "pdfdoc.h" + +#include "pdfximage.h" +#include "pdfdraw.h" +#include "pdfcolor.h" +#include "pdfdev.h" + +#include "specials.h" + +#include "spc_util.h" +#include "spc_pdfm.h" + +#include "dvipdfmx.h" + +#define ENABLE_TOUNICODE 1 + + +/* PLEASE REMOVE THIS */ +struct resource_map { + int type; + int res_id; +}; + +#ifdef ENABLE_TOUNICODE +struct tounicode { + int cmap_id; + int unescape_backslash; + pdf_obj *taintkeys; /* An array of PDF names. */ +}; +#endif /* ENABLE_TOUNICODE */ + +struct spc_pdf_ +{ + pdf_obj *annot_dict; /* pending annotation dict */ + int lowest_level; /* current min level of outlines */ + struct ht_table *resourcemap; /* see remark below (somewhere) */ +#ifdef ENABLE_TOUNICODE + struct tounicode cd; /* For to-UTF16-BE conversion :( */ +#endif /* ENABLE_TOUNICODE */ +}; + +#if 1 +static struct spc_pdf_ _pdf_stat = { + NULL, + 255, + NULL, +#ifdef ENABLE_TOUNICODE + { -1, 0, NULL } +#endif /* ENABLE_TOUNICODE */ +}; +#endif + +/* PLEASE REMOVE THIS */ +static void +hval_free (void *vp) +{ + RELEASE(vp); +} + + +static int +addresource (struct spc_pdf_ *sd, const char *ident, int res_id) +{ + struct resource_map *r; + + if (!ident || res_id < 0) + return -1; + + r = NEW(1, struct resource_map); + r->type = 0; /* unused */ + r->res_id = res_id; + + ht_append_table(sd->resourcemap, ident, strlen(ident), r); + spc_push_object(ident, pdf_ximage_get_reference(res_id)); + + return 0; +} + +static int +findresource (struct spc_pdf_ *sd, const char *ident) +{ + struct resource_map *r; + + if (!ident) + return -1; + + r = ht_lookup_table(sd->resourcemap, ident, strlen(ident)); + + return (r ? r->res_id : -1); +} + + +static int +spc_handler_pdfm__init (struct spc_env *spe, struct spc_arg *ap, void *dp) +{ + struct spc_pdf_ *sd = dp; +#ifdef ENABLE_TOUNICODE + static const char *default_taintkeys[] = { + "Title", "Author", "Subject", "Keywords", + "Creator", "Producer", "Contents", "Subj", + "TU", "T", "TM", NULL /* EOD */ + }; + int i; +#endif /* ENABLE_TOUNICODE */ + + sd->annot_dict = NULL; + sd->lowest_level = 255; + sd->resourcemap = NEW(1, struct ht_table); + ht_init_table(sd->resourcemap, hval_free); + +#ifdef ENABLE_TOUNICODE + sd->cd.taintkeys = pdf_new_array(); + for (i = 0; default_taintkeys[i] != NULL; i++) { + pdf_add_array(sd->cd.taintkeys, + pdf_new_name(default_taintkeys[i])); + } +#endif /* ENABLE_TOUNICODE */ + + return 0; +} + +static int +spc_handler_pdfm__clean (struct spc_env *spe, struct spc_arg *ap, void *dp) +{ + struct spc_pdf_ *sd = dp; + + if (sd->annot_dict) { + WARN("Unbalanced bann and eann found."); + pdf_release_obj(sd->annot_dict); + } + sd->lowest_level = 255; + sd->annot_dict = NULL; + if (sd->resourcemap) { + ht_clear_table(sd->resourcemap); + RELEASE(sd->resourcemap); + } + sd->resourcemap = NULL; + +#ifdef ENABLE_TOUNICODE + if (sd->cd.taintkeys) + pdf_release_obj(sd->cd.taintkeys); + sd->cd.taintkeys = NULL; +#endif /* ENABLE_TOUNICODE */ + + return 0; +} + + +int +spc_pdfm_at_begin_document (void) +{ + struct spc_pdf_ *sd = &_pdf_stat; + return spc_handler_pdfm__init(NULL, NULL, sd); +} + +int +spc_pdfm_at_end_document (void) +{ + struct spc_pdf_ *sd = &_pdf_stat; + return spc_handler_pdfm__clean(NULL, NULL, sd); +} + + +/* Dvipdfm specials */ +static int +spc_handler_pdfm_bop (struct spc_env *spe, struct spc_arg *args) +{ + if (args->curptr < args->endptr) { + pdf_doc_set_bop_content(args->curptr, + (long) (args->endptr - args->curptr)); + } + + args->curptr = args->endptr; + + return 0; +} + +static int +spc_handler_pdfm_eop (struct spc_env *spe, struct spc_arg *args) +{ + if (args->curptr < args->endptr) { + pdf_doc_set_eop_content(args->curptr, + (long) (args->endptr - args->curptr)); + } + + args->curptr = args->endptr; + + return 0; +} + +#define streamfiltered(o) \ + (pdf_lookup_dict(pdf_stream_dict((o)), "Filter") ? 1 : 0) + +/* Why should we have this kind of things? */ +static int +safeputresdent (pdf_obj *kp, pdf_obj *vp, void *dp) +{ + char *key; + + ASSERT(kp && vp && dp); + + key = pdf_name_value(kp); + if (pdf_lookup_dict(dp, key)) + WARN("Object \"%s\" already defined in dict! (ignored)", key); + else { + pdf_add_dict(dp, + pdf_link_obj(kp), pdf_link_obj(vp)); + } + return 0; +} + +#ifndef pdf_obj_isaref +#define pdf_obj_isaref(o) (pdf_obj_typeof((o)) == PDF_INDIRECT) +#endif + +static int +safeputresdict (pdf_obj *kp, pdf_obj *vp, void *dp) +{ + char *key; + pdf_obj *dict; + + ASSERT(kp && vp && dp); + + key = pdf_name_value(kp); + dict = pdf_lookup_dict(dp, key); + + if (pdf_obj_isaref(vp)) { + pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); + } else if (pdf_obj_typeof(vp) == PDF_DICT) { + if (dict) + pdf_foreach_dict(vp, safeputresdent, dict); + else { + pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); + } + } else { + WARN("Invalid type (not DICT) for page/form resource dict entry: key=\"%s\"", key); + return -1; + } + + return 0; +} + + +/* Think what happens if you do + * + * pdf:put @resources << /Font << >> >> + * + */ +static int +spc_handler_pdfm_put (struct spc_env *spe, struct spc_arg *ap) +{ + pdf_obj *obj1, *obj2; /* put obj2 into obj1 */ + char *ident; + int error = 0; + + skip_white(&ap->curptr, ap->endptr); + + ident = parse_opt_ident(&ap->curptr, ap->endptr); + if (!ident) { + spc_warn(spe, "Missing object identifier."); + return -1; + } + obj1 = spc_lookup_object(ident); + if (!obj1) { + spc_warn(spe, "Specified object not exist: %s", ident); + RELEASE(ident); + return -1; + } + skip_white(&ap->curptr, ap->endptr); + + obj2 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); + if (!obj2) { + spc_warn(spe, "Missing (an) object(s) to put into \"%s\"!", ident); + RELEASE(ident); + return -1; + } + + switch (pdf_obj_typeof(obj1)) { + case PDF_DICT: + if (pdf_obj_typeof(obj2) != PDF_DICT) { + spc_warn(spe, "Inconsistent object type for \"put\" (expecting DICT): %s", ident); + error = -1; + } else { + if (!strcmp(ident, "resources")) + error = pdf_foreach_dict(obj2, safeputresdict, obj1); + else { + pdf_merge_dict(obj1, obj2); + } + } + break; + + case PDF_STREAM: + if (pdf_obj_typeof(obj2) == PDF_DICT) + pdf_merge_dict(pdf_stream_dict(obj1), obj2); + else if (pdf_obj_typeof(obj2) == PDF_STREAM) +#if 0 + { + pdf_merge_dict(pdf_stream_dict(obj1), pdf_stream_dict(obj2)); + pdf_add_stream(obj1, pdf_stream_dataptr(obj2), pdf_stream_length(obj2)); + } +#else + { + spc_warn(spe, "\"put\" operation not supported for STREAM <- STREAM: %s", ident); + error = -1; + } +#endif + else { + spc_warn(spe, "Invalid type: expecting a DICT or STREAM: %s", ident); + error = -1; + } + break; + + case PDF_ARRAY: + /* dvipdfm */ + pdf_add_array(obj1, pdf_link_obj(obj2)); + while (ap->curptr < ap->endptr) { + pdf_obj *obj3 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); + if (!obj3) + break; + pdf_add_array(obj1, obj3); + skip_white(&ap->curptr, ap->endptr); + } + break; + + default: + spc_warn(spe, "Can't \"put\" object into non-DICT/STREAM/ARRAY type object: %s", ident); + error = -1; + break; + } + pdf_release_obj(obj2); + RELEASE(ident); + + return error; +} + + +#ifdef ENABLE_TOUNICODE + +/* For pdf:tounicode support + * This feature is provided for convenience. TeX can't do + * input encoding conversion. + */ +#include "cmap.h" + +static int +reencodestring (CMap *cmap, pdf_obj *instring) +{ +#define WBUF_SIZE 4096 + unsigned char wbuf[WBUF_SIZE]; + unsigned char *obufcur; + const unsigned char *inbufcur; + long inbufleft, obufleft; + + if (!cmap || !instring) + return 0; + + inbufleft = pdf_string_length(instring); + inbufcur = pdf_string_value (instring); + + wbuf[0] = 0xfe; + wbuf[1] = 0xff; + obufcur = wbuf + 2; + obufleft = WBUF_SIZE - 2; + + CMap_decode(cmap, + &inbufcur, &inbufleft, + &obufcur, &obufleft); + + if (inbufleft > 0) { + return -1; + } + + pdf_set_string(instring, wbuf, WBUF_SIZE - obufleft); + + return 0; +} + +#ifdef XETEX +/* tables/values used in UTF-8 interpretation - + code is based on ConvertUTF.[ch] sample code + published by the Unicode consortium */ +static unsigned long +offsetsFromUTF8[6] = { + 0x00000000UL, + 0x00003080UL, + 0x000E2080UL, + 0x03C82080UL, + 0xFA082080UL, + 0x82082080UL +}; + +static unsigned char +bytesFromUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +static int +maybe_reencode_utf8(pdf_obj *instring) +{ + unsigned char* inbuf; + int inlen; + int non_ascii = 0; + unsigned char* cp; + unsigned char* op; + unsigned char wbuf[WBUF_SIZE]; + + if (!instring) + return 0; + + inlen = pdf_string_length(instring); + inbuf = pdf_string_value(instring); + + /* check if the input string is strictly ASCII */ + for (cp = inbuf; cp < inbuf + inlen; ++cp) { + if (*cp > 127) { + non_ascii = 1; + } + } + if (non_ascii == 0) + return 0; /* no need to reencode ASCII strings */ + + cp = inbuf; + op = wbuf; + *op++ = 0xfe; + *op++ = 0xff; + while (cp < inbuf + inlen) { + unsigned long usv = *cp++; + int extraBytes = bytesFromUTF8[usv]; + if (cp + extraBytes > inbuf + inlen) + return -1; /* ill-formed, so give up reencoding */ + switch (extraBytes) { /* note: code falls through cases! */ + case 5: usv <<= 6; usv += *cp++; + case 4: usv <<= 6; usv += *cp++; + case 3: usv <<= 6; usv += *cp++; + case 2: usv <<= 6; usv += *cp++; + case 1: usv <<= 6; usv += *cp++; + case 0: ; + }; + usv -= offsetsFromUTF8[extraBytes]; + if (usv > 0x10FFFF) + return -1; /* out of valid Unicode range, give up */ + if (usv > 0xFFFF) { + /* supplementary-plane character: generate high surrogate */ + unsigned long hi = 0xdc00 + (usv - 0x10000) % 0x0400; + if (op > wbuf + WBUF_SIZE - 2) + return -1; /* out of space */ + *op++ = hi / 256; + *op++ = hi % 256; + usv = 0xd800 + (usv - 0x10000) / 0x0400; + /* remaining value in usv is the low surrogate */ + } + if (op > wbuf + WBUF_SIZE - 2) + return -1; /* out of space */ + *op++ = usv / 256; + *op++ = usv % 256; + } + + pdf_set_string(instring, wbuf, op - wbuf); + + return 0; +} +#endif + +static int +needreencode (pdf_obj *kp, pdf_obj *vp, struct tounicode *cd) +{ + int r = 0, i; + pdf_obj *tk; + + ASSERT( cd && cd->taintkeys ); + ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); + ASSERT( pdf_obj_typeof(vp) == PDF_STRING ); + + for (i = 0; i < pdf_array_length(cd->taintkeys); i++) { + tk = pdf_get_array(cd->taintkeys, i); + ASSERT( tk && pdf_obj_typeof(tk) == PDF_NAME ); + if (!strcmp(pdf_name_value(kp), pdf_name_value(tk))) { + r = 1; + break; + } + } + if (r) { + /* Check UTF-16BE BOM. */ + if (pdf_string_length(vp) >= 2 && + !memcmp(pdf_string_value(vp), "\xfe\xff", 2)) + r = 0; + } + + return r; +} + +static int modstrings (pdf_obj *key, pdf_obj *value, void *pdata); + +static int +modstrings (pdf_obj *kp, pdf_obj *vp, void *dp) +{ + int r = 0; /* continue */ + struct tounicode *cd = dp; + + ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); + +#ifndef XETEX + if (!cd || cd->cmap_id < 0 || !cd->taintkeys) + return -1; +#endif + + switch (pdf_obj_typeof(vp)) { + case PDF_STRING: + { + CMap *cmap; + +#ifdef XETEX + if (cd && cd->cmap_id >= 0 && cd->taintkeys) +#endif + { + cmap = CMap_cache_get(cd->cmap_id); + if (needreencode(kp, vp, cd)) { + r = reencodestring(cmap, vp); + } + } +#ifdef XETEX + else { + r = maybe_reencode_utf8(vp); + } +#endif + if (r < 0) /* error occured... */ + WARN("Failed to convert input string to UTF16..."); + } + break; + case PDF_DICT: + r = pdf_foreach_dict(vp, modstrings, dp); + break; + case PDF_STREAM: + r = pdf_foreach_dict(pdf_stream_dict(vp), modstrings, dp); + break; + } + + return r; +} + +static pdf_obj * +my_parse_pdf_dict (const char **pp, const char *endptr, struct tounicode *cd) +{ + pdf_obj *dict; + +#ifdef XETEX +/* disable this test, as we do utf8 reencoding with no cmap */ +#else + if (cd->cmap_id < 0) + return parse_pdf_dict(pp, endptr, NULL); +#endif + + /* :( */ + if (cd && cd->unescape_backslash) + dict = parse_pdf_tainted_dict(pp, endptr); + else { + dict = parse_pdf_dict(pp, endptr, NULL); + } + if (dict) + pdf_foreach_dict(dict, modstrings, cd); + + return dict; +} + +#endif /* ENABLE_TOUNICODE */ + + +static int +spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) +{ +#ifdef ENABLE_TOUNICODE + struct spc_pdf_ *sd = &_pdf_stat; +#endif /* ENABLE_TOUNICODE */ + pdf_obj *annot_dict; + pdf_rect rect; + char *ident = NULL; + pdf_coord cp; + transform_info ti; + + skip_white(&args->curptr, args->endptr); + if (args->curptr[0] == '@') { + ident = parse_opt_ident(&args->curptr, args->endptr); + skip_white(&args->curptr, args->endptr); + } + + transform_info_clear(&ti); + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { + if (ident) + RELEASE(ident); + return -1; + } + + if ((ti.flags & INFO_HAS_USER_BBOX) && + ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { + spc_warn(spe, "You can't specify both bbox and width/height."); + if (ident) + RELEASE(ident); + return -1; + } + +#ifdef ENABLE_TOUNICODE + annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!annot_dict) { + spc_warn(spe, "Could not find dictionary object."); + if (ident) + RELEASE(ident); + return -1; + } else if (!PDF_OBJ_DICTTYPE(annot_dict)) { + spc_warn(spe, "Invalid type: not dictionary object."); + if (ident) + RELEASE(ident); + pdf_release_obj(annot_dict); + return -1; + } + + cp.x = spe->x_user; cp.y = spe->y_user; + pdf_dev_transform(&cp, NULL); + if (ti.flags & INFO_HAS_USER_BBOX) { + rect.llx = ti.bbox.llx + cp.x; + rect.lly = ti.bbox.lly + cp.y; + rect.urx = ti.bbox.urx + cp.x; + rect.ury = ti.bbox.ury + cp.y; + } else { + rect.llx = cp.x; + rect.lly = cp.y - spe->mag * ti.depth; + rect.urx = cp.x + spe->mag * ti.width; + rect.ury = cp.y + spe->mag * ti.height; + } + + /* Order is important... */ + if (ident) + spc_push_object(ident, pdf_link_obj(annot_dict)); + /* Add this reference. */ + pdf_doc_add_annot(pdf_doc_current_page_number(), &rect, annot_dict, 1); + + if (ident) { + spc_flush_object(ident); + RELEASE(ident); + } + pdf_release_obj(annot_dict); + + return 0; +} + +/* NOTE: This can't have ident. See "Dvipdfm User's Manual". */ +static int +spc_handler_pdfm_bann (struct spc_env *spe, struct spc_arg *args) +{ + struct spc_pdf_ *sd = &_pdf_stat; + int error = 0; + + if (sd->annot_dict) { + spc_warn(spe, "Can't begin an annotation when one is pending."); + return -1; + } + + skip_white(&args->curptr, args->endptr); + +#ifdef ENABLE_TOUNICODE + sd->annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + sd->annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!sd->annot_dict) { + spc_warn(spe, "Ignoring annotation with invalid dictionary."); + return -1; + } else if (!PDF_OBJ_DICTTYPE(sd->annot_dict)) { + spc_warn(spe, "Invalid type: not a dictionary object."); + pdf_release_obj(sd->annot_dict); + sd->annot_dict = NULL; + return -1; + } + + error = spc_begin_annot(spe, sd->annot_dict); + + return error; +} + +static int +spc_handler_pdfm_eann (struct spc_env *spe, struct spc_arg *args) +{ + struct spc_pdf_ *sd = &_pdf_stat; + int error = 0; + + if (!sd->annot_dict) { + spc_warn(spe, "Tried to end an annotation without starting one!"); + return -1; + } + + error = spc_end_annot(spe); + + pdf_release_obj(sd->annot_dict); + sd->annot_dict = NULL; + + return error; +} + + +/* Color:.... */ +static int +spc_handler_pdfm_bcolor (struct spc_env *spe, struct spc_arg *ap) +{ + int error; + pdf_color fc, sc; + pdf_color *pfc, *psc; + + pdf_color_get_current(&psc, &pfc); + error = spc_util_read_pdfcolor(spe, &fc, ap, pfc); + if (!error) { + if (ap->curptr < ap->endptr) { + error = spc_util_read_pdfcolor(spe, &sc, ap, psc); + } else { + pdf_color_copycolor(&sc, &fc); + } + } + + if (error) + spc_warn(spe, "Invalid color specification?"); + else { + pdf_color_push(&sc, &fc); /* save currentcolor */ +#ifdef XETEX + pdf_dev_set_strokingcolor(&sc); + pdf_dev_set_nonstrokingcolor(&fc); +#endif + } + + return error; +} + +/* + * This special changes the current color without clearing the color stack. + * It therefore differs from "color rgb 1 0 0". + */ +static int +spc_handler_pdfm_scolor (struct spc_env *spe, struct spc_arg *ap) +{ + int error; + pdf_color fc, sc; + pdf_color *pfc, *psc; + + pdf_color_get_current(&psc, &pfc); + error = spc_util_read_pdfcolor(spe, &fc, ap, pfc); + if (!error) { + if (ap->curptr < ap->endptr) { + error = spc_util_read_pdfcolor(spe, &sc, ap, psc); + } else { + pdf_color_copycolor(&sc, &fc); + } + } + + if (error) + spc_warn(spe, "Invalid color specification?"); + else + pdf_color_set(&sc, &fc); + + return error; +} + +static int +spc_handler_pdfm_ecolor (struct spc_env *spe, struct spc_arg *args) +{ + pdf_color_pop(); + return 0; +} + + +static int +spc_handler_pdfm_btrans (struct spc_env *spe, struct spc_arg *args) +{ + pdf_tmatrix M; + transform_info ti; + + transform_info_clear(&ti); + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { + return -1; + } + + /* Create transformation matrix */ + pdf_copymatrix(&M, &(ti.matrix)); + 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); + + pdf_dev_gsave(); + pdf_dev_concat(&M); + + return 0; +} + +static int +spc_handler_pdfm_etrans (struct spc_env *spe, struct spc_arg *args) +{ + pdf_dev_grestore(); + + /* + * Unfortunately, the following line is necessary in case + * of a color change inside of the save/restore pair. + * (Font changes are automatically corrected by pdf_dev_grestore().) + * Anything that was done there must be redone, so in effect, + * we make no assumptions about what fonts. We act like we are + * starting a new page. + */ + pdf_dev_reset_color(0); + + return 0; +} + +static int +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, 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, NULL); + if (!tmp) { + spc_warn(spe, "Missing number for outline item depth."); + return -1; + } else if (!PDF_OBJ_NUMBERTYPE(tmp)) { + pdf_release_obj(tmp); + spc_warn(spe, "Expecting number for outline item depth."); + return -1; + } + + item_dict = NULL; + + level = (int) pdf_number_value(tmp); + pdf_release_obj(tmp); + + /* What is this? Starting at level 3 and can go down to level 1? + * + * Here is the original comment: + * Make sure we know where the starting level is + * + * NOTE: added + * We need this for converting pages from 3rd to... :( + */ + sd->lowest_level = MIN(sd->lowest_level, level); + + level += 1 - sd->lowest_level; + +#ifdef ENABLE_TOUNICODE + item_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + item_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!item_dict) { + spc_warn(spe, "Ignoring invalid dictionary."); + return -1; + } + current_depth = pdf_doc_bookmarks_depth(); + if (current_depth > level) { + while (current_depth-- > level) + pdf_doc_bookmarks_up(); + } else if (current_depth < level) { + while (current_depth++ < level) + pdf_doc_bookmarks_down(); + } + + pdf_doc_bookmarks_add(item_dict, is_open); + + return 0; +} + +static int +spc_handler_pdfm_article (struct spc_env *spe, struct spc_arg *args) +{ +#ifdef ENABLE_TOUNICODE + struct spc_pdf_ *sd = &_pdf_stat; +#endif /* ENABLE_TOUNICODE */ + char *ident; + pdf_obj *info_dict; + + skip_white (&args->curptr, args->endptr); + + ident = parse_opt_ident(&args->curptr, args->endptr); + if (!ident) { + spc_warn(spe, "Article name expected but not found."); + return -1; + } + +#ifdef ENABLE_TOUNICODE + info_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + info_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!info_dict) { + spc_warn(spe, "Ignoring article with invalid info dictionary."); + RELEASE(ident); + return -1; + } + + pdf_doc_begin_article(ident, pdf_link_obj(info_dict)); + spc_push_object(ident, info_dict); + RELEASE(ident); + + return 0; +} + +static int +spc_handler_pdfm_bead (struct spc_env *spe, struct spc_arg *args) +{ +#ifdef ENABLE_TOUNICODE + struct spc_pdf_ *sd = &_pdf_stat; +#endif /* ENABLE_TOUNICODE */ + pdf_obj *article; + pdf_obj *article_info; + char *article_name; + pdf_rect rect; + long page_no; + transform_info ti; + pdf_coord cp; + + skip_white(&args->curptr, args->endptr); + + if (args->curptr[0] != '@') { + spc_warn(spe, "Article identifier expected but not found."); + return -1; + } + + article_name = parse_opt_ident(&args->curptr, args->endptr); + if (!article_name) { + spc_warn(spe, "Article reference expected but not found."); + return -1; + } + + /* If okay so far, try to get a bounding box */ + transform_info_clear(&ti); + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { + RELEASE(article_name); + return -1; + } + + if ((ti.flags & INFO_HAS_USER_BBOX) && + ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { + spc_warn(spe, "You can't specify both bbox and width/height."); + RELEASE(article_name); + return -1; + } + + cp.x = spe->x_user; cp.y = spe->y_user; + pdf_dev_transform(&cp, NULL); + if (ti.flags & INFO_HAS_USER_BBOX) { + rect.llx = ti.bbox.llx + cp.x; + rect.lly = ti.bbox.lly + cp.y; + rect.urx = ti.bbox.urx + cp.x; + rect.ury = ti.bbox.ury + cp.y; + } else { + rect.llx = cp.x; + rect.lly = cp.y - spe->mag * ti.depth; + rect.urx = cp.x + spe->mag * ti.width; + rect.ury = cp.y + spe->mag * ti.height; + } + + skip_white(&args->curptr, args->endptr); + if (args->curptr[0] != '<') { + article_info = pdf_new_dict(); + } else { +#ifdef ENABLE_TOUNICODE + article_info = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + article_info = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!article_info) { + spc_warn(spe, "Error in reading dictionary."); + RELEASE(article_name); + return -1; + } + } + + /* Does this article exist yet */ + article = spc_lookup_object(article_name); + if (article) { + pdf_merge_dict (article, article_info); + pdf_release_obj(article_info); + } else { + pdf_doc_begin_article(article_name, pdf_link_obj(article_info)); + spc_push_object(article_name, article_info); + } + page_no = pdf_doc_current_page_number(); + pdf_doc_add_bead(article_name, NULL, page_no, &rect); + + RELEASE(article_name); + return 0; +} + +static int +spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) +{ + struct spc_pdf_ *sd = &_pdf_stat; + int xobj_id; + char *ident = NULL; + pdf_obj *fspec, *attr = NULL; + transform_info ti; + long page_no; + + skip_white(&args->curptr, args->endptr); + if (args->curptr[0] == '@') { + ident = parse_opt_ident(&args->curptr, args->endptr); + xobj_id = findresource(sd, ident); + if (xobj_id >= 0) { + spc_warn(spe, "Object reference name for image \"%s\" already used.", ident); + RELEASE(ident); + return -1; + } + } + + transform_info_clear(&ti); + page_no = 1; + if (spc_util_read_dimtrns(spe, &ti, args, &page_no, 0) < 0) { + if (ident) + RELEASE(ident); + return -1; + } + + skip_white(&args->curptr, args->endptr); + fspec = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!fspec) { + spc_warn(spe, "Missing filename string for pdf:image."); + if (ident) + RELEASE(ident); + return -1; + } 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; + } + + skip_white(&args->curptr, args->endptr); + if (args->curptr < args->endptr) { + attr = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!attr || !PDF_OBJ_DICTTYPE(attr)) { + spc_warn(spe, "Ignore invalid attribute dictionary."); + if (attr) pdf_release_obj(attr); + } + } + + xobj_id = pdf_ximage_findresource(pdf_string_value(fspec), page_no, attr); + if (xobj_id < 0) { + spc_warn(spe, "Could not find image resource..."); + pdf_release_obj(fspec); + if (ident) + RELEASE(ident); + return -1; + } + + if (!(ti.flags & INFO_DO_HIDE)) + pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); + + if (ident) { + if (compat_mode && + pdf_ximage_get_subtype(xobj_id) == PDF_XOBJECT_TYPE_IMAGE) + pdf_ximage_set_attr(xobj_id, 1, 1, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0); + addresource(sd, ident, xobj_id); + RELEASE(ident); + } + + pdf_release_obj(fspec); + + return 0; +} + +/* Use do_names instead. */ +static int +spc_handler_pdfm_dest (struct spc_env *spe, struct spc_arg *args) +{ + pdf_obj *name, *array; + + skip_white(&args->curptr, args->endptr); + + name = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!name) { + spc_warn(spe, "PDF string expected for destination name but not found."); + return -1; + } else if (!PDF_OBJ_STRINGTYPE(name)) { + spc_warn(spe, "PDF string expected for destination name but invalid type."); + pdf_release_obj(name); + return -1; + } + +#ifdef XETEX +#ifdef ENABLE_TOUNICODE + if (maybe_reencode_utf8(name) < 0) + WARN("Failed to convert input string to UTF16..."); +#endif +#endif + + array = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!array) { + spc_warn(spe, "No destination specified for pdf:dest."); + pdf_release_obj(name); + return -1; + } else if (!PDF_OBJ_ARRAYTYPE(array)) { + spc_warn(spe, "Destination not specified as an array object!"); + pdf_release_obj(name); + pdf_release_obj(array); + return -1; + } + + pdf_doc_add_names("Dests", + pdf_string_value (name), + pdf_string_length(name), + array); + pdf_release_obj(name); + + return 0; +} + +static int +spc_handler_pdfm_names (struct spc_env *spe, struct spc_arg *args) +{ + pdf_obj *category, *key, *value, *tmp; + int i, size; + + category = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!category) { + spc_warn(spe, "PDF name expected but not found."); + return -1; + } else if (!PDF_OBJ_NAMETYPE(category)) { + spc_warn(spe, "PDF name expected but not found."); + pdf_release_obj(category); + return -1; + } + + tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!tmp) { + spc_warn(spe, "PDF object expected but not found."); + pdf_release_obj(category); + return -1; + } else if (PDF_OBJ_ARRAYTYPE(tmp)) { + size = pdf_array_length(tmp); + if (size % 2 != 0) { + spc_warn(spe, "Array size not multiple of 2 for pdf:names."); + pdf_release_obj(category); + pdf_release_obj(tmp); + return -1; + } + + for (i = 0; i < size / 2; i++) { + key = pdf_get_array(tmp, 2 * i); + value = pdf_get_array(tmp, 2 * i + 1); + if (!PDF_OBJ_STRINGTYPE(key)) { + spc_warn(spe, "Name tree key must be string."); + pdf_release_obj(category); + pdf_release_obj(tmp); + return -1; + } else if (pdf_doc_add_names(pdf_name_value(category), + pdf_string_value (key), + pdf_string_length(key), + pdf_link_obj(value)) < 0) { + spc_warn(spe, "Failed to add Name tree entry..."); + pdf_release_obj(category); + pdf_release_obj(tmp); + return -1; + } + } + pdf_release_obj(tmp); + } else if (PDF_OBJ_STRINGTYPE(tmp)) { + key = tmp; + value = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!value) { + pdf_release_obj(category); + pdf_release_obj(key); + spc_warn(spe, "PDF object expected but not found."); + return -1; + } + if (pdf_doc_add_names(pdf_name_value(category), + pdf_string_value (key), + pdf_string_length(key), + value) < 0) { + spc_warn(spe, "Failed to add Name tree entry..."); + pdf_release_obj(category); + pdf_release_obj(key); + return -1; + } + pdf_release_obj(key); + } else { + pdf_release_obj(tmp); + pdf_release_obj(category); + spc_warn(spe, "Invalid object type for pdf:names."); + return -1; + } + pdf_release_obj(category); + + return 0; +} + +static int +spc_handler_pdfm_docinfo (struct spc_env *spe, struct spc_arg *args) +{ +#ifdef ENABLE_TOUNICODE + struct spc_pdf_ *sd = &_pdf_stat; +#endif /* ENABLE_TOUNICODE */ + pdf_obj *docinfo, *dict; + +#ifdef ENABLE_TOUNICODE + dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!dict) { + spc_warn(spe, "Dictionary object expected but not found."); + return -1; + } + + docinfo = pdf_doc_docinfo(); + pdf_merge_dict(docinfo, dict); + pdf_release_obj(dict); + + return 0; +} + +static int +spc_handler_pdfm_docview (struct spc_env *spe, struct spc_arg *args) +{ +#ifdef ENABLE_TOUNICODE + struct spc_pdf_ *sd = &_pdf_stat; +#endif /* ENABLE_TOUNICODE */ + pdf_obj *catalog, *dict; + pdf_obj *pref_old, *pref_add; + +#ifdef ENABLE_TOUNICODE + dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); +#else + dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); +#endif /* ENABLE_TOUNICODE */ + if (!dict) { + spc_warn(spe, "Dictionary object expected but not found."); + return -1; + } + + catalog = pdf_doc_catalog(); + /* Avoid overriding whole ViewerPreferences */ + pref_old = pdf_lookup_dict(catalog, "ViewerPreferences"); + pref_add = pdf_lookup_dict(dict, "ViewerPreferences"); + if (pref_old && pref_add) { + pdf_merge_dict (pref_old, pref_add); + pdf_remove_dict(dict, "ViewerPreferences"); + } + pdf_merge_dict (catalog, dict); + pdf_release_obj(dict); + + return 0; +} + +static int +spc_handler_pdfm_close (struct spc_env *spe, struct spc_arg *args) +{ + char *ident; + + skip_white(&args->curptr, args->endptr); + ident = parse_opt_ident(&args->curptr, args->endptr); + if (ident) { + spc_flush_object(ident); + RELEASE(ident); + } else { /* Close all? */ + spc_clear_objects(); + } + + return 0; +} + +static int +spc_handler_pdfm_object (struct spc_env *spe, struct spc_arg *args) +{ + char *ident; + pdf_obj *object; + + skip_white(&args->curptr, args->endptr); + ident = parse_opt_ident(&args->curptr, args->endptr); + if (!ident) { + spc_warn(spe, "Could not find a object identifier."); + return -1; + } + + object = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!object) { + spc_warn(spe, "Could not find an object definition for \"%s\".", ident); + RELEASE(ident); + return -1; + } else { + spc_push_object(ident, object); + } + RELEASE(ident); + + return 0; +} + +static int +spc_handler_pdfm_content (struct spc_env *spe, struct spc_arg *args) +{ + long len = 0; + + skip_white(&args->curptr, args->endptr); + if (args->curptr < args->endptr) { + pdf_tmatrix M; + + pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user, spe->y_user); + work_buffer[len++] = ' '; + work_buffer[len++] = 'q'; + work_buffer[len++] = ' '; + len += pdf_sprint_matrix(work_buffer + len, &M); + work_buffer[len++] = ' '; + work_buffer[len++] = 'c'; + work_buffer[len++] = 'm'; + work_buffer[len++] = ' '; + + pdf_doc_add_page_content(work_buffer, len); /* op: q cm */ + len = (long) (args->endptr - args->curptr); + pdf_doc_add_page_content(args->curptr, len); /* op: ANY */ + pdf_doc_add_page_content(" Q", 2); /* op: Q */ + } + args->curptr = args->endptr; + + return 0; +} + +static int +spc_handler_pdfm_literal (struct spc_env *spe, struct spc_arg *args) +{ + int direct = 0; + + skip_white(&args->curptr, args->endptr); + while (args->curptr < args->endptr) { + if (args->curptr + 7 <= args->endptr && + !strncmp(args->curptr, "reverse", 7)) { + args->curptr += 7; + WARN("The special \"pdf:literal reverse ...\" is no longer supported.\nIgnore the \"reverse\" option."); + } else if (args->curptr + 6 <= args->endptr && + !strncmp(args->curptr, "direct", 6)) { + direct = 1; + args->curptr += 6; + } else { + break; + } + skip_white(&args->curptr, args->endptr); + } + + if (args->curptr < args->endptr) { + pdf_tmatrix M; + if (!direct) { + M.a = M.d = 1.0; M.b = M.c = 0.0; + M.e = spe->x_user; M.f = spe->y_user; + pdf_dev_concat(&M); + } + pdf_doc_add_page_content(" ", 1); /* op: */ + pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ + if (!direct) { + M.e = -spe->x_user; M.f = -spe->y_user; + pdf_dev_concat(&M); + } + } + + args->curptr = args->endptr; + + return 0; +} + +static int +spc_handler_pdfm_bcontent (struct spc_env *spe, struct spc_arg *args) +{ + pdf_tmatrix M; + double xpos, ypos; + + pdf_dev_gsave(); + pdf_dev_get_coord(&xpos, &ypos); + pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user - xpos, spe->y_user - ypos); + pdf_dev_concat(&M); + pdf_dev_push_coord(spe->x_user, spe->y_user); + return 0; +} + +static int +spc_handler_pdfm_econtent (struct spc_env *spe, struct spc_arg *args) +{ + pdf_dev_pop_coord(); + pdf_dev_grestore(); + pdf_dev_reset_color(0); + + return 0; +} + +static int +spc_handler_pdfm_code (struct spc_env *spe, struct spc_arg *args) +{ + skip_white(&args->curptr, args->endptr); + + if (args->curptr < args->endptr) { + pdf_doc_add_page_content(" ", 1); /* op: */ + pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ + args->curptr = args->endptr; + } + + return 0; +} + +static int +spc_handler_pdfm_do_nothing (struct spc_env *spe, struct spc_arg *args) +{ + args->curptr = args->endptr; + return 0; +} + +#define STRING_STREAM 0 +#define FILE_STREAM 1 + +static int +spc_handler_pdfm_stream_with_type (struct spc_env *spe, struct spc_arg *args, int type) +{ + pdf_obj *fstream; + long nb_read; + char *ident, *instring, *fullname; + pdf_obj *tmp; + FILE *fp; + + skip_white(&args->curptr, args->endptr); + + ident = parse_opt_ident(&args->curptr, args->endptr); + if (!ident) { + spc_warn(spe, "Missing objname for pdf:(f)stream."); + return -1; + } + + skip_white(&args->curptr, args->endptr); + + tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); + if (!tmp) { + spc_warn(spe, "Missing input string for pdf:(f)stream."); + RELEASE(ident); + return -1; + } else if (!PDF_OBJ_STRINGTYPE(tmp)) { + spc_warn(spe, "Invalid type of input string for pdf:(f)stream."); + pdf_release_obj(tmp); + RELEASE(ident); + return -1; + } + + instring = pdf_string_value(tmp); + + switch (type) { + case FILE_STREAM: + if (!instring) { + spc_warn(spe, "Missing filename for pdf:fstream."); + pdf_release_obj(tmp); + RELEASE(ident); + return -1; + } + fullname = kpse_find_pict(instring); + if (!fullname) { + spc_warn(spe, "File \"%s\" not found.", instring); + pdf_release_obj(tmp); + RELEASE(ident); + return -1; + } + fp = DPXFOPEN(fullname, DPX_RES_TYPE_BINARY); + if (!fp) { + spc_warn(spe, "Could not open file: %s", instring); + pdf_release_obj(tmp); + RELEASE(ident); + RELEASE(fullname); + return -1; + } + fstream = pdf_new_stream(STREAM_COMPRESS); + while ((nb_read = + fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) + pdf_add_stream(fstream, work_buffer, nb_read); + MFCLOSE(fp); + RELEASE(fullname); + break; + case STRING_STREAM: + fstream = pdf_new_stream(STREAM_COMPRESS); + if (instring) + pdf_add_stream(fstream, instring, strlen(instring)); + break; + default: + pdf_release_obj(tmp); + RELEASE(ident); + return -1; + } + pdf_release_obj(tmp); + + /* + * Optional dict. + * + * TODO: check Length, Filter... + */ + skip_white(&args->curptr, args->endptr); + + if (args->curptr[0] == '<') { + pdf_obj *stream_dict; + + stream_dict = pdf_stream_dict(fstream); + + tmp = parse_pdf_dict(&args->curptr, args->endptr, NULL); + if (!tmp) { + spc_warn(spe, "Parsing dictionary failed."); + pdf_release_obj(fstream); + RELEASE(ident); + return -1; + } + if (pdf_lookup_dict(tmp, "Length")) { + pdf_remove_dict(tmp, "Length"); + } else if (pdf_lookup_dict(tmp, "Filter")) { + pdf_remove_dict(tmp, "Filter"); + } + pdf_merge_dict(stream_dict, tmp); + pdf_release_obj(tmp); + } + + /* Users should explicitly close this. */ + spc_push_object(ident, fstream); + RELEASE(ident); + + return 0; +} + +/* + * STREAM: Create a PDF stream object from an input string. + * + * pdf: stream @objname (input_string) [PDF_DICT] + */ +static int +spc_handler_pdfm_stream (struct spc_env *spe, struct spc_arg *args) +{ + return spc_handler_pdfm_stream_with_type (spe, args, STRING_STREAM); +} + +/* + * FSTREAM: Create a PDF stream object from an existing file. + * + * pdf: fstream @objname (filename) [PDF_DICT] + */ +static int +spc_handler_pdfm_fstream (struct spc_env *spe, struct spc_arg *args) +{ + return spc_handler_pdfm_stream_with_type (spe, args, FILE_STREAM); +} + +/* Grab page content as follows: + * + * Reference point = (x_user, y_user) + * + * Case 1. \special{pdf:bxobj @obj width WD height HT depth DP} + * + * Grab the box with the lower-left corner (x_user, y_user-DP) + * and the upper right corner (x_user+WD, y_user+HT). + * + * Case 2. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} + * + * Grab the box with the lower-left corner (x_user+LLX, y_user+LLY) + * and the upper right corner (x_user+URX, y_user+URY). + * + * Note that scale, xscale, yscale, xoffset, yoffset options are ignored. + */ +static int +spc_handler_pdfm_bform (struct spc_env *spe, struct spc_arg *args) +{ + int xobj_id; + char *ident; + pdf_rect cropbox; + transform_info ti; + + skip_white(&args->curptr, args->endptr); + + ident = parse_opt_ident(&args->curptr, args->endptr); + if (!ident) { + spc_warn(spe, "A form XObject must have name."); + return -1; + } + + transform_info_clear(&ti); + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { + RELEASE(ident); + return -1; + } + + /* A XForm with zero dimension results in a non-invertible transformation + * matrix. And it may result in unpredictable behaviour. It might be an + * error in Acrobat. Bounding box with zero dimension may cause division + * by zero. + */ + if (ti.flags & INFO_HAS_USER_BBOX) { + if (ti.bbox.urx - ti.bbox.llx == 0.0 || + ti.bbox.ury - ti.bbox.lly == 0.0) { + spc_warn(spe, "Bounding box has a zero dimension."); + RELEASE(ident); + return -1; + } + cropbox.llx = ti.bbox.llx; + cropbox.lly = ti.bbox.lly; + cropbox.urx = ti.bbox.urx; + cropbox.ury = ti.bbox.ury; + } else { + if (ti.width == 0.0 || + ti.depth + ti.height == 0.0) { + spc_warn(spe, "Bounding box has a zero dimension."); + RELEASE(ident); + return -1; + } + cropbox.llx = 0.0; + cropbox.lly = -ti.depth; + cropbox.urx = ti.width; + cropbox.ury = ti.height; + } + + xobj_id = pdf_doc_begin_grabbing(ident, spe->x_user, spe->y_user, &cropbox); + + if (xobj_id < 0) { + RELEASE(ident); + spc_warn(spe, "Couldn't start form object."); + return -1; + } + + spc_push_object(ident, pdf_ximage_get_reference(xobj_id)); + RELEASE(ident); + + return 0; +} + +/* An extra dictionary after exobj must be merged to the form dictionary, + * not resource dictionary. + * Please use pdf:put @resources (before pdf:exobj) instead. + */ +static int +spc_handler_pdfm_eform (struct spc_env *spe, struct spc_arg *args) +{ + pdf_obj *attrib = NULL; + + skip_white(&args->curptr, args->endptr); + + if (args->curptr < args->endptr) { + attrib = parse_pdf_dict(&args->curptr, args->endptr, NULL); + if (attrib && !PDF_OBJ_DICTTYPE(attrib)) { + pdf_release_obj(attrib); + attrib = NULL; + } + } + pdf_doc_end_grabbing(attrib); + + return 0; +} + +/* Saved XObjects can be used as follows: + * + * Reference point = (x_user, y_user) + * + * Case 1. \special{pdf:uxobj @obj width WD height HT depth DP} + * + * Scale the XObject to fit in the box + * [x_user, y_user-DP, x_user+WD, y_user+HT]. + * + * Case 2. \special{pdf:uxobj @obj xscale XS yscale YS} + * + * Scale the XObject with XS and YS. Note that width and xscale + * or height and yscale cannot be used together. + * + * Case 3. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} + * + * Scale the XObject to fit in the box + * [x_user+LLX, y_user+LLY, x_user+URX, y_user+URY]. + * + * Note that xoffset and yoffset moves the reference point where the + * lower-left corner of the XObject will be put. + */ +static int +spc_handler_pdfm_uxobj (struct spc_env *spe, struct spc_arg *args) +{ + struct spc_pdf_ *sd = &_pdf_stat; + int xobj_id; + char *ident; + transform_info ti; + + skip_white(&args->curptr, args->endptr); + + ident = parse_opt_ident(&args->curptr, args->endptr); + if (!ident) { + spc_warn(spe, "No object identifier given."); + return -1; + } + + transform_info_clear(&ti); + if (args->curptr < args->endptr) { + if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { + RELEASE(ident); + return -1; + } + } + + /* Dvipdfmx was suddenly changed to use file name to identify + * external images. We can't use ident to find image resource + * here. + */ + xobj_id = findresource(sd, ident); + if (xobj_id < 0) { + xobj_id = pdf_ximage_findresource(ident, 0, NULL); + if (xobj_id < 0) { + spc_warn(spe, "Specified (image) object doesn't exist: %s", ident); + RELEASE(ident); + return -1; + } + } + + pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); + RELEASE(ident); + + return 0; +} + +static int +spc_handler_pdfm_link (struct spc_env *spe, struct spc_arg *args) +{ + return spc_resume_annot(spe); +} + +static int +spc_handler_pdfm_nolink (struct spc_env *spe, struct spc_arg *args) +{ + return spc_suspend_annot(spe); +} + + + +/* Handled at BOP */ +static int +spc_handler_pdfm_pagesize (struct spc_env *spe, struct spc_arg *args) +{ + args->curptr = args->endptr; + + return 0; +} + +/* Please remove this. + * This should be handled before processing pages! + */ +static int +spc_handler_pdfm_bgcolor (struct spc_env *spe, struct spc_arg *args) +{ + int error; + pdf_color colorspec; + + error = spc_util_read_pdfcolor(spe, &colorspec, args, NULL); + if (error) + spc_warn(spe, "No valid color specified?"); + else { + pdf_doc_set_bgcolor(&colorspec); + } + + return error; +} + +static int +spc_handler_pdfm_mapline (struct spc_env *spe, struct spc_arg *ap) +{ + fontmap_rec *mrec; + char *map_name, opchr; + int error = 0; + + skip_white(&ap->curptr, ap->endptr); + if (ap->curptr >= ap->endptr) { + spc_warn(spe, "Empty mapline special?"); + return -1; + } + + opchr = ap->curptr[0]; + if (opchr == '-' || opchr == '+') + ap->curptr++; + + skip_white(&ap->curptr, ap->endptr); + + switch (opchr) { + case '-': + map_name = parse_ident(&ap->curptr, ap->endptr); + if (map_name) { + pdf_remove_fontmap_record(map_name); + RELEASE(map_name); + } else { + spc_warn(spe, "Invalid fontmap line: Missing TFM name."); + error = -1; + } + break; + case '+': + mrec = NEW(1, fontmap_rec); + pdf_init_fontmap_record(mrec); + error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); + if (error) + spc_warn(spe, "Invalid fontmap line."); + else { + pdf_append_fontmap_record(mrec->map_name, mrec); + } + pdf_clear_fontmap_record(mrec); + RELEASE(mrec); + break; + default: + mrec = NEW(1, fontmap_rec); + pdf_init_fontmap_record(mrec); + error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); + if (error) + spc_warn(spe, "Invalid fontmap line."); + else { + pdf_insert_fontmap_record(mrec->map_name, mrec); + } + pdf_clear_fontmap_record(mrec); + RELEASE(mrec); + break; + } + if (!error) + ap->curptr = ap->endptr; + + return 0; +} + +static int +spc_handler_pdfm_mapfile (struct spc_env *spe, struct spc_arg *args) +{ + char *mapfile; + int mode, error = 0; + + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) + return 0; + + switch (args->curptr[0]) { + case '-': + mode = FONTMAP_RMODE_REMOVE; + args->curptr++; + break; + case '+': + mode = FONTMAP_RMODE_APPEND; + args->curptr++; + break; + default: + mode = FONTMAP_RMODE_REPLACE; + break; + } + + mapfile = parse_val_ident(&args->curptr, args->endptr); + if (!mapfile) { + spc_warn(spe, "No fontmap file specified."); + return -1; + } else { + error = pdf_load_fontmap_file(mapfile, mode); + } + RELEASE(mapfile); + + return error; +} + + +#ifdef ENABLE_TOUNICODE +static int +spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) +{ + struct spc_pdf_ *sd = &_pdf_stat; + char *cmap_name; + + /* First clear */ + sd->cd.cmap_id = -1; + sd->cd.unescape_backslash = 0; + + skip_white(&args->curptr, args->endptr); + if (args->curptr >= args->endptr) { + spc_warn(spe, "Missing CMap name for pdf:tounicode."); + return -1; + } + + /* _FIXME_ + * Any valid char allowed for PDF name object should be allowed here. + * The argument to this special should be a PDF name obejct. + * But it's too late to change this special. + */ + cmap_name = parse_ident(&args->curptr, args->endptr); + if (!cmap_name) { + spc_warn(spe, "Missing ToUnicode mapping name..."); + 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); + 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 (sd->cd.cmap_id >= 0) { + if (strstr(cmap_name, "RKSJ") || + strstr(cmap_name, "B5") || + strstr(cmap_name, "GBK") || + strstr(cmap_name, "KSC")) + sd->cd.unescape_backslash = 1; + } + RELEASE(cmap_name); + return 0; +} +#endif /* ENABLE_TOUNICODE */ + + +static struct spc_handler pdfm_handlers[] = { + {"annotation", spc_handler_pdfm_annot}, + {"annotate", spc_handler_pdfm_annot}, + {"annot", spc_handler_pdfm_annot}, + {"ann", spc_handler_pdfm_annot}, + + {"outline", spc_handler_pdfm_outline}, + {"out", spc_handler_pdfm_outline}, + + {"article", spc_handler_pdfm_article}, + {"art", spc_handler_pdfm_article}, + + {"bead", spc_handler_pdfm_bead}, + {"thread", spc_handler_pdfm_bead}, + + {"destination", spc_handler_pdfm_dest}, + {"dest", spc_handler_pdfm_dest}, + + + {"object", spc_handler_pdfm_object}, + {"obj", spc_handler_pdfm_object}, + + + {"docinfo", spc_handler_pdfm_docinfo}, + {"docview", spc_handler_pdfm_docview}, + + {"content", spc_handler_pdfm_content}, + {"put", spc_handler_pdfm_put}, + {"close", spc_handler_pdfm_close}, + {"bop", spc_handler_pdfm_bop}, + {"eop", spc_handler_pdfm_eop}, + + {"image", spc_handler_pdfm_image}, + {"img", spc_handler_pdfm_image}, + {"epdf", spc_handler_pdfm_image}, + + {"link", spc_handler_pdfm_link}, + {"nolink", spc_handler_pdfm_nolink}, + + {"begincolor", spc_handler_pdfm_bcolor}, + {"bcolor", spc_handler_pdfm_bcolor}, + {"bc", spc_handler_pdfm_bcolor}, + + {"setcolor", spc_handler_pdfm_scolor}, + {"scolor", spc_handler_pdfm_scolor}, + {"sc", spc_handler_pdfm_scolor}, + + {"endcolor", spc_handler_pdfm_ecolor}, + {"ecolor", spc_handler_pdfm_ecolor}, + {"ec", spc_handler_pdfm_ecolor}, + + {"begingray", spc_handler_pdfm_bcolor}, + {"bgray", spc_handler_pdfm_bcolor}, + {"bg", spc_handler_pdfm_bcolor}, + + {"endgray", spc_handler_pdfm_ecolor}, + {"egray", spc_handler_pdfm_ecolor}, + {"eg", spc_handler_pdfm_ecolor}, + + {"bgcolor", spc_handler_pdfm_bgcolor}, + {"bgc", spc_handler_pdfm_bgcolor}, + {"bbc", spc_handler_pdfm_bgcolor}, + {"bbg", spc_handler_pdfm_bgcolor}, + + {"pagesize", spc_handler_pdfm_pagesize}, + + {"bannot", spc_handler_pdfm_bann}, + {"beginann", spc_handler_pdfm_bann}, + {"bann", spc_handler_pdfm_bann}, + + {"eannot", spc_handler_pdfm_eann}, + {"endann", spc_handler_pdfm_eann}, + {"eann", spc_handler_pdfm_eann}, + + {"btrans", spc_handler_pdfm_btrans}, + {"begintransform", spc_handler_pdfm_btrans}, + {"begintrans", spc_handler_pdfm_btrans}, + {"bt", spc_handler_pdfm_btrans}, + + {"etrans", spc_handler_pdfm_etrans}, + {"endtransform", spc_handler_pdfm_etrans}, + {"endtrans", spc_handler_pdfm_etrans}, + {"et", spc_handler_pdfm_etrans}, + + {"bform", spc_handler_pdfm_bform}, + {"beginxobj", spc_handler_pdfm_bform}, + {"bxobj", spc_handler_pdfm_bform}, + + {"eform", spc_handler_pdfm_eform}, + {"endxobj", spc_handler_pdfm_eform}, + {"exobj", spc_handler_pdfm_eform}, + + {"usexobj", spc_handler_pdfm_uxobj}, + {"uxobj", spc_handler_pdfm_uxobj}, + +#ifdef ENABLE_TOUNICODE + {"tounicode", spc_handler_pdfm_tounicode}, +#endif /* ENABLE_TOUNICODE */ + {"literal", spc_handler_pdfm_literal}, + {"stream", spc_handler_pdfm_stream}, + {"fstream", spc_handler_pdfm_fstream}, + {"names", spc_handler_pdfm_names}, + {"mapline", spc_handler_pdfm_mapline}, + {"mapfile", spc_handler_pdfm_mapfile}, + + {"bcontent", spc_handler_pdfm_bcontent}, + {"econtent", spc_handler_pdfm_econtent}, + {"code", spc_handler_pdfm_code}, + + {"minorversion", spc_handler_pdfm_do_nothing}, + {"encrypt", spc_handler_pdfm_do_nothing}, +}; + +int +spc_pdfm_check_special (const char *buf, long len) +{ + int r = 0; + const char *p, *endptr; + + p = buf; + endptr = p + len; + + skip_white(&p, endptr); + if (p + strlen("pdf:") <= endptr && + !memcmp(p, "pdf:", strlen("pdf:"))) { + r = 1; + } + + return r; +} + +int +spc_pdfm_setup_handler (struct spc_handler *sph, + struct spc_env *spe, struct spc_arg *ap) +{ + int error = -1, i; + char *q; + + ASSERT(sph && spe && ap); + + skip_white(&ap->curptr, ap->endptr); + if (ap->curptr + strlen("pdf:") >= ap->endptr || + memcmp(ap->curptr, "pdf:", strlen("pdf:"))) { + spc_warn(spe, "Not pdf: special???"); + return -1; + } + ap->curptr += strlen("pdf:"); + + skip_white(&ap->curptr, ap->endptr); + q = parse_c_ident(&ap->curptr, ap->endptr); + if (q) { + for (i = 0; + i < sizeof(pdfm_handlers) / sizeof(struct spc_handler); i++) { + if (!strcmp(q, pdfm_handlers[i].key)) { + ap->command = pdfm_handlers[i].key; + sph->key = "pdf:"; + sph->exec = pdfm_handlers[i].exec; + skip_white(&ap->curptr, ap->endptr); + error = 0; + break; + } + } + RELEASE(q); + } + + return error; +} + diff --git a/Build/source/texk/dvipdfm-x/spc_tpic.c b/Build/source/texk/dvipdfm-x/spc_tpic.c new file mode 100644 index 00000000000..6fdf50eb0ed --- /dev/null +++ b/Build/source/texk/dvipdfm-x/spc_tpic.c @@ -0,0 +1,1136 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2002-2012 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. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "mem.h" +#include "error.h" + +#include "numbers.h" +#include "dpxutil.h" + +#include "pdfdoc.h" + +#include "pdfdraw.h" +#include "pdfdev.h" + +#include "specials.h" +#include "spc_tpic.h" + +#define DEBUG 1 +#define ENABLE_SPC_NAMESPACE 1 + +/* + * Following "constant" converts milli-inches to + * device (in this case PDF stream) coordinates. + */ + +#define MI2DEV (0.072/pdf_dev_scale()) + +/* + * Value for 'sh' command 'g' is interpreted as + * + * gray color value 1-g for "solid" + * opacity value g for "opacity" + * shape value g for "shape" + */ +#define TPIC_MODE__FILL_SOLID 0 +#define TPIC_MODE__FILL_OPACITY 1 +#define TPIC_MODE__FILL_SHAPE 2 + +#ifndef ISBLANK +# define ISBLANK(c) ( (c) == ' ' || (c) == '\t' ) +#endif + +static void +skip_blank (const char **pp, const char *endptr) +{ + const char *p = *pp; + for ( ; p < endptr && ISBLANK(*p); p++); + *pp = p; +} + +struct spc_tpic_ +{ + struct { + int fill; + } mode; + + /* state */ + double pen_size; + int fill_shape; /* boolean */ + double fill_color; + + pdf_coord *points; + int num_points; + int max_points; +}; + +#if 1 +static struct spc_tpic_ _tpic_state; +#endif + +/* We use pdf_doc_add_page_content() here + * since we always draw isolated graphics. + */ +static void +tpic__clear (struct spc_tpic_ *tp) +{ + if (tp->points) { + RELEASE(tp->points); + tp->points = NULL; + } + tp->num_points = 0; + tp->max_points = 0; + tp->fill_shape = 0; + tp->fill_color = 0.0; +} + + +static pdf_obj * +create_xgstate (double a /* alpha */, int f_ais /* alpha is shape */) +{ + pdf_obj *dict; + + dict = pdf_new_dict(); + pdf_add_dict(dict, + pdf_new_name("Type"), + pdf_new_name("ExtGState")); + if (f_ais) { + pdf_add_dict(dict, + pdf_new_name("AIS"), + pdf_new_boolean(1)); + } + pdf_add_dict(dict, + pdf_new_name("ca"), + pdf_new_number(a)); + + return dict; +} + +static int +check_resourcestatus (const char *category, const char *resname) +{ + pdf_obj *dict1, *dict2; + + dict1 = pdf_doc_current_page_resources(); + if (!dict1) + return 0; + + dict2 = pdf_lookup_dict(dict1, category); + if (dict2 && + pdf_obj_typeof(dict2) == PDF_DICT) { + if (pdf_lookup_dict(dict2, resname)) + return 1; + } + return 0; +} + +static int +set_linestyle (double pn, double da) +{ + double dp[2]; /* dash pattern */ + + pdf_dev_setlinejoin(1); + pdf_dev_setmiterlimit(1.4); + pdf_dev_setlinewidth(pn); + if (da > 0.0) { + dp[0] = da * 72.0; + pdf_dev_setdash(1, dp, 0); + pdf_dev_setlinecap(0); + } else if (da < 0.0) { + dp[0] = pn; + dp[1] = -da * 72.0; + pdf_dev_setdash(2, dp, 0); + pdf_dev_setlinecap(1); + } else { + pdf_dev_setlinecap(0); + } + + return 0; +} + +static int +set_fillstyle (double g, double a, int f_ais) +{ + pdf_obj *dict; + char resname[32]; + char buf[32]; + int alp, len = 0; + + if (a > 0.0) { + alp = round(100.0 * a); + sprintf(resname, "_Tps_a%03d_", alp); + if (!check_resourcestatus("ExtGState", resname)) { + dict = create_xgstate(ROUND(0.01 * alp, 0.01), f_ais); + pdf_doc_add_page_resource("ExtGState", + resname, pdf_ref_obj(dict)); + pdf_release_obj(dict); + } + len += sprintf(buf + len, " /%s gs", resname); + + pdf_doc_add_page_content(buf, len); /* op: gs */ + } + + { + pdf_color *sc, *fc, new_fc; + + pdf_color_get_current (&sc, &fc); /* get stroking and fill colors */ + pdf_color_brighten_color(&new_fc, fc, g); + pdf_dev_set_nonstrokingcolor(&new_fc); + } + + return 0; +} + +static void +set_styles (struct spc_tpic_ *tp, + const pdf_coord *c, + int f_fs, + int f_vp, + double pn, + double da) { + pdf_tmatrix M; + + pdf_setmatrix (&M, 1.0, 0.0, 0.0, -1.0, c->x, c->y); + pdf_dev_concat(&M); + + if (f_vp) + set_linestyle(pn, da); + + if (f_fs) { + double g, a; + int f_ais; + +#ifdef XETEX + switch (tp->mode.fill) { + case TPIC_MODE__FILL_SOLID: + g = 1.0 - tp->fill_color; + a = 0.0; + break; + case TPIC_MODE__FILL_SHAPE: + case TPIC_MODE__FILL_OPACITY: + if (tp->fill_color > 0.0) { + a = tp->fill_color; + g = 0.0; + } else { + a = 0.0; + g = 1.0; + } + break; + default: + g = 0.5; + a = 0.0; + } +#else + if (tp->mode.fill == TPIC_MODE__FILL_SOLID || !tp->fill_color) { + g = 1.0 - tp->fill_color; + a = 0.0; + } else { + g = 0.0; + a = tp->fill_color; + } +#endif + + f_ais = (tp->mode.fill == TPIC_MODE__FILL_SHAPE) ? 1 : 0; + + set_fillstyle(g, a, f_ais); + } +} + +static void +showpath (int f_vp, int f_fs) /* visible_path, fill_shape */ +{ + if (f_vp) { + if (f_fs) + pdf_dev_flushpath('b', PDF_FILL_RULE_NONZERO); + else { + pdf_dev_flushpath('S', PDF_FILL_RULE_NONZERO); + } + } else { + /* + * Acrobat claims 'Q' as illegal operation when there are unfinished + * path (a path without path-painting operator applied)? + */ + if (f_fs) + pdf_dev_flushpath('f', PDF_FILL_RULE_NONZERO); + else { + pdf_dev_newpath(); + } + } +} + +#define CLOSED_PATH(s) (\ + (s)->points[0].x == (s)->points[(s)->num_points-1].x && \ + (s)->points[0].y == (s)->points[(s)->num_points-1].y \ +) + +static int +tpic__polyline (struct spc_tpic_ *tp, + const pdf_coord *c, + int f_vp, + double da) +{ + double pn = tp->pen_size; + int f_fs = tp->fill_shape; + int i, error = 0; + + /* Shading is applied only to closed path. */ + f_fs = CLOSED_PATH(tp) ? f_fs : 0; + f_vp = (pn > 0.0) ? f_vp : 0; + + if (f_vp || f_fs) { + pdf_dev_gsave(); + + set_styles(tp, c, f_fs, f_vp, pn, da); + + pdf_dev_moveto(tp->points[0].x, tp->points[0].y); + for (i = 0; i < tp->num_points; i++) + pdf_dev_lineto(tp->points[i].x, tp->points[i].y); + + showpath(f_vp, f_fs); + + pdf_dev_grestore(); + } + + tpic__clear(tp); + + return error; +} + +/* + * Accroding to + * "Tpic: Pic for TEX", Tim Morgan, Original by Brian Kernighan, p.20: + * + * A spline is a smooth curve guided by a set of straight lines just + * like the line above. It begins at the same place, ends at the same + * place, and in between is tangent to the mid-point of each guiding + * line. The syntax for a spline is identical to a (path) line except + * for using spline instead of line. + * + * Spline is not a curve drawn by spline-fitting points p0, p1, ..., pn, + * defined by tpic special "pa" command. Instead, a path defined by set + * of points p0, p1, ... is guiding line mentioned above. + * + * Dvipsk draws them as a straight line from p0 to q1 = (p0 + p1)/2, + * followed by a quadratic B-spline curve with starting point q1, (off- + * curve) control point p1, end point q2 = (p1 + p2)/2, ..., and a + * straight line from qn to pn. + */ + +static int +tpic__spline (struct spc_tpic_ *tp, + const pdf_coord *c, + int f_vp, + double da) +{ + double v[6]; + double pn = tp->pen_size; + int f_fs = tp->fill_shape; + int i, error = 0; + + f_fs = CLOSED_PATH(tp) ? f_fs : 0; + f_vp = (pn > 0.0) ? f_vp : 0; + + if (f_vp || f_fs) { + pdf_dev_gsave(); + + set_styles(tp, c, f_fs, f_vp, pn, da); + + pdf_dev_moveto(tp->points[0].x, tp->points[0].y); + + v[0] = 0.5 * (tp->points[0].x + tp->points[1].x); + v[1] = 0.5 * (tp->points[0].y + tp->points[1].y); + pdf_dev_lineto(v[0], v[1]); + for (i = 1; i < tp->num_points - 1; i++) { + /* B-spline control points */ + v[0] = 0.5 * (tp->points[i-1].x + tp->points[i].x); + v[1] = 0.5 * (tp->points[i-1].y + tp->points[i].y); + v[2] = tp->points[i].x; + v[3] = tp->points[i].y; + v[4] = 0.5 * (tp->points[i].x + tp->points[i+1].x); + v[5] = 0.5 * (tp->points[i].y + tp->points[i+1].y); + pdf_dev_bspline(v[0], v[1], v[2], v[3], v[4], v[5]); + } + pdf_dev_lineto(tp->points[i].x, tp->points[i].y); + + showpath(f_vp, f_fs); + + pdf_dev_grestore(); + } + tpic__clear(tp); + + return error; +} + +static int +tpic__arc (struct spc_tpic_ *tp, + const pdf_coord *c, + int f_vp, + double da, + double *v /* 6 numbers */ ) +{ + double pn = tp->pen_size; + int f_fs = tp->fill_shape; + + f_fs = (round(fabs(v[4] - v[5]) + 0.5) >= 360) ? f_fs : 0; + f_vp = (pn > 0.0) ? f_vp : 0; + + if (f_vp || f_fs) { + pdf_dev_gsave(); + + set_styles(tp, c, f_fs, f_vp, pn, da); + + pdf_dev_arcx(v[0], v[1], v[2], v[3], v[4], v[5], +1, 0.0); + + showpath(f_vp, f_fs); + + pdf_dev_grestore(); + } + tpic__clear(tp); + + return 0; +} + +#if 1 +static int +spc_currentpoint (struct spc_env *spe, long *pg, pdf_coord *cp) +{ + *pg = 0; + cp->x = spe->x_user; + cp->y = spe->y_user; + return 0; +} +#endif + +static int +spc_handler_tpic_pn (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (!q) { + spc_warn(spe, "Invalid pen size specified?"); + return -1; + } + tp->pen_size = atof(q) * MI2DEV; + RELEASE(q); + + return 0; +} + +static int +spc_handler_tpic_pa (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + int i; + double v[2]; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + for (i = 0; + i < 2 && ap->curptr < ap->endptr; i++) { + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (!q) { + spc_warn(spe, "Missing numbers for TPIC \"pa\" command."); + return -1; + } + v[i] = atof(q); + RELEASE(q); + skip_blank(&ap->curptr, ap->endptr); + } + if (i != 2) { + spc_warn(spe, "Invalid arg for TPIC \"pa\" command."); + return -1; + } + + if (tp->num_points >= tp->max_points) { + tp->max_points += 256; + tp->points = RENEW(tp->points, tp->max_points, pdf_coord); + } + tp->points[tp->num_points].x = v[0] * MI2DEV; + tp->points[tp->num_points].y = v[1] * MI2DEV; + tp->num_points += 1; + + return 0; +} + +static int +spc_handler_tpic_fp (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + pdf_coord cp; + long pg; + + ASSERT(spe && ap && tp); + + if (tp->num_points <= 1) { + spc_warn(spe, "Too few points (< 2) for polyline path."); + return -1; + } + + spc_currentpoint(spe, &pg, &cp); + + return tpic__polyline(tp, &cp, 1, 0.0); +} + +static int +spc_handler_tpic_ip (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + pdf_coord cp; + long pg; + + ASSERT(spe && ap && tp); + + if (tp->num_points <= 1) { + spc_warn(spe, "Too few points (< 2) for polyline path."); + return -1; + } + + spc_currentpoint(spe, &pg, &cp); + + return tpic__polyline(tp, &cp, 0, 0.0); +} + +static int +spc_handler_tpic_da (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + double da = 0.0; + pdf_coord cp; + long pg; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (q) { + da = atof(q); + RELEASE(q); + } + if (tp->num_points <= 1) { + spc_warn(spe, "Too few points (< 2) for polyline path."); + return -1; + } + + spc_currentpoint(spe, &pg, &cp); + + return tpic__polyline(tp, &cp, 1, da); +} + +static int +spc_handler_tpic_dt (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + double da = 0.0; + pdf_coord cp; + long pg; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (q) { + da = -atof(q); + RELEASE(q); + } + if (tp->num_points <= 1) { + spc_warn(spe, "Too few points (< 2) for polyline path."); + return -1; + } + + spc_currentpoint(spe, &pg, &cp); + + return tpic__polyline(tp, &cp, 1, da); +} + +static int +spc_handler_tpic_sp (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + double da = 0.0; + pdf_coord cp; + long pg; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (q) { + da = atof(q); + RELEASE(q); + } + if (tp->num_points <= 2) { + spc_warn(spe, "Too few points (< 3) for spline path."); + return -1; + } + + spc_currentpoint(spe, &pg, &cp); + + return tpic__spline(tp, &cp, 1, da); +} + +static int +spc_handler_tpic_ar (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + double v[6]; + pdf_coord cp; + long pg; + char *q; + int i; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + for (i = 0; + i < 6 && ap->curptr < ap->endptr; i++) { + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (!q) { + spc_warn(spe, "Invalid args. in TPIC \"ar\" command."); + return -1; + } + v[i] = atof(q); + RELEASE(q); + skip_blank(&ap->curptr, ap->endptr); + } + if (i != 6) { + spc_warn(spe, "Invalid arg for TPIC \"ar\" command."); + return -1; + } + + v[0] *= MI2DEV; v[1] *= MI2DEV; + v[2] *= MI2DEV; v[3] *= MI2DEV; + v[4] *= 180.0 / M_PI; + v[5] *= 180.0 / M_PI; + + spc_currentpoint(spe, &pg, &cp); + + return tpic__arc(tp, &cp, 1, 0.0, v); +} + +static int +spc_handler_tpic_ia (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + double v[6]; + pdf_coord cp; + long pg; + char *q; + int i; + + ASSERT(spe && ap && tp); + + skip_blank(&ap->curptr, ap->endptr); + for (i = 0; + i < 6 && ap->curptr < ap->endptr; i++) { + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (!q) { + spc_warn(spe, "Invalid args. in TPIC \"ia\" command."); + return -1; + } + v[i] = atof(q); + RELEASE(q); + skip_blank(&ap->curptr, ap->endptr); + } + if (i != 6) { + spc_warn(spe, "Invalid arg for TPIC \"ia\" command."); + return -1; + } + + v[0] *= MI2DEV; v[1] *= MI2DEV; + v[2] *= MI2DEV; v[3] *= MI2DEV; + v[4] *= 180.0 / M_PI; + v[5] *= 180.0 / M_PI; + + spc_currentpoint(spe, &pg, &cp); + + return tpic__arc(tp, &cp, 0, 0.0, v); +} + +static int +spc_handler_tpic_sh (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + char *q; + + ASSERT(spe && ap && tp); + + tp->fill_shape = 1; + tp->fill_color = 0.5; + + skip_blank(&ap->curptr, ap->endptr); + q = parse_float_decimal(&ap->curptr, ap->endptr); + if (q) { + double g = atof(q); + RELEASE(q); + if (g >= 0.0 && g <= 1.0) + tp->fill_color = g; + else { + WARN("Invalid fill color specified: %g\n", g); + return -1; + } + } + + return 0; +} + +static int +spc_handler_tpic_wh (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + + ASSERT(spe && ap && tp); + + tp->fill_shape = 1; + tp->fill_color = 0.0; + + return 0; +} + +static int +spc_handler_tpic_bk (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + + ASSERT(spe && ap && tp); + + tp->fill_shape = 1; + tp->fill_color = 1.0; + + return 0; +} + +static int +spc_handler_tpic_tx (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + + ASSERT(spe && ap && tp); + + spc_warn(spe, "TPIC command \"tx\" not supported."); + + return -1; +} + + +static int +spc_handler_tpic__init (struct spc_env *spe, + struct spc_arg *ap, void *dp) +{ + struct spc_tpic_ *tp = dp; + +#if 0 + tp->mode.fill = TPIC_MODE__FILL_SOLID; +#endif + tp->pen_size = 1.0; + tp->fill_shape = 0; + tp->fill_color = 0.0; + + tp->points = NULL; + tp->num_points = 0; + tp->max_points = 0; + + if (tp->mode.fill != TPIC_MODE__FILL_SOLID && pdf_get_version() < 4) { + spc_warn(spe, "Tpic shading support requires PDF version 1.4."); + tp->mode.fill = TPIC_MODE__FILL_SOLID; + } + + return 0; +} + +static int +spc_handler_tpic__bophook (struct spc_env *spe, + struct spc_arg *ap, void *dp) +{ + struct spc_tpic_ *tp = dp; + + ASSERT(tp); + + tpic__clear(tp); + + return 0; +} + +static int +spc_handler_tpic__eophook (struct spc_env *spe, + struct spc_arg *ap, void *dp) +{ + struct spc_tpic_ *tp = dp; + + ASSERT(tp); + + if (tp->num_points > 0) + spc_warn(spe, "Unflushed tpic path at end of the page."); + tpic__clear(tp); + + return 0; +} + +static int +spc_handler_tpic__clean (struct spc_env *spe, + struct spc_arg *ap, void *dp) +{ + struct spc_tpic_ *tp = dp; + + ASSERT(tp); + + if (tp->num_points > 0) + spc_warn(spe, "Unflushed tpic path at end of the document."); + + tpic__clear(tp); +#if 0 + RELEASE(tp); +#endif + + return 0; +} + +void +tpic_set_fill_mode (int mode) +{ + struct spc_tpic_ *tp = &_tpic_state; + tp->mode.fill = mode; +} + + +int +spc_tpic_at_begin_page (void) +{ + struct spc_tpic_ *tp = &_tpic_state; + return spc_handler_tpic__bophook(NULL, NULL, tp); +} + +int +spc_tpic_at_end_page (void) +{ + struct spc_tpic_ *tp = &_tpic_state; + return spc_handler_tpic__eophook(NULL, NULL, tp); +} + + +int +spc_tpic_at_begin_document (void) +{ + struct spc_tpic_ *tp = &_tpic_state; + return spc_handler_tpic__init(NULL, NULL, tp); +} + +int +spc_tpic_at_end_document (void) +{ + struct spc_tpic_ *tp = &_tpic_state; + return spc_handler_tpic__clean(NULL, NULL, tp); +} + + +#if DEBUG +#include "pdfparse.h" /* parse_val_ident :( */ + +static pdf_obj * +spc_parse_kvpairs (struct spc_env *spe, struct spc_arg *ap) +{ + pdf_obj *dict; + char *kp, *vp; + int error = 0; + + dict = pdf_new_dict(); + + skip_blank(&ap->curptr, ap->endptr); + while (!error && ap->curptr < ap->endptr) { + kp = parse_val_ident(&ap->curptr, ap->endptr); + if (!kp) + break; + skip_blank(&ap->curptr, ap->endptr); + if (ap->curptr < ap->endptr && + ap->curptr[0] == '=') { + ap->curptr++; + skip_blank(&ap->curptr, ap->endptr); + if (ap->curptr == ap->endptr) { + RELEASE(kp); + error = -1; + break; + } + vp = parse_c_string(&ap->curptr, ap->endptr); + if (!vp) + error = -1; + else { + pdf_add_dict(dict, + pdf_new_name(kp), + pdf_new_string(vp, strlen(vp) + 1)); /* NULL terminate */ + RELEASE(vp); + } + } else { + /* Treated as 'flag' */ + pdf_add_dict(dict, + pdf_new_name(kp), + pdf_new_boolean(1)); + } + RELEASE(kp); + if (!error) + skip_blank(&ap->curptr, ap->endptr); + } + + if (error) { + pdf_release_obj(dict); + dict = NULL; + } + + return dict; +} + +static int +tpic_filter_getopts (pdf_obj *kp, pdf_obj *vp, void *dp) +{ + struct spc_tpic_ *tp = dp; + char *k, *v; + int error = 0; + + ASSERT( kp && vp && tp ); + + k = pdf_name_value(kp); + if (!strcmp(k, "fill-mode")) { + if (pdf_obj_typeof(vp) != PDF_STRING) { + WARN("Invalid value for TPIC option fill-mode..."); + error = -1; + } else { + v = pdf_string_value(vp); + if (!strcmp(v, "shape")) + tp->mode.fill = TPIC_MODE__FILL_SHAPE; + else if (!strcmp(v, "opacity")) + tp->mode.fill = TPIC_MODE__FILL_OPACITY; + else if (!strcmp(v, "solid")) + tp->mode.fill = TPIC_MODE__FILL_SOLID; + else { + WARN("Invalid value for TPIC option fill-mode: %s", v); + error = -1; + } + } + } else { + WARN("Unrecognized option for TPIC special handler: %s", k); + error = -1; + } + + return error; +} + +static int +spc_handler_tpic__setopts (struct spc_env *spe, + struct spc_arg *ap ) /* , void *dp) */ +{ + struct spc_tpic_ *tp = &_tpic_state; + pdf_obj *dict; + int error = 0; + + dict = spc_parse_kvpairs(spe, ap); + if (!dict) + return -1; + error = pdf_foreach_dict(dict, tpic_filter_getopts, tp); + if (!error) { + if (tp->mode.fill != TPIC_MODE__FILL_SOLID && + pdf_get_version() < 4) { + spc_warn(spe, "Transparent fill mode requires PDF version 1.4."); + tp->mode.fill = TPIC_MODE__FILL_SOLID; + } + } + + return error; +} +#endif /* DEBUG */ + + +static struct spc_handler tpic_handlers[] = { + {"pn", spc_handler_tpic_pn}, + {"pa", spc_handler_tpic_pa}, + {"fp", spc_handler_tpic_fp}, + {"ip", spc_handler_tpic_ip}, + {"da", spc_handler_tpic_da}, + {"dt", spc_handler_tpic_dt}, + {"sp", spc_handler_tpic_sp}, + {"ar", spc_handler_tpic_ar}, + {"ia", spc_handler_tpic_ia}, + {"sh", spc_handler_tpic_sh}, + {"wh", spc_handler_tpic_wh}, + {"bk", spc_handler_tpic_bk}, + {"tx", spc_handler_tpic_tx} +}; + +int +spc_tpic_check_special (const char *buf, long len) +{ + int istpic = 0; + char *q; + const char *p, *endptr; + int i, hasnsp = 0; + + p = buf; + endptr = p + len; + + skip_blank(&p, endptr); +#if ENABLE_SPC_NAMESPACE + if (p + strlen("tpic:") < endptr && + !memcmp(p, "tpic:", strlen("tpic:"))) + { + p += strlen("tpic:"); + hasnsp = 1; + } +#endif + q = parse_c_ident(&p, endptr); + + if (!q) + istpic = 0; + else if (q && hasnsp && !strcmp(q, "__setopt__")) { +#if DEBUG + istpic = 1; +#endif + RELEASE(q); + } else { + for (i = 0; + i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { + if (!strcmp(q, tpic_handlers[i].key)) { + istpic = 1; + break; + } + } + RELEASE(q); + } + + return istpic; +} + + +int +spc_tpic_setup_handler (struct spc_handler *sph, + struct spc_env *spe, struct spc_arg *ap) +{ + char *q; + int i, hasnsp = 0, error = -1; + + ASSERT(sph && spe && ap); + + skip_blank(&ap->curptr, ap->endptr); +#if ENABLE_SPC_NAMESPACE + if (ap->curptr + strlen("tpic:") < ap->endptr && + !memcmp(ap->curptr, "tpic:", strlen("tpic:"))) + { + ap->curptr += strlen("tpic:"); + hasnsp = 1; + } +#endif + q = parse_c_ident(&ap->curptr, ap->endptr); + + if (!q) + error = -1; + else if (q && hasnsp && !strcmp(q, "__setopt__")) { +#if DEBUG + ap->command = "__setopt__"; + sph->key = "tpic:"; + sph->exec = spc_handler_tpic__setopts; + skip_blank(&ap->curptr, ap->endptr); + error = 0; +#endif + RELEASE(q); + } else { + for (i = 0; + i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { + if (!strcmp(q, tpic_handlers[i].key)) { + ap->command = tpic_handlers[i].key; + sph->key = "tpic:"; + sph->exec = tpic_handlers[i].exec; + skip_blank(&ap->curptr, ap->endptr); + error = 0; + break; + } + } + RELEASE(q); + } + + return error; +} + + +#if 0 +int +spc_load_tpic_special (struct spc_env *spe, pdf_obj *lopts) +{ + struct spc_def *spd; + struct spc_tpic_ *sd; + + sd = NEW(1, struct spc_tpic_); + + spd = NEW(1, struct spc_def); + spc_init_def(spd); + + spc_def_init (spd, &spc_handler_tpic__init); + spc_def_setopts(spd, &spc_handler_tpic__setopts); + spc_def_bophook(spd, &spc_handler_tpic__bophook); + spc_def_eophook(spd, &spc_handler_tpic__eophook); + spc_def_clean (spd, &spc_handler_tpic__clean); + + spc_def_func(spd, "pn", &spc_handler_tpic_pn); + spc_def_func(spd, "pa", &spc_handler_tpic_pa); + spc_def_func(spd, "fp", &spc_handler_tpic_fp); + spc_def_func(spd, "ip", &spc_handler_tpic_ip); + spc_def_func(spd, "da", &spc_handler_tpic_da); + spc_def_func(spd, "dt", &spc_handler_tpic_dt); + spc_def_func(spd, "sp", &spc_handler_tpic_sp); + spc_def_func(spd, "ar", &spc_handler_tpic_ar); + spc_def_func(spd, "ia", &spc_handler_tpic_ia); + spc_def_func(spd, "sh", &spc_handler_tpic_sh); + spc_def_func(spd, "wh", &spc_handler_tpic_wh); + spc_def_func(spd, "bk", &spc_handler_tpic_bk); + spc_def_func(spd, "tx", &spc_handler_tpic_tx); + + spc_add_special(spe, "tpic", spd, sd); + + return 0; +} +#endif /* 0 */ + diff --git a/Build/source/texk/dvipdfm-x/spc_util.c b/Build/source/texk/dvipdfm-x/spc_util.c index 29bdaeb769a..63fe0b70574 100644 --- a/Build/source/texk/dvipdfm-x/spc_util.c +++ b/Build/source/texk/dvipdfm-x/spc_util.c @@ -56,9 +56,6 @@ skip_blank (const char **pp, const char *endptr) /* From pdfcolor.c */ static int pdf_color_namedcolor (pdf_color *color, const char *colorname); -#ifndef XETEX -static -#endif int spc_util_read_numbers (double *values, int num_values, struct spc_env *spe, struct spc_arg *args) @@ -172,7 +169,6 @@ spc_read_color_color (struct spc_env *spe, pdf_color *colorspec, struct spc_arg return error; } -#ifndef XETEX /* Argument for this is PDF_Number or PDF_Array. * But we ignore that since we don't want to add * dependency to pdfxxx and @foo can not be @@ -231,7 +227,6 @@ spc_read_color_pdf (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *a return error; } -#endif /* This is for reading *single* color specification. */ int @@ -247,14 +242,9 @@ spc_util_read_colorspec (struct spc_env *spe, pdf_color *colorspec, struct spc_a if (syntax) return spc_read_color_color(spe, colorspec, ap); else -#ifdef XETEX - return -1; -#else return spc_read_color_pdf(spe, colorspec, ap); -#endif } -#ifndef XETEX int spc_util_read_pdfcolor (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *ap, pdf_color *defaultcolor) { @@ -273,7 +263,6 @@ spc_util_read_pdfcolor (struct spc_env *spe, pdf_color *colorspec, struct spc_ar } return error; } -#endif /* This need to allow 'true' prefix for unit and * length value must be divided by current magnification. diff --git a/Build/source/texk/dvipdfm-x/spc_util.h b/Build/source/texk/dvipdfm-x/spc_util.h index b15c486ce02..707fb7e038b 100644 --- a/Build/source/texk/dvipdfm-x/spc_util.h +++ b/Build/source/texk/dvipdfm-x/spc_util.h @@ -38,10 +38,7 @@ 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, long *page, int syntax); -#ifdef XETEX extern int spc_util_read_numbers (double *values, int num_values, struct spc_env *spe, struct spc_arg *args); -#else extern int spc_util_read_pdfcolor (struct spc_env *spe, pdf_color *colorspec, struct spc_arg *args, pdf_color *defaultcolor); -#endif #endif /* _SPC_UTIL_H_ */ diff --git a/Build/source/texk/dvipdfm-x/spc_xtx.c b/Build/source/texk/dvipdfm-x/spc_xtx.c index cf4f668bc5c..ed0b667f8c2 100644 --- a/Build/source/texk/dvipdfm-x/spc_xtx.c +++ b/Build/source/texk/dvipdfm-x/spc_xtx.c @@ -164,7 +164,7 @@ spc_handler_xtx_grestore (struct spc_env *spe, struct spc_arg *args) * starting a new page. */ pdf_dev_reset_fonts(); - pdf_dev_reset_color(); + pdf_dev_reset_color(0); return 0; } diff --git a/Build/source/texk/dvipdfm-x/src/cidtype0.c b/Build/source/texk/dvipdfm-x/src/cidtype0.c deleted file mode 100644 index 363c8088a9d..00000000000 --- a/Build/source/texk/dvipdfm-x/src/cidtype0.c +++ /dev/null @@ -1,2076 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - 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. -*/ - -/* - * CID-Keyed Font support: - * - * Only CFF/OpenType CID-Keyed Font with Type 2 charstrings is supported. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "numbers.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfobj.h" -/* pseudo unique tag */ -#include "pdffont.h" - -/* Font info. from OpenType tables */ -#include "sfnt.h" -#include "tt_aux.h" -/* Metrics */ -#include "tt_table.h" - -#include "cff_types.h" -#include "cff_limits.h" -#include "cff.h" -#include "cff_dict.h" -#include "cs_type2.h" - -/* typedef CID in cmap.h */ -#include "cmap.h" -#include "type0.h" -#include "cid.h" -#include "cid_p.h" -#include "cidtype0.h" - -static int verbose = 0; -static long opt_flags = 0; - -void -CIDFont_type0_set_verbose (void) -{ - verbose++; -} - -void -CIDFont_type0_set_flags (long flags) -{ - opt_flags = flags; -} - -/* - * PDF Reference 3rd. ed., p.340, "Glyph Metrics in CID Fonts". - */ -#ifndef PDFUNIT -#define PDFUNIT(v) (ROUND((1000.0*(v))/(head->unitsPerEm),1)) -#endif - -static void -add_CIDHMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, - struct tt_maxp_table *maxp, - struct tt_head_table *head, struct tt_longMetrics *hmtx) -{ - pdf_obj *w_array, *an_array = NULL; - long cid, start = 0, prev = 0; - double defaultAdvanceWidth; - int empty = 1; - - defaultAdvanceWidth = PDFUNIT(hmtx[0].advance); - /* - * We alway use format: - * c [w_1 w_2 ... w_n] - */ - w_array = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - USHORT gid; - double advanceWidth; - gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; - if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) - continue; - advanceWidth = PDFUNIT(hmtx[gid].advance); - if (advanceWidth == defaultAdvanceWidth) { - if (an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - an_array = NULL; - empty = 0; - } - } else { - if (cid != prev + 1 && an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - an_array = NULL; - empty = 0; - } - if (an_array == NULL) { - an_array = pdf_new_array(); - start = cid; - } - pdf_add_array(an_array, pdf_new_number(advanceWidth)); - prev = cid; - } - } - - if (an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - empty = 0; - } - - /* - * We always write DW for older MacOS X's preview app. - * PDF Reference 2nd. ed, wrongly described default value of DW as 0, and - * MacOS X's (up to 10.2.8) preview app. implements this wrong description. - */ - pdf_add_dict(fontdict, - pdf_new_name("DW"), - pdf_new_number(defaultAdvanceWidth)); - if (!empty) { - pdf_add_dict(fontdict, - pdf_new_name("W"), - pdf_ref_obj(w_array)); - } - pdf_release_obj(w_array); - - return; -} - -static void -add_CIDVMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, - struct tt_maxp_table *maxp, - struct tt_head_table *head, struct tt_longMetrics *hmtx) -{ - pdf_obj *w2_array, *an_array = NULL; - long cid; -#if 0 - long prev = 0, start = 0; -#endif - struct tt_VORG_table *vorg; - struct tt_vhea_table *vhea = NULL; - struct tt_longMetrics *vmtx = NULL; - double defaultAdvanceHeight, defaultVertOriginY; - int empty = 1; - - /* - * No accurate vertical metrics can be obtained by simple way if the - * font does not have VORG table. Only CJK fonts may have VORG. - */ - if (sfnt_find_table_pos(sfont, "VORG") <= 0) - return; - - vorg = tt_read_VORG_table(sfont); - defaultVertOriginY = PDFUNIT(vorg->defaultVertOriginY); - if (sfnt_find_table_pos(sfont, "vhea") > 0) - 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, vhea->numOfExSideBearings); - } - - if (sfnt_find_table_pos(sfont, "OS/2") <= 0) { - struct tt_os2__table *os2; - /* OpenType font must have OS/2 table. */ - os2 = tt_read_os2__table(sfont); - defaultVertOriginY = PDFUNIT(os2->sTypoAscender); - defaultAdvanceHeight = PDFUNIT(os2->sTypoAscender - os2->sTypoDescender); - RELEASE(os2); - } else { - /* Some TrueType fonts used in Macintosh does not have OS/2 table. */ - defaultAdvanceHeight = 1000; - } - - w2_array = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - USHORT i, gid; - double advanceHeight, vertOriginX, vertOriginY; - gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; - if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) - continue; - advanceHeight = vmtx ? PDFUNIT(vmtx[gid].advance) : defaultAdvanceHeight; - vertOriginX = PDFUNIT(hmtx[gid].advance*0.5); - vertOriginY = defaultVertOriginY; - for (i = 0; - i < vorg->numVertOriginYMetrics && gid > vorg->vertOriginYMetrics[i].glyphIndex; - i++) { - if (gid == vorg->vertOriginYMetrics[i].glyphIndex) - vertOriginY = PDFUNIT(vorg->vertOriginYMetrics[i].vertOriginY); - } -#if 0 - /* - * c [w1_1y v_1x v_1y w1_2y v_2x v_2y ...] - * Not working... Why? - * Acrobat Reader: - * Wrong rendering, interpretation of position vector is wrong. - * Xpdf and gs: ignores W2? - */ - if (vertOriginY == defaultVertOriginY && - advanceHeight == defaultAdvanceHeight) { - if (an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - an_array = NULL; - empty = 0; - } - } else { - if (cid != prev + 1 && an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - an_array = NULL; - empty = 0; - } - if (an_array == NULL) { - an_array = pdf_new_array(); - start = cid; - } - pdf_add_array(an_array, pdf_new_number(-advanceHeight)); - pdf_add_array(an_array, pdf_new_number(vertOriginX)); - pdf_add_array(an_array, pdf_new_number(vertOriginY)); - prev = cid; - } -#else - /* - * c_first c_last w1_y v_x v_y - * This form may hit Acrobat's implementation limit of array element size, 8192. - * AFPL GhostScript 8.11 stops with rangecheck error with this. Maybe GS's bug? - */ - if (vertOriginY != defaultVertOriginY || - advanceHeight != defaultAdvanceHeight) { - pdf_add_array(w2_array, pdf_new_number(cid)); - pdf_add_array(w2_array, pdf_new_number(cid)); - pdf_add_array(w2_array, pdf_new_number(-advanceHeight)); - pdf_add_array(w2_array, pdf_new_number(vertOriginX)); - pdf_add_array(w2_array, pdf_new_number(vertOriginY)); - empty = 0; - } -#endif - } - -#if 0 - if (an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - empty = 0; - } -#endif - - if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) { - an_array = pdf_new_array(); - pdf_add_array(an_array, pdf_new_number(defaultVertOriginY)); - pdf_add_array(an_array, pdf_new_number(-defaultAdvanceHeight)); - pdf_add_dict(fontdict, pdf_new_name ("DW2"), an_array); - } - if (!empty) { - pdf_add_dict(fontdict, - pdf_new_name("W2"), pdf_ref_obj(w2_array)); - } - pdf_release_obj(w2_array); - - if (vorg->vertOriginYMetrics) - RELEASE(vorg->vertOriginYMetrics); - RELEASE(vorg); - - if (vmtx) - RELEASE(vmtx); - if (vhea) - RELEASE(vhea); - - return; -} - -static void -add_CIDMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, int need_vmetrics) -{ - struct tt_longMetrics *hmtx; - struct tt_head_table *head; - struct tt_hhea_table *hhea; - struct tt_maxp_table *maxp; - - /* - * Read head, hhea, maxp: - * - * unitsPerEm --> head - * numHMetrics --> hhea - * numGlyphs --> maxp - */ - head = tt_read_head_table(sfont); - maxp = tt_read_maxp_table(sfont); - hhea = tt_read_hhea_table(sfont); - - sfnt_locate_table(sfont, "hmtx"); - hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); - - add_CIDHMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); - if (need_vmetrics) - add_CIDVMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); - - RELEASE(hmtx); - RELEASE(hhea); - RELEASE(maxp); - RELEASE(head); - - return; -} - -/* - * Create an instance of embeddable font. - */ -static long -write_fontfile (CIDFont *font, cff_font *cffont) -{ - cff_index *topdict, *fdarray, *private; - unsigned char *dest; - long destlen = 0, i, size; - long offset, topdict_offset, fdarray_offset; - - /* DICT sizes (offset set to long int) */ - topdict = cff_new_index(1); - fdarray = cff_new_index(cffont->num_fds); - private = cff_new_index(cffont->num_fds); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */ - cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */ - - topdict->offset[1] = cff_dict_pack(cffont->topdict, - (card8 *) work_buffer, - WORK_BUFFER_SIZE) + 1; - for (i = 0;i < cffont->num_fds; i++) { - size = 0; - if (cffont->private && cffont->private[i]) { - size = cff_dict_pack(cffont->private[i], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - if (size < 1) { /* Private had contained only Subr */ - cff_dict_remove(cffont->fdarray[i], "Private"); - } - } - (private->offset)[i+1] = (private->offset)[i] + size; - (fdarray->offset)[i+1] = (fdarray->offset)[i] + - cff_dict_pack(cffont->fdarray[i], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - } - - destlen = 4; /* header size */ - destlen += cff_set_name(cffont, font->fontname); - destlen += cff_index_size(topdict); - destlen += cff_index_size(cffont->string); - destlen += cff_index_size(cffont->gsubr); - destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */ - destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */ - destlen += cff_index_size(cffont->cstrings); - destlen += cff_index_size(fdarray); - destlen += private->offset[private->count] - 1; /* Private is not INDEX */ - - dest = NEW(destlen, card8); - - offset = 0; - /* Header */ - offset += cff_put_header(cffont, dest + offset, destlen - offset); - /* Name */ - offset += cff_pack_index(cffont->name, dest + offset, destlen - offset); - /* Top DICT */ - topdict_offset = offset; - offset += cff_index_size(topdict); - /* Strings */ - offset += cff_pack_index(cffont->string, dest + offset, destlen - offset); - /* Global Subrs */ - offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset); - - /* charset */ - cff_dict_set(cffont->topdict, "charset", 0, offset); - offset += cff_pack_charsets(cffont, dest + offset, destlen - offset); - - /* FDSelect */ - cff_dict_set(cffont->topdict, "FDSelect", 0, offset); - offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset); - - /* CharStrings */ - cff_dict_set(cffont->topdict, "CharStrings", 0, offset); - offset += cff_pack_index(cffont->cstrings, - dest + offset, cff_index_size(cffont->cstrings)); - cff_release_index(cffont->cstrings); - cffont->cstrings = NULL; /* Charstrings cosumes huge memory */ - - /* FDArray and Private */ - cff_dict_set(cffont->topdict, "FDArray", 0, offset); - fdarray_offset = offset; - offset += cff_index_size(fdarray); - - fdarray->data = NEW(fdarray->offset[fdarray->count] - 1, card8); - for (i = 0; i < cffont->num_fds; i++) { - size = private->offset[i+1] - private->offset[i]; - if (cffont->private[i] && size > 0) { - cff_dict_pack(cffont->private[i], dest + offset, size); - cff_dict_set(cffont->fdarray[i], "Private", 0, size); - cff_dict_set(cffont->fdarray[i], "Private", 1, offset); - } - cff_dict_pack(cffont->fdarray[i], - fdarray->data + (fdarray->offset)[i] - 1, - fdarray->offset[fdarray->count] - 1); - offset += size; - } - - cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray)); - cff_release_index(fdarray); - cff_release_index(private); - - /* Finally Top DICT */ - topdict->data = NEW(topdict->offset[topdict->count] - 1, card8); - cff_dict_pack(cffont->topdict, - topdict->data, topdict->offset[topdict->count] - 1); - cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict)); - cff_release_index(topdict); - - /* - * FontFile - */ - { - pdf_obj *fontfile, *stream_dict; - - fontfile = pdf_new_stream(STREAM_COMPRESS); - stream_dict = pdf_stream_dict(fontfile); - pdf_add_dict(font->descriptor, - pdf_new_name("FontFile3"), - pdf_ref_obj (fontfile)); - pdf_add_dict(stream_dict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0C")); - pdf_add_stream(fontfile, (char *) dest, offset); - pdf_release_obj(fontfile); - RELEASE(dest); - } - - return destlen; -} - -void -CIDFont_type0_dofont (CIDFont *font) -{ - sfnt *sfont; - cff_font *cffont; - FILE *fp = NULL; - cff_index *charstrings, *idx; - cff_charsets *charset = NULL; - cff_fdselect *fdselect = NULL; - long charstring_len, max_len; - long destlen = 0; - long size, offset = 0; - card8 *data; - card16 num_glyphs, gid; - long cid, cid_count; - card16 cs_count, last_cid; - int fd, prev_fd, parent_id; - char *used_chars; - unsigned char *CIDToGIDMap = NULL; - - ASSERT(font); - - if (!font->indirect) - return; - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - if (CIDFont_is_BaseFont(font)) - return; - else if (!CIDFont_get_embedding(font) && - (opt_flags & CIDFONT_FORCE_FIXEDPITCH)) { - /* No metrics needed. */ - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(1000.0)); - return; - } - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); - if (!fp) - ERROR("Could not open OpenType font file: %s", font->ident); - sfont = sfnt_open(fp); -#endif - if (!sfont) - ERROR("Could not open OpenType font file: %s", font->ident); - - if (sfnt_read_table_directory(sfont, 0) < 0 || - sfont->type != SFNT_TYPE_POSTSCRIPT) - ERROR("Not a CFF/OpenType font ?"); - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) - ERROR("Not a CFF/OpenType font ?"); - - cffont = cff_open(fp, offset, font->options->index); - if (!cffont) - ERROR("Could not open CFF font."); - if (!(cffont->flag & FONTTYPE_CIDFONT)) - ERROR("Not a CIDFont."); - - if (cff_dict_known(cffont->topdict, "CIDCount")) { - cid_count = (long) cff_dict_get(cffont->topdict, "CIDCount", 0); - } else { - cid_count = CID_MAX + 1; - } - - cff_read_charsets(cffont); - CIDToGIDMap = NEW(2*cid_count, unsigned char); - memset(CIDToGIDMap, 0, 2*cid_count); - add_to_used_chars2(used_chars, 0); /* .notdef */ - cid = 0; last_cid = 0; num_glyphs = 0; - for (cid = 0; cid <= CID_MAX; cid++) { - if (is_used_char2(used_chars, cid)) { - gid = cff_charsets_lookup(cffont, (card16)cid); - if (cid != 0 && gid == 0) { - WARN("Glyph for CID %u missing in font \"%s\".", (CID) cid, font->ident); - used_chars[cid/8] &= ~(1 << (7 - (cid % 8))); - continue; - } - CIDToGIDMap[2*cid] = (gid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = gid & 0xff; - last_cid = cid; - num_glyphs++; - } - } - - /* - * DW, W, DW2 and W2: - * Those values are obtained from OpenType table (not TFM). - */ - if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) { - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(1000.0)); - } else { - add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, - ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); - } - - if (!CIDFont_get_embedding(font)) { - RELEASE(CIDToGIDMap); - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return; - } - - /* - * Embed font subset. - */ - cff_read_fdselect(cffont); - cff_read_fdarray(cffont); - cff_read_private(cffont); - - cff_read_subrs(cffont); - - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - idx = cff_get_index_header(cffont); - /* offset is now absolute offset ... bad */ - offset = ftell(cffont->stream); - - if ((cs_count = idx->count) < 2) { - ERROR("No valid charstring data found."); - } - - /* New Charsets data */ - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = 0; - charset->data.glyphs = NEW(num_glyphs, s_SID); - - /* New FDSelect data */ - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 0; - fdselect->data.ranges = NEW(num_glyphs, cff_range3); - - /* New CharStrings INDEX */ - charstrings = cff_new_index((card16)(num_glyphs+1)); - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - /* - * TODO: Re-assign FD number. - */ - prev_fd = -1; gid = 0; - data = NEW(CS_STR_LEN_MAX, card8); - for (cid = 0; cid <= last_cid; cid++) { - unsigned short gid_org; - - if (!is_used_char2(used_chars, cid)) - continue; - - gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]); - if ((size = (idx->offset)[gid_org+1] - (idx->offset)[gid_org]) - > CS_STR_LEN_MAX) - ERROR("Charstring too long: gid=%u", gid_org); - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - (charstrings->offset)[gid] = charstring_len + 1; - seek_absolute(cffont->stream, offset + (idx->offset)[gid_org] - 1); - fread(data, 1, size, cffont->stream); - fd = cff_fdselect_lookup(cffont, gid_org); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, (cffont->subrs)[fd], 0, 0, NULL); - if (cid > 0 && gid_org > 0) { - charset->data.glyphs[charset->num_entries] = cid; - charset->num_entries += 1; - } - if (fd != prev_fd) { - fdselect->data.ranges[fdselect->num_entries].first = gid; - fdselect->data.ranges[fdselect->num_entries].fd = fd; - fdselect->num_entries += 1; - prev_fd = fd; - } - gid++; - } - if (gid != num_glyphs) - ERROR("Unexpeced error: ?????"); - RELEASE(data); - cff_release_index(idx); - - RELEASE(CIDToGIDMap); - - (charstrings->offset)[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - cffont->num_glyphs = num_glyphs; - cffont->cstrings = charstrings; - - /* discard old one, set new data */ - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - cff_release_fdselect(cffont->fdselect); - cffont->fdselect = fdselect; - - /* no Global subr */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - - for (fd = 0; fd < cffont->num_fds; fd++) { - if (cffont->subrs && cffont->subrs[fd]) { - cff_release_index(cffont->subrs[fd]); - cffont->subrs[fd] = NULL; - } - if (cffont->private && (cffont->private)[fd]) { - cff_dict_remove((cffont->private)[fd], "Subrs"); /* no Subrs */ - } - } - - destlen = write_fontfile(font, cffont); - - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) - MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, destlen); - - /* - * CIDSet: - * Length of CIDSet stream is not clear. Must be 8192 bytes long? - */ - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - return; -} - -int -CIDFont_type0_open (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - CIDSysInfo *csi; - char *fontname; - sfnt *sfont; - cff_font *cffont; - FILE *fp = NULL; - unsigned long offset = 0; - - ASSERT(font); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); - if (!sfont) { - ERROR("Not a CFF/OpenType font?"); - } -#endif - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0 || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font?"); - } - - cffont = cff_open(sfont->stream, offset, opt->index); - if (!cffont) { - ERROR("Cannot read CFF font data"); - } - - if (!(cffont->flag & FONTTYPE_CIDFONT)) { - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - return -1; - } - - csi = NEW(1, CIDSysInfo); - csi->registry = - cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 0)); - csi->ordering = - cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 1)); - csi->supplement = (int)cff_dict_get(cffont->topdict, "ROS", 2); - - if (cmap_csi) { - if (strcmp(csi->registry, cmap_csi->registry) != 0 || - strcmp(csi->ordering, cmap_csi->ordering) != 0) { - MESG("\nCharacter collection mismatched:\n"); - MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); - MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); - ERROR("Inconsistent CMap specified for this font."); - } - if (csi->supplement < cmap_csi->supplement) { - WARN("CMap have higher supplmement number."); - WARN("Some characters may not be displayed or printed."); - } - } - - { - char *shortname; - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - /* - * Mangled name requires more 7 bytes. - * Style requires more 11 bytes. - */ - fontname = NEW(strlen(shortname)+19, char); - memset(fontname, 0, strlen(shortname)+19); - strcpy(fontname, shortname); - RELEASE(shortname); - } - cff_close(cffont); - - if (opt->embed && opt->style != FONT_STYLE_NONE) { - WARN("Embedding disabled due to style option for %s.", name); - opt->embed = 0; - } - switch (opt->style) { - case FONT_STYLE_BOLD: - strcat(fontname, ",Bold"); - break; - case FONT_STYLE_ITALIC: - strcat(fontname, ",Italic"); - break; - case FONT_STYLE_BOLDITALIC: - strcat(fontname, ",BoldItalic"); - break; - } - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = csi; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - /* getting font info. from TrueType tables */ - if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) - ERROR("Could not obtain necessary font info."); - - if (opt->embed) { - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - } - - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string(csi->registry, strlen(csi->registry))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string(csi->ordering, strlen(csi->ordering))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(csi->supplement)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), - pdf_new_number(1000)); /* not sure */ - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - -void -CIDFont_type0_t1cdofont (CIDFont *font) -{ - sfnt *sfont; - cff_font *cffont; - cff_index *charstrings, *idx; - long charstring_len, max_len; - long destlen = 0; - long size, offset = 0; - card8 *data; - card16 num_glyphs, gid, last_cid; - long i, cid; - int parent_id; - char *used_chars; - double default_width, nominal_width; - FILE *fp = NULL; - - ASSERT(font); - - if (!font->indirect) - return; - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); - if (!fp) - ERROR("Could not open OpenType font file: %s", font->ident); - - sfont = sfnt_open(fp); -#endif - if (!sfont) - ERROR("Could not open OpenType font file: %s", font->ident); - - if (sfnt_read_table_directory(sfont, 0) < 0 || - sfont->type != SFNT_TYPE_POSTSCRIPT) - ERROR("Not a CFF/OpenType font ?"); - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) - ERROR("Not a CFF/OpenType font ?"); - - cffont = cff_open(fp, offset, font->options->index); - if (!cffont) - ERROR("Could not open CFF font."); - if (cffont->flag & FONTTYPE_CIDFONT) - ERROR("This is CIDFont..."); - - cff_read_private(cffont); - cff_read_subrs (cffont); - - if (cffont->private[0] && cff_dict_known(cffont->private[0], "StdVW")) { - double stemv; - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - pdf_add_dict(font->descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - } - if (cffont->private[0] && cff_dict_known(cffont->private[0], "defaultWidthX")) { - default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - default_width = CFF_DEFAULTWIDTHX_DEFAULT; - } - if (cffont->private[0] && cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominal_width = CFF_NOMINALWIDTHX_DEFAULT; - } - - num_glyphs = 0; last_cid = 0; - add_to_used_chars2(used_chars, 0); /* .notdef */ - for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { - int c, j; - - c = used_chars[i]; - for (j = 7; j >= 0; j--) { - if (c & (1 << j)) { - num_glyphs++; - last_cid = (i + 1) * 8 - j - 1; - } - } - } - - { - cff_fdselect *fdselect; - - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 1; - fdselect->data.ranges = NEW(1, cff_range3); - fdselect->data.ranges[0].first = 0; - fdselect->data.ranges[0].fd = 0; - cffont->fdselect = fdselect; - } - - { - cff_charsets *charset; - - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = num_glyphs-1; - charset->data.glyphs = NEW(num_glyphs-1, s_SID); - - for (gid = 0, cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - if (gid > 0) - charset->data.glyphs[gid-1] = cid; - gid++; - } - } - /* cff_release_charsets(cffont->charsets); */ - cffont->charsets = charset; - } - - cff_dict_add(cffont->topdict, "CIDCount", 1); - cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); - - cffont->fdarray = NEW(1, cff_dict *); - cffont->fdarray[0] = cff_new_dict(); - cff_dict_add(cffont->fdarray[0], "FontName", 1); - cff_dict_set(cffont->fdarray[0], "FontName", 0, - (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ - cff_dict_add(cffont->fdarray[0], "Private", 2); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - /* FDArray - index offset, not known yet */ - cff_dict_add(cffont->topdict, "FDArray", 1); - cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); - /* FDSelect - offset, not known yet */ - cff_dict_add(cffont->topdict, "FDSelect", 1); - cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - cff_dict_remove(cffont->topdict, "Private"); - cff_dict_remove(cffont->topdict, "Encoding"); - - - /* */ - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - idx = cff_get_index_header(cffont); - /* offset is now absolute offset ... bad */ - offset = ftell(cffont->stream); - - if (idx->count < 2) - ERROR("No valid charstring data found."); - - /* New CharStrings INDEX */ - charstrings = cff_new_index((card16)(num_glyphs+1)); - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - gid = 0; - data = NEW(CS_STR_LEN_MAX, card8); - for (cid = 0; cid <= last_cid; cid++) { - if (!is_used_char2(used_chars, cid)) - continue; - - if ((size = (idx->offset)[cid+1] - (idx->offset)[cid]) - > CS_STR_LEN_MAX) - ERROR("Charstring too long: gid=%u", cid); - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - (charstrings->offset)[gid] = charstring_len + 1; - seek_absolute(cffont->stream, offset + (idx->offset)[cid] - 1); - fread(data, 1, size, cffont->stream); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, (cffont->subrs)[0], - default_width, nominal_width, NULL); - gid++; - } - if (gid != num_glyphs) - ERROR("Unexpeced error: ?????"); - RELEASE(data); - cff_release_index(idx); - - (charstrings->offset)[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - cffont->num_glyphs = num_glyphs; - cffont->cstrings = charstrings; - - /* no Global subr */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - - if (cffont->subrs && cffont->subrs[0]) { - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - } - if (cffont->private && (cffont->private)[0]) { - cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */ - } - - cff_add_string(cffont, "Adobe", 1); - cff_add_string(cffont, "Identity", 1); - - cff_dict_update(cffont->topdict, cffont); - cff_dict_update(cffont->private[0], cffont); - cff_update_string(cffont); - - /* CFF code need to be rewrote... */ - cff_dict_add(cffont->topdict, "ROS", 3); - cff_dict_set(cffont->topdict, "ROS", 0, - (double) cff_get_sid(cffont, "Adobe")); - cff_dict_set(cffont->topdict, "ROS", 1, - (double) cff_get_sid(cffont, "Identity")); - cff_dict_set(cffont->topdict, "ROS", 2, 0.0); - - destlen = write_fontfile(font, cffont); - - cff_close(cffont); - - /* - * DW, W, DW2 and W2: - * Those values are obtained from OpenType table (not TFM). - */ - { - unsigned char *CIDToGIDMap; - - CIDToGIDMap = NEW(2 * (last_cid+1), unsigned char); - memset(CIDToGIDMap, 0, 2 * (last_cid + 1)); - for (cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - CIDToGIDMap[2*cid ] = (cid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = cid & 0xff; - } - } - add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, - ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); - RELEASE(CIDToGIDMap); - } - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) - MESG("[%u glyphs][%ld bytes]", num_glyphs, destlen); - - /* - * CIDSet: - * Length of CIDSet stream is not clear. Must be 8192 bytes long? - */ - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - return; -} - -int -CIDFont_type0_t1copen (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - CIDSysInfo *csi; - char *fontname; - sfnt *sfont; - cff_font *cffont; - unsigned long offset = 0; - FILE *fp = NULL; - - ASSERT(font); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); -#endif - if (!sfont) { - ERROR("Not a CFF/OpenType font?"); - } - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0 || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font?"); - } - - cffont = cff_open(fp, offset, opt->index); - if (!cffont) { - ERROR("Cannot read CFF font data"); - } - - if (cffont->flag & FONTTYPE_CIDFONT) { - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return -1; - } - - csi = NEW(1, CIDSysInfo); - csi->registry = NEW(strlen("Adobe")+1, char); - strcpy(csi->registry, "Adobe"); - csi->ordering = NEW(strlen("Identity")+1, char); - strcpy(csi->ordering, "Identity"); - csi->supplement = 0; - - if (cmap_csi) { - if (strcmp(csi->registry, cmap_csi->registry) != 0 || - strcmp(csi->ordering, cmap_csi->ordering) != 0) { - MESG("\nCharacter collection mismatched:\n"); - MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); - MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); - ERROR("Inconsistent CMap specified for this font."); - } - if (csi->supplement < cmap_csi->supplement) { - WARN("CMap have higher supplmement number."); - WARN("Some characters may not be displayed or printed."); - } - } - - { - char *shortname; - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - /* Mangled name requires more 7 bytes. */ - - fontname = NEW(strlen(shortname) + 8, char); - memset(fontname, 0, strlen(shortname) + 8); - strcpy(fontname, shortname); - RELEASE(shortname); - } - cff_close(cffont); - - opt->embed = 1; - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = csi; - font->flags |= CIDFONT_FLAG_TYPE1C; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - /* getting font info. from TrueType tables */ - if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) - ERROR("Could not obtain necessary font info."); - - if (opt->embed) { - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - } - - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string(csi->registry, strlen(csi->registry))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string(csi->ordering, strlen(csi->ordering))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(csi->supplement)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - - -/* Type1 --> CFF CIDFont */ -#include "unicode.h" -#include "t1_load.h" -#include "t1_char.h" - -#include "agl.h" - -#include "cmap.h" -#include "cmap_write.h" -#include "fontmap.h" - -static int -load_base_CMap (const char *font_name, int wmode, cff_font *cffont) -{ - int cmap_id = -1; - CMap *cmap; - char *cmap_name; - card16 gid; - unsigned char range_min[4] = {0x00, 0x00, 0x00, 0x00}; - unsigned char range_max[4] = {0x7f, 0xff, 0xff, 0xff}; - - cmap_name = NEW(strlen(font_name)+strlen("-UCS4-H")+1, char); - if (wmode) { - sprintf(cmap_name, "%s-UCS4-V", font_name); - } else { - sprintf(cmap_name, "%s-UCS4-H", font_name); - } - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id >= 0) { - RELEASE(cmap_name); - return cmap_id; - } - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - CMap_add_codespacerange(cmap, range_min, range_max, 4); - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - RELEASE(cmap_name); - - for (gid = 1; gid < cffont->num_glyphs; gid++) { - long ucv; - s_SID sid; - char *glyph, *name, *suffix; - unsigned char srcCode[4]; - - sid = cff_charsets_lookup_inverse(cffont, gid); - glyph = cff_get_string (cffont, sid); - - name = agl_chop_suffix(glyph, &suffix); - if (!name) { - if (suffix) - RELEASE(suffix); - RELEASE(glyph); - continue; - } - - if (suffix) { - RELEASE(name); - RELEASE(suffix); - RELEASE(glyph); - continue; - } - - if (agl_name_is_unicode(name)) { - ucv = agl_name_convert_unicode(name); - srcCode[0] = (ucv >> 24) & 0xff; - srcCode[1] = (ucv >> 16) & 0xff; - srcCode[2] = (ucv >> 8) & 0xff; - srcCode[3] = ucv & 0xff; - CMap_add_cidchar(cmap, srcCode, 4, gid); - } else { - agl_name *agln; - - agln = agl_lookup_list(name); - if (!agln) - WARN("Glyph \"%s\" inaccessible (no Unicode mapping)", glyph); - while (agln) { - if (agln->n_components > 1) { - WARN("Glyph \"%s\" inaccessible (composite character)", glyph); - } else if (agln->n_components == 1) { - ucv = agln->unicodes[0]; - srcCode[0] = (ucv >> 24) & 0xff; - srcCode[1] = (ucv >> 16) & 0xff; - srcCode[2] = (ucv >> 8) & 0xff; - srcCode[3] = ucv & 0xff; - CMap_add_cidchar(cmap, srcCode, 4, gid); - } - agln = agln->alternate; - } - } - RELEASE(name); - if (suffix) - RELEASE(suffix); - RELEASE(glyph); - } - cmap_id = CMap_cache_add(cmap); - - return cmap_id; -} - -int -t1_load_UnicodeCMap (const char *font_name, - const char *otl_tags, /* not supported yet */ - int wmode) -{ - int cmap_id = -1; - cff_font *cffont; - FILE *fp; - - if (!font_name) - return -1; - - fp = DPXFOPEN(font_name, DPX_RES_TYPE_T1FONT); - if (!fp) - return -1; - - cffont = t1_load_font(NULL, 1, fp); - DPXFCLOSE(fp); - if (!cffont) - return -1; - - cmap_id = load_base_CMap(font_name, wmode, cffont); - - cff_close(cffont); - - if (cmap_id < 0) { - ERROR("Failed to create Unicode charmap for font \"%s\".", font_name); - return -1; - } - - if (otl_tags) { - WARN("Glyph substitution not supported for Type1 font yet..."); - } - - return cmap_id; -} - - -/* - * ToUnicode CMap - */ - -static pdf_obj * -create_ToUnicode_stream (cff_font *cffont, - const char *font_name, const char *used_glyphs) -{ - pdf_obj *stream = NULL; - CMap *cmap; - CID cid; - card16 gid; - long glyph_count, total_fail_count; - char *cmap_name; -#define WBUF_SIZE 1024 - unsigned char wbuf[WBUF_SIZE]; - unsigned char *p, *endptr; - static unsigned char range_min[2] = {0x00, 0x00}; - static unsigned char range_max[2] = {0xff, 0xff}; - - if (!font_name || !used_glyphs) - return NULL; - - cmap = CMap_new(); - - cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+1, char); - strcpy(cmap_name, font_name); - strcat(cmap_name, "-UTF16"); - CMap_set_name (cmap, cmap_name); - RELEASE(cmap_name); - - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - - CMap_add_codespacerange(cmap, range_min, range_max, 2); - - glyph_count = total_fail_count = 0; - p = wbuf; - endptr = wbuf + WBUF_SIZE; - for (cid = 1; cid < cffont->num_glyphs; cid++) { /* Skip .notdef */ - if (is_used_char2(used_glyphs, cid)) { - char *glyph; - long len; - int fail_count; - - wbuf[0] = (cid >> 8) & 0xff; - wbuf[1] = (cid & 0xff); - - p = wbuf + 2; - gid = cff_charsets_lookup_inverse(cffont, cid); - if (gid == 0) - continue; - glyph = cff_get_string(cffont, gid); - if (glyph) { - len = agl_sput_UTF16BE(glyph, &p, endptr, &fail_count); - if (len < 1 || fail_count) { - total_fail_count += fail_count; - } else { - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); - } - RELEASE(glyph); - } - glyph_count++; - } - } - - if (total_fail_count != 0 && - total_fail_count >= glyph_count/10) { - WARN("%d glyph names (out of %d) missing Unicode mapping.", - total_fail_count, glyph_count); - WARN("ToUnicode CMap \"%s-UTF16\" removed.", font_name); - } else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - - -int -CIDFont_type0_t1open (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - FILE *fp; - char *fontname, *shortname; - cff_font *cffont; - - ASSERT(font); - - if (cmap_csi && - (strcmp(cmap_csi->registry, "Adobe") != 0 || - strcmp(cmap_csi->ordering, "Identity") != 0)) { - return -1; - } - fp = DPXFOPEN(name, DPX_RES_TYPE_T1FONT); - if (!fp) - return -1; - - cffont = t1_load_font(NULL, 1, fp); - if (!cffont) { - DPXFCLOSE(fp); - return -1; - } - DPXFCLOSE(fp); - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - fontname = NEW(strlen(shortname) + 8, char); - memset(fontname, 0, strlen(shortname) + 8); - strcpy(fontname, shortname); - RELEASE(shortname); - -#ifdef XETEX - font->ft_to_gid = cff_get_ft_to_gid(cffont); - cffont->ft_to_gid = NULL; -#endif - - cff_close(cffont); - - if (opt->style != FONT_STYLE_NONE) { - WARN(",Bold, ,Italic, ... not supported for this type of font..."); - opt->style = FONT_STYLE_NONE; - } - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = NEW(1, CIDSysInfo); - font->csi->registry = NEW(strlen("Adobe")+1, char); - strcpy(font->csi->registry, "Adobe"); - font->csi->ordering = NEW(strlen("Identity")+1, char); - strcpy(font->csi->ordering, "Identity"); - font->csi->supplement = 0; - font->flags |= CIDFONT_FLAG_TYPE1; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - - font->descriptor = pdf_new_dict(); - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict; - - csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string("Adobe", strlen("Adobe"))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string("Identity", strlen("Identity"))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(0.0)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - - - return 0; -} - -/* Duplicate from type1.c */ -#define TYPE1_NAME_LEN_MAX 127 - -#define FONT_FLAG_FIXEDPITCH (1 << 0) /* Fixed-width font */ -#define FONT_FLAG_SERIF (1 << 1) /* Serif font */ -#define FONT_FLAG_SYMBOLIC (1 << 2) /* Symbolic font */ -#define FONT_FLAG_SCRIPT (1 << 3) /* Script font */ -#define FONT_FLAG_STANDARD (1 << 5) /* Adobe Standard Character Set */ -#define FONT_FLAG_ITALIC (1 << 6) /* Italic */ -#define FONT_FLAG_ALLCAP (1 << 16) /* All-cap font */ -#define FONT_FLAG_SMALLCAP (1 << 17) /* Small-cap font */ -#define FONT_FLAG_FORCEBOLD (1 << 18) /* Force bold at small text sizes */ - -/* pdf_font --> CIDFont */ -static void -get_font_attr (CIDFont *font, cff_font *cffont) -{ - double capheight, ascent, descent; - double italicangle, stemv; - double defaultwidth, nominalwidth; - long flags = 0; - long gid; - int i; - static const char *L_c[] = { - "H", "P", "Pi", "Rho", NULL - }; - static const char *L_d[] = { - "p", "q", "mu", "eta", NULL - }; - static const char *L_a[] = { - "b", "h", "lambda", NULL - }; - t1_ginfo gm; - - defaultwidth = 500.0; - nominalwidth = 0.0; - - /* - * CapHeight, Ascent, and Descent is meaningfull only for Latin/Greek/Cyrillic. - * The BlueValues and OtherBlues also have those information. - */ - if (cff_dict_known(cffont->topdict, "FontBBox")) { - /* Default values */ - capheight = ascent = cff_dict_get(cffont->topdict, "FontBBox", 3); - descent = cff_dict_get(cffont->topdict, "FontBBox", 1); - } else { - capheight = 680.0; - ascent = 690.0; - descent = -190.0; - } - if (cff_dict_known(cffont->private[0], "StdVW")) { - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - } else { - /* - * We may use the following values for StemV: - * Thin - ExtraLight: <= 50 - * Light: 71 - * Regular(Normal): 88 - * Medium: 109 - * SemiBold(DemiBold): 135 - * Bold - Heavy: >= 166 - */ - stemv = 88.0; - } - if (cff_dict_known(cffont->topdict, "ItalicAngle")) { - italicangle = cff_dict_get(cffont->topdict, "ItalicAngle", 0); - if (italicangle != 0.0) - flags |= FONT_FLAG_ITALIC; - } else { - italicangle = 0.0; - } - - /* - * Use "space", "H", "p", and "b" for various values. - * Those characters should not "seac". (no accent) - */ - gid = cff_glyph_lookup(cffont, "space"); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - defaultwidth = gm.wx; - } - - for (i = 0; L_c[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_c[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - capheight = gm.bbox.ury; - break; - } - } - - for (i = 0; L_d[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_d[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - descent = gm.bbox.lly; - break; - } - } - - for (i = 0; L_a[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_a[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - ascent = gm.bbox.ury; - break; - } - } - - if (defaultwidth != 0.0) { - cff_dict_add(cffont->private[0], "defaultWidthX", 1); - cff_dict_set(cffont->private[0], "defaultWidthX", 0, defaultwidth); - } - if (nominalwidth != 0.0) { - cff_dict_add(cffont->private[0], "nominalWidthX", 1); - cff_dict_set(cffont->private[0], "nominalWidthX", 0, nominalwidth); - } - if (cff_dict_known(cffont->private[0], "ForceBold") && - cff_dict_get(cffont->private[0], "ForceBold", 0)) { - flags |= FONT_FLAG_FORCEBOLD; - } - if (cff_dict_known(cffont->private[0], "IsFixedPitch") && - cff_dict_get(cffont->private[0], "IsFixedPitch", 0)) { - flags |= FONT_FLAG_FIXEDPITCH; - } - if (font->fontname && - !strstr(font->fontname, "Sans")) { - flags |= FONT_FLAG_SERIF; - } - flags |= FONT_FLAG_SYMBOLIC; - - pdf_add_dict(font->descriptor, - pdf_new_name("CapHeight"), pdf_new_number(capheight)); - pdf_add_dict(font->descriptor, - pdf_new_name("Ascent"), pdf_new_number(ascent)); - pdf_add_dict(font->descriptor, - pdf_new_name("Descent"), pdf_new_number(descent)); - pdf_add_dict(font->descriptor, - pdf_new_name("ItalicAngle"), pdf_new_number(italicangle)); - pdf_add_dict(font->descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - pdf_add_dict(font->descriptor, - pdf_new_name("Flags"), pdf_new_number(flags)); -} - -static void -add_metrics (CIDFont *font, cff_font *cffont, - unsigned char *CIDToGIDMap, - double *widths, double default_width, CID last_cid) -{ - pdf_obj *tmp; - double val; - card16 cid, gid; - char *used_chars; - int i, parent_id; - - /* - * The original FontBBox of the font is preserved, instead - * of replacing it with tight bounding box calculated from - * charstrings, to prevent Acrobat 4 from greeking text as - * much as possible. - */ - if (!cff_dict_known(cffont->topdict, "FontBBox")) { - ERROR("No FontBBox?"); - } - tmp = pdf_new_array(); - for (i = 0; i < 4; i++) { - val = cff_dict_get(cffont->topdict, "FontBBox", i); - pdf_add_array(tmp, pdf_new_number(ROUND(val, 1.0))); - } - pdf_add_dict(font->descriptor, pdf_new_name("FontBBox"), tmp); - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) { - ERROR("Unexpected error: Font not actually used???"); - } - - /* FIXME: - * This writes "CID CID width". - * I think it's better to handle each 8 char block - * and to use "CID_start [ w0 w1 ...]". - */ - tmp = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - gid = (CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]; - if (widths[gid] != default_width) { - pdf_add_array(tmp, pdf_new_number(cid)); - pdf_add_array(tmp, pdf_new_number(cid)); - pdf_add_array(tmp, pdf_new_number(ROUND(widths[gid], 1.0))); - } - } - } - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(default_width)); - if (pdf_array_length(tmp) > 0) { - pdf_add_dict(font->fontdict, pdf_new_name("W"), pdf_ref_obj(tmp)); - } - pdf_release_obj(tmp); -} - -void -CIDFont_type0_t1dofont (CIDFont *font) -{ - cff_font *cffont; - double defaultwidth, nominalwidth; - long num_glyphs = 0; - FILE *fp; - long i, offset; - char *used_chars = NULL; - card16 last_cid, gid, cid; - unsigned char *CIDToGIDMap; - - ASSERT(font); - - if (!font->indirect) { - return; - } - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_T1FONT); - if (!fp) { - ERROR("Type1: Could not open Type1 font."); - } - - cffont = t1_load_font(NULL, 0, fp); - if (!cffont) - ERROR("Could not read Type 1 font..."); - DPXFCLOSE(fp); - - if (!font->fontname) - ERROR("Fontname undefined..."); - - { - Type0Font *hparent, *vparent; - pdf_obj *tounicode; - int vparent_id, hparent_id; - - hparent_id = CIDFont_get_parent_id(font, 0); - vparent_id = CIDFont_get_parent_id(font, 1); - if (hparent_id < 0 && vparent_id < 0) - ERROR("No parent Type 0 font !"); - - /* usedchars is same for h and v */ - if (hparent_id < 0) - hparent = NULL; - else { - hparent = Type0Font_cache_get(hparent_id); - used_chars = Type0Font_get_usedchars(hparent); - } - if (vparent_id < 0) - vparent = NULL; - else { - vparent = Type0Font_cache_get(vparent_id); - used_chars = Type0Font_get_usedchars(vparent); - } - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - - tounicode = create_ToUnicode_stream(cffont, font->fontname, used_chars); - - if (hparent) - Type0Font_set_ToUnicode(hparent, pdf_ref_obj(tounicode)); - if (vparent) - Type0Font_set_ToUnicode(vparent, pdf_ref_obj(tounicode)); - pdf_release_obj(tounicode); - } - - cff_set_name(cffont, font->fontname); - - /* defaultWidthX, CapHeight, etc. */ - get_font_attr(font, cffont); - if (cff_dict_known(cffont->private[0], "defaultWidthX")) { - defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - defaultwidth = 0.0; - } - if (cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominalwidth = 0.0; - } - - num_glyphs = 0; last_cid = 0; - add_to_used_chars2(used_chars, 0); /* .notdef */ - for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { - int c, j; - - c = used_chars[i]; - for (j = 7; j >= 0; j--) { - if (c & (1 << j)) { - num_glyphs++; - last_cid = (i + 1) * 8 - j - 1; - } - } - } - - { - cff_fdselect *fdselect; - - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 1; - fdselect->data.ranges = NEW(1, cff_range3); - fdselect->data.ranges[0].first = 0; - fdselect->data.ranges[0].fd = 0; - cffont->fdselect = fdselect; - } - - CIDToGIDMap = NEW(2*(last_cid+1), unsigned char); - memset(CIDToGIDMap, 0, 2*(last_cid+1)); - { - cff_charsets *charset; - - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = num_glyphs-1; - charset->data.glyphs = NEW(num_glyphs-1, s_SID); - - for (gid = 0, cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - if (gid > 0) - charset->data.glyphs[gid-1] = cid; - CIDToGIDMap[2*cid ] = (gid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = gid & 0xff; - gid++; - } - } - - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - } - - cff_dict_add(cffont->topdict, "CIDCount", 1); - cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); - - cffont->fdarray = NEW(1, cff_dict *); - cffont->fdarray[0] = cff_new_dict(); - cff_dict_add(cffont->fdarray[0], "FontName", 1); - cff_dict_set(cffont->fdarray[0], "FontName", 0, - (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ - cff_dict_add(cffont->fdarray[0], "Private", 2); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - - /* FDArray - index offset, not known yet */ - cff_dict_add(cffont->topdict, "FDArray", 1); - cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); - /* FDSelect - offset, not known yet */ - cff_dict_add(cffont->topdict, "FDSelect", 1); - cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); - - cff_dict_add(cffont->topdict, "charset", 1); - cff_dict_set(cffont->topdict, "charset", 0, 0.0); - - cff_dict_add(cffont->topdict, "CharStrings", 1); - cff_dict_set(cffont->topdict, "CharStrings", 0, 0.0); - - { - cff_index *cstring; - t1_ginfo gm; - long max = 0; - double *widths; - int w_stat[1001], max_count, dw; - - widths = NEW(num_glyphs, double); - memset(w_stat, 0, sizeof(int)*1001); - offset = 0L; - cstring = cff_new_index((card16)num_glyphs); - cstring->data = NULL; - cstring->offset[0] = 1; - gid = 0; - for (cid = 0; cid <= last_cid; cid++) { - if (!is_used_char2(used_chars, cid)) - continue; - - if (offset + CS_STR_LEN_MAX >= max) { - max += CS_STR_LEN_MAX*2; - cstring->data = RENEW(cstring->data, max, card8); - } - offset += t1char_convert_charstring(cstring->data + cstring->offset[gid] - 1, CS_STR_LEN_MAX, - cffont->cstrings->data + cffont->cstrings->offset[cid] - 1, - cffont->cstrings->offset[cid+1] - cffont->cstrings->offset[cid], - cffont->subrs[0], defaultwidth, nominalwidth, &gm); - cstring->offset[gid+1] = offset + 1; - if (gm.use_seac) { - ERROR("This font using the \"seac\" command for accented characters..."); - } - widths[gid] = gm.wx; - if (gm.wx >= 0.0 && gm.wx <= 1000.0) { - w_stat[((int) gm.wx)] += 1; - } - gid++; - } - - cff_release_index(cffont->cstrings); - cffont->cstrings = cstring; - - max_count = 0; dw = -1; - for (i = 0; i <= 1000; i++) { - if (w_stat[i] > max_count) { - dw = i; - max_count = w_stat[i]; - } - } - if (dw >= 0) { - add_metrics(font, cffont, CIDToGIDMap, widths, dw, last_cid); - } else { - add_metrics(font, cffont, CIDToGIDMap, widths, defaultwidth, last_cid); - } - RELEASE(widths); - } - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - - RELEASE(CIDToGIDMap); - - cff_add_string(cffont, "Adobe", 1); - cff_add_string(cffont, "Identity", 1); - - cff_dict_update(cffont->topdict, cffont); - cff_dict_update(cffont->private[0], cffont); - - cff_update_string(cffont); - - /* CFF code need to be rewrote... */ - cff_dict_add(cffont->topdict, "ROS", 3); - cff_dict_set(cffont->topdict, "ROS", 0, - (double) cff_get_sid(cffont, "Adobe")); - cff_dict_set(cffont->topdict, "ROS", 1, - (double) cff_get_sid(cffont, "Identity")); - cff_dict_set(cffont->topdict, "ROS", 2, 0.0); - - cffont->num_glyphs = num_glyphs; - offset = write_fontfile(font, cffont); - - cff_close(cffont); - - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - - return; -} - -void -CIDFont_type0_release(CIDFont *font) -{ -#ifdef XETEX - if (font->ft_to_gid) - RELEASE(font->ft_to_gid); -#endif - return; -} diff --git a/Build/source/texk/dvipdfm-x/src/dvi.c b/Build/source/texk/dvipdfm-x/src/dvi.c deleted file mode 100644 index 9328866cb16..00000000000 --- a/Build/source/texk/dvipdfm-x/src/dvi.c +++ /dev/null @@ -1,2481 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "numbers.h" - -#include "pdfdev.h" -#include "pdfdoc.h" -#include "pdfparse.h" -#include "pdfencrypt.h" - -#include "fontmap.h" - -#include "dvicodes.h" -#include "tfm.h" -#include "vf.h" -#include "subfont.h" - -#include "spc_util.h" -#include "specials.h" - -#include "dvi.h" - -#ifdef XETEX -#include "pdfximage.h" -#include FT_ADVANCES_H -#endif - -#define DVI_STACK_DEPTH_MAX 256u -#define TEX_FONTS_ALLOC_SIZE 16u -#define VF_NESTING_MAX 16u - -/* UTF-32 over U+FFFF -> UTF-16 surrogate pair */ -#define UTF32toUTF16HS(x) (0xd800 + (((x-0x10000) >> 10) & 0x3ff)) -#define UTF32toUTF16LS(x) (0xdc00 + ( x & 0x3ff)) - -/* Interal Variables */ -static FILE *dvi_file = NULL; - -static unsigned long *page_loc = NULL; -static UNSIGNED_PAIR num_pages = 0; - -static unsigned long dvi_file_size = 0; - -static struct dvi_header -{ - UNSIGNED_QUAD unit_num; - UNSIGNED_QUAD unit_den; - UNSIGNED_QUAD mag; - UNSIGNED_QUAD media_width, media_height; - UNSIGNED_PAIR stackdepth; - char comment[257]; -} dvi_info = { - 25400000 , /* num */ - 473628672, /* den */ - 1000, /* mag */ - 0, 0, /* media width and height */ - 0, /* stackdepth */ - {'\0'} /* comment */ -}; - -static double dev_origin_x = 72.0, dev_origin_y = 770.0; - -#ifdef XETEX -double get_origin (int x) -{ - return x ? dev_origin_x : dev_origin_y; -} -#endif - -#define PHYSICAL 1 -#define VIRTUAL 2 -#define SUBFONT 3 -#define NATIVE 4 -#define DVI 1 -#define VF 2 - -static struct loaded_font -{ - int type; /* Type is physical or virtual */ - int font_id; /* id returned by dev (for PHYSICAL fonts) - * or by vf module for (VIRTUAL fonts) - */ - int subfont_id; /* id returned by subfont_locate_font() */ - int tfm_id; - spt_t size; - int source; /* Source is either DVI or VF */ -#ifdef XETEX - unsigned long rgba_color; - FT_Face ft_face; - int layout_dir; - float extend; - float slant; - float embolden; -#endif -} *loaded_fonts = NULL; -static int num_loaded_fonts = 0, max_loaded_fonts = 0; - -static void -need_more_fonts (unsigned n) -{ - if (num_loaded_fonts + n > max_loaded_fonts) { - max_loaded_fonts += TEX_FONTS_ALLOC_SIZE; - loaded_fonts = RENEW (loaded_fonts, max_loaded_fonts, struct loaded_font); - } -} - -static struct font_def -{ - long tex_id; - spt_t point_size; - spt_t design_size; - char *font_name; - int font_id; /* index of _loaded_ font in loaded_fonts array */ - int used; -#ifdef XETEX - int native; /* boolean */ - 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; - -#ifdef XETEX -#define XDV_FLAG_VERTICAL 0x0100 -#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; -static int compute_boxes = 0, link_annot = 1; -static int verbose = 0; - -#ifdef XETEX -#define DVI_PAGE_BUF_CHUNK 0x10000UL /* 64K should be plenty for most pages */ - -static unsigned char* dvi_page_buffer; -static unsigned long dvi_page_buf_size; -static unsigned long dvi_page_buf_index; - -/* functions to read numbers from the dvi file and store them in dvi_page_buffer */ -static UNSIGNED_BYTE get_and_buffer_unsigned_byte (FILE *file) -{ - int ch; - if ((ch = fgetc (file)) < 0) - ERROR ("File ended prematurely\n"); - if (dvi_page_buf_index >= dvi_page_buf_size) { - dvi_page_buf_size += DVI_PAGE_BUF_CHUNK; - dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); - } - dvi_page_buffer[dvi_page_buf_index++] = ch; - return (UNSIGNED_BYTE) ch; -} - -#if 0 -/* Not used */ -static SIGNED_BYTE get_and_buffer_signed_byte (FILE *file) -{ - int byte; - byte = get_and_buffer_unsigned_byte(file); - if (byte >= 0x80) - byte -= 0x100; - return (SIGNED_BYTE) byte; -} -#endif - -static UNSIGNED_PAIR get_and_buffer_unsigned_pair (FILE *file) -{ - int i; - UNSIGNED_BYTE byte; - UNSIGNED_PAIR pair = 0; - for (i=0; i<2; i++) { - byte = get_and_buffer_unsigned_byte(file); - pair = pair*0x100u + byte; - } - return pair; -} - -static SIGNED_PAIR get_and_buffer_signed_pair (FILE *file) -{ - int i; - long pair = 0; - for (i=0; i<2; i++) { - pair = pair*0x100 + get_and_buffer_unsigned_byte(file); - } - if (pair >= 0x8000) { - pair -= 0x10000l; - } - return (SIGNED_PAIR) pair; -} - -static UNSIGNED_TRIPLE get_and_buffer_unsigned_triple(FILE *file) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100u + get_and_buffer_unsigned_byte(file); - } - return (UNSIGNED_TRIPLE) triple; -} - -static SIGNED_TRIPLE get_and_buffer_signed_triple(FILE *file) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100 + get_and_buffer_unsigned_byte(file); - } - if (triple >= 0x800000l) - triple -= 0x1000000l; - return (SIGNED_TRIPLE) triple; -} - -static SIGNED_QUAD get_and_buffer_signed_quad(FILE *file) -{ - int byte, i; - long quad = 0; - - /* Check sign on first byte before reading others */ - byte = get_and_buffer_unsigned_byte(file); - quad = byte; - if (quad >= 0x80) - quad = byte - 0x100; - for (i=0; i<3; i++) { - quad = quad*0x100 + get_and_buffer_unsigned_byte(file); - } - return (SIGNED_QUAD) quad; -} - -static UNSIGNED_QUAD get_and_buffer_unsigned_quad(FILE *file) -{ - int i; - unsigned long quad = 0; - for (i=0; i<4; i++) { - quad = quad*0x100u + get_and_buffer_unsigned_byte(file); - } - return (UNSIGNED_QUAD) quad; -} - -static void get_and_buffer_bytes(FILE *file, unsigned int count) -{ - if (dvi_page_buf_index + count >= dvi_page_buf_size) { - dvi_page_buf_size = dvi_page_buf_index + count + DVI_PAGE_BUF_CHUNK; - dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); - } - if (fread(dvi_page_buffer + dvi_page_buf_index, 1, count, file) != count) - ERROR ("File ended prematurely\n"); - dvi_page_buf_index += count; -} - -/* functions to fetch values from dvi_page_buffer */ - -static UNSIGNED_BYTE get_buffered_unsigned_byte (void) -{ - return dvi_page_buffer[dvi_page_buf_index++]; -} - -static SIGNED_BYTE get_buffered_signed_byte (void) -{ - int byte; - byte = dvi_page_buffer[dvi_page_buf_index++]; - if (byte >= 0x80) - byte -= 0x100; - return (SIGNED_BYTE) byte; -} - -static UNSIGNED_PAIR get_buffered_unsigned_pair (void) -{ - int i; - UNSIGNED_BYTE byte; - UNSIGNED_PAIR pair = 0; - for (i=0; i<2; i++) { - byte = dvi_page_buffer[dvi_page_buf_index++]; - pair = pair*0x100u + byte; - } - return pair; -} - -static SIGNED_PAIR get_buffered_signed_pair (void) -{ - int i; - long pair = 0; - for (i=0; i<2; i++) { - pair = pair*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - if (pair >= 0x8000) { - pair -= 0x10000l; - } - return (SIGNED_PAIR) pair; -} - -static UNSIGNED_TRIPLE get_buffered_unsigned_triple(void) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100u + dvi_page_buffer[dvi_page_buf_index++]; - } - return (UNSIGNED_TRIPLE) triple; -} - -static SIGNED_TRIPLE get_buffered_signed_triple(void) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - if (triple >= 0x800000l) - triple -= 0x1000000l; - return (SIGNED_TRIPLE) triple; -} - -static SIGNED_QUAD get_buffered_signed_quad(void) -{ - int byte, i; - long quad = 0; - - /* Check sign on first byte before reading others */ - byte = dvi_page_buffer[dvi_page_buf_index++]; - quad = byte; - if (quad >= 0x80) - quad = byte - 0x100; - for (i=0; i<3; i++) { - quad = quad*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - return (SIGNED_QUAD) quad; -} - -static UNSIGNED_QUAD get_buffered_unsigned_quad(void) -{ - int i; - unsigned long quad = 0; - for (i=0; i<4; i++) { - quad = quad*0x100u + dvi_page_buffer[dvi_page_buf_index++]; - } - return (UNSIGNED_QUAD) quad; -} -#else -#define get_and_buffer_unsigned_byte(fp) get_unsigned_byte(fp) -#if 0 -#define get_and_buffer_signed_byte(fp) get_signed_byte(fp) -#endif -#define get_and_buffer_unsigned_pair(fp) get_unsigned_pair(fp) -#define get_and_buffer_signed_pair(fp) get_signed_pair(fp) -#define get_and_buffer_unsigned_triple(fp) get_unsigned_triple(fp) -#define get_and_buffer_signed_triple(fp) get_signed_triple(fp) -#define get_and_buffer_signed_quad(fp) get_unsigned_quad(fp) -#define get_and_buffer_unsigned_quad(fp) get_unsigned_quad(fp) -#define get_and_buffer_bytes(fp, ct) seek_relative(fp, ct) - -#define get_buffered_unsigned_byte() get_unsigned_byte(dvi_file) -#define get_buffered_signed_byte() get_signed_byte(dvi_file) -#define get_buffered_unsigned_pair() get_unsigned_pair(dvi_file) -#define get_buffered_signed_pair() get_signed_pair(dvi_file) -#define get_buffered_unsigned_triple() get_unsigned_triple(dvi_file) -#define get_buffered_signed_triple() get_signed_triple(dvi_file) -#define get_buffered_signed_quad() get_signed_quad(dvi_file) -#define get_buffered_unsigned_quad() get_unsigned_quad(dvi_file) -#endif - -void -dvi_set_verbose (void) -{ - verbose++; - subfont_set_verbose(); - tfm_set_verbose(); - vf_set_verbose (); - spc_set_verbose(); -} - -unsigned -dvi_npages (void) -{ - return num_pages; -} - -static const char invalid_signature[] = -"Something is wrong. Are you sure this is a DVI file?"; - -#define range_check_loc(loc) \ - if ((loc) > dvi_file_size) {\ - ERROR(invalid_signature); \ - } - -static long -find_post (void) -{ - long current; - int ch; - - /* First find end of file */ - dvi_file_size = file_size(dvi_file); - current = dvi_file_size; - - /* Scan backwards through PADDING */ - do { - current--; - seek_absolute(dvi_file, current); - } while ((ch = fgetc(dvi_file)) == PADDING && - current > 0); - - /* file_position now points to last non padding character or - * beginning of file */ - if (dvi_file_size - current < 4 || current == 0 || -#ifdef XETEX - !(ch == DVI_ID || ch == DVIV_ID || ch == XDVI_ID)) { -#else - !(ch == DVI_ID || ch == DVIV_ID)) { -#endif - MESG("DVI ID = %d\n", ch); - ERROR(invalid_signature); - } - - /* Make sure post_post is really there */ - current = current - 5; - seek_absolute(dvi_file, current); - if ((ch = fgetc(dvi_file)) != POST_POST) { - MESG("Found %d where post_post opcode should be\n", ch); - ERROR(invalid_signature); - } - current = get_signed_quad(dvi_file); - seek_absolute(dvi_file, current); - if ((ch = fgetc(dvi_file)) != POST) { - MESG("Found %d where post_post opcode should be\n", ch); - ERROR(invalid_signature); - } - - return current; -} - -static void -get_page_info (long post_location) -{ - int i; - - seek_absolute(dvi_file, post_location + 27); - num_pages = get_unsigned_pair(dvi_file); - if (num_pages == 0) { - ERROR("Page count is 0!"); - } - if (verbose > 2) { - MESG("Page count:\t %4d\n", num_pages); - } - - page_loc = NEW(num_pages, unsigned long); - - seek_absolute(dvi_file, post_location + 1); - page_loc[num_pages-1] = get_unsigned_quad(dvi_file); - range_check_loc(page_loc[num_pages-1] + 41); - for (i = num_pages - 2; i >= 0; i--) { - seek_absolute(dvi_file, page_loc[i+1] + 41); - page_loc[i] = get_unsigned_quad(dvi_file); - range_check_loc(page_loc[num_pages-1] + 41); - } -} - -/* Following are computed "constants" used for unit conversion */ -static double dvi2pts = 1.52018, total_mag = 1.0; - -double -dvi_tell_mag (void) -{ - return total_mag; -} - -static void -do_scales (double mag) -{ - total_mag = (double) dvi_info.mag / 1000.0 * mag; - dvi2pts = (double) dvi_info.unit_num / (double) dvi_info.unit_den; - dvi2pts *= (72.0 / 254000.0); -} - -static void -get_dvi_info (long post_location) -{ - seek_absolute(dvi_file, post_location + 5); - - dvi_info.unit_num = get_unsigned_quad(dvi_file); - dvi_info.unit_den = get_unsigned_quad(dvi_file); - dvi_info.mag = get_unsigned_quad(dvi_file); - - dvi_info.media_height = get_unsigned_quad(dvi_file); - dvi_info.media_width = get_unsigned_quad(dvi_file); - - dvi_info.stackdepth = get_unsigned_pair(dvi_file); - - if (dvi_info.stackdepth > DVI_STACK_DEPTH_MAX) { - WARN("DVI need stack depth of %d,", dvi_info.stackdepth); - WARN("but DVI_STACK_DEPTH_MAX is %d.", DVI_STACK_DEPTH_MAX); - ERROR("Capacity exceeded."); - } - - if (verbose > 2) { - MESG("DVI File Info\n"); - MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den); - MESG("Magnification: %ld\n", dvi_info.mag); - MESG("Media Height: %ld\n", dvi_info.media_height); - MESG("Media Width: %ld\n", dvi_info.media_width); - MESG("Stack Depth: %d\n", dvi_info.stackdepth); - } -} - -const char * -dvi_comment (void) -{ - return dvi_info.comment; -} - -static void -read_font_record (SIGNED_QUAD tex_id) -{ - UNSIGNED_BYTE dir_length, name_length; - UNSIGNED_QUAD point_size, design_size; - char *directory, *font_name; - - if (num_def_fonts >= max_def_fonts) { - max_def_fonts += TEX_FONTS_ALLOC_SIZE; - def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def); - } - get_unsigned_quad(dvi_file); - point_size = get_unsigned_quad(dvi_file); - design_size = get_unsigned_quad(dvi_file); - dir_length = get_unsigned_byte(dvi_file); - name_length = get_unsigned_byte(dvi_file); - - directory = NEW(dir_length + 1, char); - if (fread(directory, 1, dir_length, dvi_file) != dir_length) { - ERROR(invalid_signature); - } - directory[dir_length] = '\0'; - RELEASE(directory); /* unused */ - - font_name = NEW(name_length + 1, char); - if (fread(font_name, 1, name_length, dvi_file) != name_length) { - ERROR(invalid_signature); - } - font_name[name_length] = '\0'; - def_fonts[num_def_fonts].tex_id = tex_id; - def_fonts[num_def_fonts].font_name = font_name; - def_fonts[num_def_fonts].point_size = point_size; - def_fonts[num_def_fonts].design_size = design_size; - def_fonts[num_def_fonts].used = 0; - num_def_fonts++; - - return; -} - -static void -get_dvi_fonts (long post_location) -{ - UNSIGNED_BYTE code; - SIGNED_QUAD tex_id = 0; - - seek_absolute(dvi_file, post_location + 29); - while ((code = get_unsigned_byte(dvi_file)) != POST_POST) { - switch (code) { - case FNT_DEF1: - tex_id = get_unsigned_byte(dvi_file); - break; - case FNT_DEF2: - tex_id = get_unsigned_pair(dvi_file); - break; - case FNT_DEF3: - tex_id = get_unsigned_triple(dvi_file); - break; - case FNT_DEF4: -#ifdef XETEX - case XDV_NATIVE_FONT_DEF: -#endif - tex_id = get_signed_quad(dvi_file); - break; - default: - MESG("Unexpected op code: %3d\n", code); - ERROR(invalid_signature); - } -#ifdef XETEX - if (code == XDV_NATIVE_FONT_DEF) - read_native_font_record(tex_id); - else -#endif - read_font_record(tex_id); - } - if (verbose > 2) { - unsigned i; - - MESG("\n"); - MESG("DVI file font info\n"); - for (i = 0; i < num_def_fonts; i++) { - MESG("TeX Font: %10s loaded at ID=%5ld, ", - def_fonts[i].font_name, def_fonts[i].tex_id); - MESG("size=%5.2fpt (scaled %4.1f%%)", - def_fonts[i].point_size * dvi2pts, - 100.0 * ((double) def_fonts[i].point_size / def_fonts[i].design_size)); - MESG("\n"); - } - } -} - -static void get_comment (void) -{ - UNSIGNED_BYTE length; - - seek_absolute(dvi_file, 14); - length = get_unsigned_byte(dvi_file); - if (fread(dvi_info.comment, - 1, length, dvi_file) != length) { - ERROR(invalid_signature); - } - dvi_info.comment[length] = '\0'; - if (verbose) { - MESG("DVI Comment: %s\n", dvi_info.comment); - } -} - -/* - * The section below this line deals with the actual processing of the - * dvi file. - * - * The dvi file processor state is contained in the following variables: - */ - -struct dvi_registers -{ - SIGNED_QUAD h, v, w, x, y, z, d; -}; - -static struct dvi_registers dvi_state; -static struct dvi_registers dvi_stack[DVI_STACK_DEPTH_MAX]; -static unsigned dvi_stack_depth = 0 ; -static int current_font = -1; -static int processing_page = 0 ; - -static void -clear_state (void) -{ - dvi_state.h = 0; dvi_state.v = 0; dvi_state.w = 0; - dvi_state.x = 0; dvi_state.y = 0; dvi_state.z = 0; - dvi_state.d = 0; /* direction */ - dvi_stack_depth = 0; - current_font = -1; -} - -/* Migrated from pdfdev.c: - * The following codes are originally put into pdfdev.c. - * But they are moved to here to make PDF output independent - * from DVI input. - * pdfdoc, pdfspecial and htex are also modified. pdfspecial - * and htex does tag/untag depth. pdfdev and pdfdoc now does - * not care about line-breaking at all. - */ -static unsigned marked_depth = 0; -static int tagged_depth = -1; - -static void -dvi_mark_depth (void) -{ - /* If decreasing below tagged_depth */ - if (link_annot && - marked_depth == tagged_depth && - dvi_stack_depth == tagged_depth - 1) { - /* - * See if this appears to be the end of a "logical unit" - * that's been broken. If so, flush the logical unit. - */ - pdf_doc_break_annot(); - } - marked_depth = dvi_stack_depth; -} - -/* - * The following routines setup and tear down a callback at a - * certain stack depth. This is used to handle broken (linewise) - * links. - */ -void -dvi_tag_depth (void) -{ - tagged_depth = marked_depth; - dvi_compute_boxes(1); -} - -void -dvi_untag_depth (void) -{ - tagged_depth = -1; - dvi_compute_boxes(0); -} - -void -dvi_compute_boxes (int flag) -{ - compute_boxes = flag; -} - -void -dvi_link_annot (int flag) -{ - link_annot = flag; -} - -void -dvi_do_special (const void *buffer, UNSIGNED_QUAD size) -{ - double x_user, y_user, mag; - const char *p; - - if (size > 0x7fffffffUL) { - WARN("Special more than %ul bytes???", size); - return; - } - - graphics_mode(); - - p = (const char *) buffer; - - x_user = dvi_state.h * dvi2pts; - y_user = -dvi_state.v * dvi2pts; - mag = dvi_tell_mag(); - - if (spc_exec_special(p, (long) size, x_user, y_user, mag) < 0) { - if (verbose) { - dump(p, p + size); - } - } - - return; -} - -#if 0 -double -dvi_unit_size (void) -{ - return dvi2pts; -} -#endif - - -int -dvi_locate_font (const char *tfm_name, spt_t ptsize) -{ - int cur_id = -1; - const char *name = tfm_name; - int subfont_id = -1, font_id; /* VF or device font ID */ - fontmap_rec *mrec; - - if (verbose) - MESG("<%s@%.2fpt", tfm_name, ptsize * dvi2pts); - - need_more_fonts(1); - - /* This routine needs to be recursive/reentrant. Load current high water - * mark into an automatic variable. - */ - cur_id = num_loaded_fonts++; - - mrec = pdf_lookup_fontmap_record(tfm_name); - /* Load subfont mapping table */ - if (mrec && mrec->charmap.sfd_name && mrec->charmap.subfont_id) { - subfont_id = sfd_load_record(mrec->charmap.sfd_name, mrec->charmap.subfont_id); - } - - /* TFM must exist here. */ - loaded_fonts[cur_id].tfm_id = tfm_open(tfm_name, 1); - loaded_fonts[cur_id].subfont_id = subfont_id; - loaded_fonts[cur_id].size = ptsize; - /* This will be reset later if it was really generated by the dvi file. */ - loaded_fonts[cur_id].source = VF; - - /* The order of searching fonts is as follows: - * - * 1. If mrec is null, that is, there is no map entry matching - * with tfm_name, then search a virtual font matching with - * tfm_name at first. If no virtual font is found, search a - * PK font matching with tfm_name. - * - * 2. If mrec is non-null, search a physical scalable font. - * - * 3. Notice that every subfont gets non-null mrec. In this case, - * enc_name corresponding to mrec will be used instead of mrec. - * That is enc_name is NULL, search a virtual font for Omega (.ovf) - * matching with the base name of the subfont. If no virtual font - * for Omega is found, it is a fatal error because there is no PK font - * for Omega. - */ - if (!mrec) { - font_id = vf_locate_font(tfm_name, ptsize); - if (font_id >= 0) { - loaded_fonts[cur_id].type = VIRTUAL; - loaded_fonts[cur_id].font_id = font_id; - if (verbose) - MESG("(VF)>"); - return cur_id; - } - } -#if 1 - /* Sorry, I don't understand this well... Please fix. - * The purpose of this seems to be: - * - * Map 8-bit char codes in subfont to 16-bit code with SFD mapping - * and map subfonts to single OVF font. - * - * But it apparently only does TFM -> OVF mapping but no character - * code mapping. Please see dvi_set(), you can't have both font->type - * VIRTUAL and font->subfont_id >= 0. Am I missing something? - */ - else if (subfont_id >= 0 && mrec->map_name) - { - fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); - /* enc_name=NULL should be used only for 'built-in' encoding. - * Please fix this! - */ - if (mrec1 && !mrec1->enc_name) { - font_id = vf_locate_font(mrec1->font_name, ptsize); - if (font_id < 0) - WARN("Could not locate Omega Virtual Font \"%s\" for \"%s\".", - mrec1->font_name, tfm_name); - else { - loaded_fonts[cur_id].type = VIRTUAL; - loaded_fonts[cur_id].font_id = font_id; - if (verbose) - MESG("(OVF)>"); - return cur_id; - } - } - } -#endif /* 1 */ - - /* Failed to load a virtual font so we try to load a physical font. */ - - /* If mrec->map_name is not NULL, font name identified in PDF output - * is different than tfm_name, this can happen for subfonts grouped - * into a single "intermediate" font foo@SFD@. - * This is necessary for optimal output; to avoid unnecessary creation - * of multiple instances of a same font, to avoid frequent font selection - * and break of string_mode. - */ - if (mrec && mrec->map_name) { - name = mrec->map_name; - } else { - name = tfm_name; - } - - /* We need ptsize for PK font creation. */ - font_id = pdf_dev_locate_font(name, ptsize); - if (font_id < 0) { - WARN("Could not locate a virtual/physical font for TFM \"%s\".", tfm_name); - if (mrec && mrec->map_name) { /* has map_name */ - fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); - WARN(">> This font is mapped to an intermediate 16-bit font \"%s\" with SFD charmap=<%s,%s>,", - mrec->map_name, mrec->charmap.sfd_name, mrec->charmap.subfont_id); - if (!mrec1) - WARN(">> but I couldn't find font mapping for \"%s\".", mrec->map_name); - else { - WARN(">> and then mapped to a physical font \"%s\" by fontmap.", mrec1->font_name); - WARN(">> Please check if kpathsea library can find this font: %s", mrec1->font_name); - } - } else if (mrec && !mrec->map_name) { - WARN(">> This font is mapped to a physical font \"%s\".", mrec->font_name); - WARN(">> Please check if kpathsea library can find this font: %s", mrec->font_name); - } else { - WARN(">> There are no valid font mapping entry for this font."); - WARN(">> Font file name \"%s\" was assumed but failed to locate that font.", tfm_name); - } - ERROR("Cannot proceed without .vf or \"physical\" font for PDF output..."); - } - loaded_fonts[cur_id].type = PHYSICAL; - loaded_fonts[cur_id].font_id = font_id; - - if (verbose) - MESG(">"); - - return cur_id; -} - -double -dvi_dev_xpos (void) -{ - return dvi_state.h * dvi2pts; -} - -double -dvi_dev_ypos (void) -{ - return -(dvi_state.v * dvi2pts); -} - -static void do_moveto (SIGNED_QUAD x, SIGNED_QUAD y) -{ - dvi_state.h = x; - dvi_state.v = y; -} - -void dvi_right (SIGNED_QUAD x) -{ - switch (dvi_state.d) { - case 0: - dvi_state.h += x; break; - case 1: - dvi_state.v += x; break; - case 3: - dvi_state.v -= x; break; - } -} - -void dvi_down (SIGNED_QUAD y) -{ - switch (dvi_state.d) { - case 0: - dvi_state.v += y; break; - case 1: - dvi_state.h -= y; break; - case 3: - dvi_state.h += y; break; - } -} - -/* Please remove this. - * Optimization for 8-bit encodings. - */ -static void -do_string (unsigned char *s, int len) -{ - struct loaded_font *font; - spt_t width, height, depth; - int i; - - if (current_font < 0) - ERROR("No font selected!"); - - font = &loaded_fonts[current_font]; - - width = tfm_string_width(font->tfm_id, s, len); - width = sqxfw(font->size, width); - - switch (font->type) { - case PHYSICAL: - if (font->subfont_id < 0) { - pdf_dev_set_string(dvi_state.h, -dvi_state.v, s, len, - width, font->font_id, 1); - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_string_height(font->tfm_id, s, len); - depth = tfm_string_depth (font->tfm_id, s, len); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - } else { /* Subfonts */ - dvi_push(); - for (i = 0; i < len; i++) { - dvi_set(s[i]); - } - dvi_pop(); - } - break; - case VIRTUAL: - dvi_push(); - for (i = 0; i < len; i++) { - dvi_set(s[i]); - } - dvi_pop(); - } - switch (dvi_state.d) { - case 0: - dvi_state.h += width; break; - case 1: - dvi_state.v += width; break; - case 3: - dvi_state.v -= width; break; - } -} - -/* _FIXME_ - * CMap decoder wants multibyte strings as input but - * how DVI char codes are converted to multibyte sting - * is not clear. - */ -void -dvi_set (SIGNED_QUAD ch) -{ - struct loaded_font *font; - spt_t width, height, depth; - unsigned char wbuf[4]; - - if (current_font < 0) { - ERROR("No font selected!"); - } - /* The division by dvi2pts seems strange since we actually know the - * "dvi" size of the fonts contained in the DVI file. In other - * words, we converted from DVI units to pts and back again! - * The problem comes from fonts defined in VF files where we don't know - * the DVI size. It's keeping me sane to keep *point sizes* of *all* - * fonts in the dev.c file and convert them back if necessary. - */ - font = &loaded_fonts[current_font]; - - width = tfm_get_fw_width(font->tfm_id, ch); - width = sqxfw(font->size, width); - - switch (font->type) { - case PHYSICAL: - if (ch > 65535) { /* _FIXME_ */ - wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff; - wbuf[1] = UTF32toUTF16HS(ch) & 0xff; - wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff; - wbuf[3] = UTF32toUTF16LS(ch) & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4, - width, font->font_id, 2); - } else if (ch > 255) { /* _FIXME_ */ - wbuf[0] = (ch >> 8) & 0xff; - wbuf[1] = ch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else if (font->subfont_id >= 0) { - unsigned short uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); - wbuf[0] = (uch >> 8) & 0xff; - wbuf[1] = uch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else { - wbuf[0] = (unsigned char) ch; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, - width, font->font_id, 1); - } - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_get_fw_height(font->tfm_id, ch); - depth = tfm_get_fw_depth (font->tfm_id, ch); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - break; - case VIRTUAL: -#if 0 - /* See comment in locate_font() */ - if (font->subfont_id >= 0) - ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); -#endif /* 0 */ - vf_set_char(ch, font->font_id); /* push/pop invoked */ - break; - } - switch (dvi_state.d) { - case 0: - dvi_state.h += width; break; - case 1: - dvi_state.v += width; break; - case 3: - dvi_state.v -= width; break; - } -} - -void -dvi_put (SIGNED_QUAD ch) -{ - struct loaded_font *font; - spt_t width, height, depth; - unsigned char wbuf[4]; - - if (current_font < 0) { - ERROR("No font selected!"); - } - - font = &loaded_fonts[current_font]; - - switch (font->type) { - case PHYSICAL: - width = tfm_get_fw_width(font->tfm_id, ch); - width = sqxfw(font->size, width); - - /* Treat a single character as a one byte string and use the - * string routine. - */ - if (ch > 65535) { /* _FIXME_ */ - wbuf[0] = (UTF32toUTF16HS(ch) >> 8) & 0xff; - wbuf[1] = UTF32toUTF16HS(ch) & 0xff; - wbuf[2] = (UTF32toUTF16LS(ch) >> 8) & 0xff; - wbuf[3] = UTF32toUTF16LS(ch) & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 4, - width, font->font_id, 2); - } else if (ch > 255) { /* _FIXME_ */ - wbuf[0] = (ch >> 8) & 0xff; - wbuf[1] = ch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else if (font->subfont_id >= 0) { - unsigned int uch; - - uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); - wbuf[0] = (uch >> 8) & 0xff; - wbuf[1] = uch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else { - wbuf[0] = (unsigned char) ch; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, - width, font->font_id, 1); - } - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_get_fw_height(font->tfm_id, ch); - depth = tfm_get_fw_depth (font->tfm_id, ch); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - break; - case VIRTUAL: -#if 0 - /* See comment in locate_font() */ - if (font->subfont_id >= 0) - ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); -#endif /* 0 */ - vf_set_char(ch, font->font_id); - break; - } - - return; -} - - -void -dvi_rule (SIGNED_QUAD width, SIGNED_QUAD height) -{ - do_moveto(dvi_state.h, dvi_state.v); - - switch (dvi_state.d) { - case 0: - pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height); - break; - case 1: - pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width); - break; - case 3: - pdf_dev_set_rule(dvi_state.h - height, -dvi_state.v , height, width); - break; - } -} - -void -dvi_dir (UNSIGNED_BYTE dir) /* how? */ -{ - fprintf(stderr, " > dvi_dir %d\n", dir); - dvi_state.d = dir; - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - -static void -do_set1 (void) -{ - dvi_set(get_buffered_unsigned_byte()); -} - -static void -do_set2 (void) -{ - dvi_set(get_buffered_unsigned_pair()); -} - -static void -do_set3 (void) -{ - dvi_set(get_buffered_unsigned_triple()); -} - -static void -do_setrule (void) -{ - SIGNED_QUAD width, height; - - height = get_buffered_signed_quad(); - width = get_buffered_signed_quad(); - if (width > 0 && height > 0) { - dvi_rule(width, height); - } - dvi_right(width); -} - -static void -do_putrule (void) -{ - SIGNED_QUAD width, height; - - height = get_buffered_signed_quad (); - width = get_buffered_signed_quad (); - if (width > 0 && height > 0) { - dvi_rule(width, height); - } -} - -static void -do_put1 (void) -{ - dvi_put(get_buffered_unsigned_byte()); -} - -static void -do_put2 (void) -{ - dvi_put(get_buffered_unsigned_pair()); -} - -static void -do_put3 (void) -{ - dvi_put(get_buffered_unsigned_triple()); -} - -void -dvi_push (void) -{ - if (dvi_stack_depth >= DVI_STACK_DEPTH_MAX) - ERROR("DVI stack exceeded limit."); - - dvi_stack[dvi_stack_depth++] = dvi_state; -} - -void -dvi_pop (void) -{ - if (dvi_stack_depth <= 0) - ERROR ("Tried to pop an empty stack."); - - dvi_state = dvi_stack[--dvi_stack_depth]; - do_moveto(dvi_state.h, dvi_state.v); - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - - -static void -do_right1 (void) -{ - dvi_right(get_buffered_signed_byte()); -} - -static void -do_right2 (void) -{ - dvi_right(get_buffered_signed_pair()); -} - -static void -do_right3 (void) -{ - dvi_right(get_buffered_signed_triple()); -} - -static void -do_right4 (void) -{ - dvi_right(get_buffered_signed_quad()); -} - -void -dvi_w (SIGNED_QUAD ch) -{ - dvi_state.w = ch; - dvi_right(ch); -} - -void -dvi_w0 (void) -{ - dvi_right(dvi_state.w); -} - -static void -do_w1 (void) -{ - dvi_w(get_buffered_signed_byte()); -} - -static void -do_w2 (void) -{ - dvi_w(get_buffered_signed_pair()); -} - -static void -do_w3 (void) -{ - dvi_w(get_buffered_signed_triple()); -} - -static void -do_w4 (void) -{ - dvi_w(get_buffered_signed_quad()); -} - -void -dvi_x (SIGNED_QUAD ch) -{ - dvi_state.x = ch; - dvi_right(ch); -} - -void -dvi_x0 (void) -{ - dvi_right(dvi_state.x); -} - -static void -do_x1 (void) -{ - dvi_x(get_buffered_signed_byte()); -} - -static void -do_x2 (void) -{ - dvi_x(get_buffered_signed_pair()); -} - -static void -do_x3 (void) -{ - dvi_x(get_buffered_signed_triple()); -} - -static void -do_x4 (void) -{ - dvi_x(get_buffered_signed_quad()); -} - -static void -do_down1 (void) -{ - dvi_down(get_buffered_signed_byte()); -} - -static void -do_down2 (void) -{ - dvi_down(get_buffered_signed_pair()); -} - -static void -do_down3 (void) -{ - dvi_down(get_buffered_signed_triple()); -} - -static void -do_down4 (void) -{ - dvi_down(get_buffered_signed_quad()); -} - -void -dvi_y (SIGNED_QUAD ch) -{ - dvi_state.y = ch; - dvi_down(ch); -} - -void -dvi_y0 (void) -{ - dvi_down(dvi_state.y); -} - -static -void do_y1 (void) -{ - dvi_y(get_buffered_signed_byte()); -} - -static -void do_y2 (void) -{ - dvi_y(get_buffered_signed_pair()); -} - -static -void do_y3 (void) -{ - dvi_y(get_buffered_signed_triple()); -} - -static -void do_y4 (void) -{ - dvi_y(get_buffered_signed_quad()); -} - -void -dvi_z (SIGNED_QUAD ch) -{ - dvi_state.z = ch; - dvi_down(ch); -} - -void -dvi_z0 (void) -{ - dvi_down(dvi_state.z); -} - -static void -do_z1 (void) -{ - dvi_z(get_buffered_signed_byte()); -} - -static void -do_z2 (void) -{ - dvi_z(get_buffered_signed_pair()); -} - -static void -do_z3 (void) -{ - dvi_z(get_buffered_signed_triple()); -} - -static void -do_z4 (void) -{ - dvi_z(get_buffered_signed_quad()); -} - -static void -do_fntdef (void) -{ - int area_len, name_len, i; - - get_signed_quad(dvi_file); - get_signed_quad(dvi_file); - get_signed_quad(dvi_file); - area_len = get_unsigned_byte(dvi_file); - name_len = get_unsigned_byte(dvi_file); - for (i = 0; i < area_len + name_len; i++) { - get_unsigned_byte(dvi_file); - } -} - -static void -do_fntdef1 (void) -{ - get_unsigned_byte(dvi_file); - do_fntdef(); -} - -static void -do_fntdef2 (void) -{ - get_unsigned_pair(dvi_file); - do_fntdef(); -} - -static void -do_fntdef3 (void) -{ - get_unsigned_triple(dvi_file); - do_fntdef(); -} - -static void -do_fntdef4 (void) -{ - get_signed_quad(dvi_file); - do_fntdef(); -} - -void -dvi_set_font (int font_id) -{ - current_font = font_id; -} - -static void -do_fnt (SIGNED_QUAD tex_id) -{ - int i; - - for (i = 0; i < num_def_fonts; i++) { - if (def_fonts[i].tex_id == tex_id) - break; - } - - if (i == num_def_fonts) { - ERROR("Tried to select a font that hasn't been defined: id=%ld", tex_id); - } - - if (!def_fonts[i].used) { - int font_id; - - font_id = dvi_locate_font(def_fonts[i].font_name, def_fonts[i].point_size); - loaded_fonts[font_id].source = DVI; - def_fonts[i].used = 1; - def_fonts[i].font_id = font_id; - } - current_font = def_fonts[i].font_id; -} - -static void -do_fnt1 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_byte(); - do_fnt(tex_id); -} - -static void -do_fnt2 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_pair(); - do_fnt(tex_id); -} - -static void -do_fnt3 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_triple(); - do_fnt(tex_id); -} - -static void -do_fnt4 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_signed_quad(); - do_fnt(tex_id); -} - -static void -do_xxx (UNSIGNED_QUAD size) -{ -#ifdef XETEX - dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size); - dvi_page_buf_index += size; -#else - UNSIGNED_QUAD i; - Ubyte *buffer; - - buffer = NEW(size+1, Ubyte); - for (i = 0; i < size; i++) { - buffer[i] = get_buffered_unsigned_byte(); - } - dvi_do_special(buffer, size); - RELEASE(buffer); -#endif -} - -static void -do_xxx1 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_byte(); - do_xxx(size); -} - -static void -do_xxx2 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_pair(); - do_xxx(size); -} - -static void -do_xxx3 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_triple(); - do_xxx(size); -} - -static void -do_xxx4 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_quad(); - do_xxx(size); -} - -static void -do_bop (void) -{ - int i; - - if (processing_page) - ERROR("Got a bop in the middle of a page!"); - - /* For now, ignore TeX's count registers */ - for (i = 0; i < 10; i++) { - get_buffered_signed_quad(); - } - /* Ignore previous page pointer since we have already - * saved this information - */ - get_buffered_signed_quad(); - clear_state(); - processing_page = 1; - - pdf_doc_begin_page(dvi_tell_mag(), dev_origin_x, dev_origin_y); - spc_exec_at_begin_page(); - - return; -} - -static void -do_eop (void) -{ - processing_page = 0; - - if (dvi_stack_depth != 0) { - ERROR("DVI stack depth is not zero at end of page"); - } - spc_exec_at_end_page(); - - pdf_doc_end_page(); - - return; -} - -static void -do_dir (void) -{ - dvi_state.d = get_unsigned_byte(dvi_file); - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - -#ifdef XETEX -static void -do_native_font_def (int scanning) -{ - if (scanning) { - SIGNED_QUAD tex_id = get_signed_quad(dvi_file); - if (linear) { - read_native_font_record(tex_id); - } else { - UNSIGNED_PAIR flags; - int name_length, nvars, i; - - get_unsigned_quad(dvi_file); /* skip point size */ - flags = get_unsigned_pair(dvi_file); - name_length = (int) get_unsigned_byte(dvi_file); - name_length += (int) get_unsigned_byte(dvi_file); - name_length += (int) get_unsigned_byte(dvi_file); - for (i = 0; i < name_length; ++i) - get_unsigned_byte(dvi_file); - if (flags & XDV_FLAG_COLORED) { - get_unsigned_quad(dvi_file); - } - if (flags & XDV_FLAG_VARIATIONS) { - nvars = get_unsigned_pair(dvi_file); - for (i = 0; i < nvars * 2; ++i) - get_unsigned_quad(dvi_file); /* skip axis and value for each variation setting */ - } - } - --dvi_page_buf_index; /* don't buffer the opcode */ - } -} - -static void -do_glyph_array (int yLocsPresent) -{ - struct loaded_font *font; - spt_t width, height, depth, *xloc, *yloc, glyph_width = 0; - unsigned char wbuf[2]; - unsigned int i, glyph_id, slen = 0; - - if (current_font < 0) - ERROR("No font selected!"); - - font = &loaded_fonts[current_font]; - - width = get_buffered_signed_quad(); - - slen = (unsigned int) get_buffered_unsigned_pair(); - xloc = NEW(slen, spt_t); - yloc = NEW(slen, spt_t); - for (i = 0; i < slen; i++) { - xloc[i] = get_buffered_signed_quad(); - yloc[i] = yLocsPresent ? get_buffered_signed_quad() : 0; - } - - if (font->rgba_color != 0xffffffff) { - pdf_color color; - 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_color_push(&color, &color); - } - - for (i = 0; i < slen; i++) { - glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */ - if (glyph_id < font->ft_face->num_glyphs) { - FT_Error error; - FT_Fixed advance; - int flags = FT_LOAD_NO_SCALE; - - if (font->layout_dir == 1) - flags |= FT_LOAD_VERTICAL_LAYOUT; - - error = FT_Get_Advance(font->ft_face, glyph_id, flags, &advance); - if (error) - advance = 0; - - glyph_width = (double)font->size * (double)advance / (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; - depth = (double)font->size * -(double)font->ft_face->descender / (double)font->ft_face->units_per_EM; - pdf_dev_set_rect(&rect, dvi_state.h + xloc[i], -dvi_state.v - yloc[i], glyph_width, height, depth); - pdf_doc_expand_box(&rect); - } - } - - wbuf[0] = glyph_id >> 8; - wbuf[1] = glyph_id & 0xff; - pdf_dev_set_string(dvi_state.h + xloc[i], -dvi_state.v - yloc[i], wbuf, 2, - glyph_width, font->font_id, -1); - } - - if (font->rgba_color != 0xffffffff) { - pdf_color_pop(); - } - RELEASE(xloc); - RELEASE(yloc); - - if (!dvi_state.d) { - dvi_state.h += width; - } else { - dvi_state.v += width; - } - - return; -} - -static void -do_pic_file(void) - /* parameters for XDV_PIC_FILE opcode: pdf_box[1] t[4][6] p[2] len[2] path[l] */ -{ - int page_no; - UNSIGNED_PAIR len; - char *path; - int i; - int xobj_id; - transform_info ti; - - transform_info_clear(&ti); - - /* pdf_box = */ get_buffered_unsigned_byte(); - - ti.matrix.a = get_buffered_signed_quad() / 65536.0; /* convert 16.16 Fixed to floating-point */ - ti.matrix.b = get_buffered_signed_quad() / 65536.0; - ti.matrix.c = get_buffered_signed_quad() / 65536.0; - ti.matrix.d = get_buffered_signed_quad() / 65536.0; - ti.matrix.e = get_buffered_signed_quad() / 65536.0; - ti.matrix.f = get_buffered_signed_quad() / 65536.0; - - page_no = get_buffered_signed_pair(); - len = get_buffered_unsigned_pair(); - path = NEW(len + 1, char); - for (i = 0; i < len; ++i) - path[i] = get_buffered_unsigned_byte(); - path[len] = 0; - - /* - now we need to place page /page_no/ of the graphic file from /path/, applying /transform/ - if pdf_box=0 the file is a raster image (.jpg, .png, .tif, etc; need to determine format - by examining the file) - else it is a PDF document, pdf_box tells which PDF box (media, trim, crop, etc) to use - page_no is currently only used with PDF documents, though in theory could be used - with multi-page TIFFs, etc - transform is a 3x2 affine transform matrix expressed in fixed-point values - */ - - xobj_id = pdf_ximage_findresource(path, page_no, NULL); - 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, - not just assume the "original" size is 100dpi - */ - pdf_dev_put_image(xobj_id, &ti, dvi_dev_xpos(), dvi_dev_ypos()); - } - - RELEASE(path); -} -#endif - -/* Note to be absolutely certain that the string escape buffer doesn't - * hit its limit, FORMAT_BUF_SIZE should set to 4 times S_BUFFER_SIZE - * in pdfobj.c. Is there any application that genenerate words with - * 1k characters? - */ - -#define SBUF_SIZE 1024 - -/* Most of the work of actually interpreting - * the dvi file is here. - */ -void -dvi_do_page (long n, - double paper_width, double paper_height, - double hmargin, double vmargin) -{ - unsigned char opcode; - unsigned char sbuf[SBUF_SIZE]; - unsigned int slen = 0; - - if (!page_loc || n >= num_pages) - ERROR("Tried to process non-existent page: %ld", n); - - /* DVI coordinate */ - dev_origin_x = hmargin; - dev_origin_y = paper_height - vmargin; - - seek_absolute(dvi_file, page_loc[n]); - - dvi_stack_depth = 0; - for (;;) { - /* The most likely opcodes are individual setchars. - * These are buffered for speed. */ - slen = 0; - while ((opcode = get_buffered_unsigned_byte()) <= SET_CHAR_127 && - slen < SBUF_SIZE) { - sbuf[slen++] = opcode; - } - if (slen > 0) { - do_string(sbuf, slen); - } - if (slen == SBUF_SIZE) - continue; - - /* If we are here, we have an opcode that is something - * other than SET_CHAR. - */ - if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) { - do_fnt(opcode - FNT_NUM_0); - continue; - } - - switch (opcode) { - case SET1: do_set1(); break; - case SET2: do_set2(); break; - case SET3: do_set3(); break; - case SET4: - ERROR("Multibyte (>24 bits) character not supported!"); - break; - - case SET_RULE: - do_setrule(); - break; - - case PUT1: do_put1(); break; - case PUT2: do_put2(); break; - case PUT3: do_put3(); break; - case PUT4: - ERROR ("Multibyte character (>24 bits) not supported!"); - break; - - case PUT_RULE: - do_putrule(); - break; - - case NOP: - break; - - case BOP: - do_bop(); - break; - case EOP: - do_eop(); - return; - break; - - case PUSH: - dvi_push(); - /* The following line needs to go here instead of in - * dvi_push() since logical structure of document is - * oblivous to virtual fonts. For example the last line on a - * page could be at stack level 3 and the page footer should - * be at stack level 3. However, if the page footer contains - * virtual fonts (or other nested constructions), it could - * fool the link breaker into thinking it was a continuation - * of the link */ - dvi_mark_depth(); - break; - case POP: - dvi_pop(); - /* Above explanation holds for following line too */ - dvi_mark_depth(); - break; - - case RIGHT1: do_right1(); break; - case RIGHT2: do_right2(); break; - case RIGHT3: do_right3(); break; - case RIGHT4: do_right4(); break; - - case W0: dvi_w0(); break; - case W1: do_w1 (); break; - case W2: do_w2 (); break; - case W3: do_w3 (); break; - case W4: do_w4 (); break; - - case X0: dvi_x0(); break; - case X1: do_x1 (); break; - case X2: do_x2 (); break; - case X3: do_x3 (); break; - case X4: do_x4 (); break; - - case DOWN1: do_down1(); break; - case DOWN2: do_down2(); break; - case DOWN3: do_down3(); break; - case DOWN4: do_down4(); break; - - case Y0: dvi_y0(); break; - case Y1: do_y1 (); break; - case Y2: do_y2 (); break; - case Y3: do_y3 (); break; - case Y4: do_y4 (); break; - - case Z0: dvi_z0(); break; - case Z1: do_z1 (); break; - case Z2: do_z2 (); break; - case Z3: do_z3 (); break; - case Z4: do_z4 (); break; - - case FNT1: do_fnt1(); break; - case FNT2: do_fnt2(); break; - case FNT3: do_fnt3(); break; - case FNT4: do_fnt4(); break; - - /* Specials */ - case XXX1: do_xxx1(); break; - case XXX2: do_xxx2(); break; - case XXX3: do_xxx3(); break; - case XXX4: do_xxx4(); break; - - /* Font definition - skipped. */ - case FNT_DEF1: do_fntdef1(); break; - case FNT_DEF2: do_fntdef2(); break; - case FNT_DEF3: do_fntdef3(); break; - case FNT_DEF4: do_fntdef4(); break; - - /* pTeX extension */ - case PTEXDIR: - do_dir(); - break; - -#ifdef XETEX - /* XeTeX extension */ - case XDV_GLYPH_STRING: - do_glyph_array(0); - break; - case XDV_GLYPH_ARRAY: - do_glyph_array(1); - break; - case XDV_NATIVE_FONT_DEF: - do_native_font_def(0); /* should not occur - processed during pre-scanning */ - break; - case XDV_PIC_FILE: - do_pic_file(); - break; -#endif - - case POST: -#ifdef XETEX - if (linear && !processing_page) { - /* for linear processing, this means there are no more pages */ - num_pages = 0; /* force loop to terminate */ - return; - } - /* else fall through to error case */ -#endif - ERROR("Unexpected preamble or postamble in dvi file"); - break; - default: - ERROR("Unexpected opcode or DVI file ended prematurely"); - } - } -} - -double -dvi_init (char *dvi_filename, double mag) -{ - long post_location; - - dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); - if (!dvi_file) { - ERROR("Could not open specified DVI file: %s", dvi_filename); - return 0.0; - } - - /* DVI files are most easily read backwards by - * searching for post_post and then post opcode. - */ - post_location = find_post(); - get_dvi_info(post_location); - do_scales(mag); - get_page_info(post_location); - get_comment(); - get_dvi_fonts(post_location); - clear_state(); - - return dvi2pts; -} - -void -dvi_close (void) -{ - int i; - - /* We add comment in dvi_close instead of dvi_init so user - * has a change to overwrite it. The docinfo dictionary is - * treated as a write-once record. - */ - - /* Do some house cleaning */ - MFCLOSE(dvi_file); - dvi_file = NULL; - - if (def_fonts) { - for (i = 0; i < num_def_fonts; i++) { - if (def_fonts[i].font_name) - RELEASE(def_fonts[i].font_name); - def_fonts[i].font_name = NULL; - } - RELEASE(def_fonts); - } - def_fonts = NULL; - - if (page_loc) - RELEASE(page_loc); - page_loc = NULL; - num_pages = 0; - - if (loaded_fonts) - RELEASE(loaded_fonts); - loaded_fonts = NULL; - num_loaded_fonts = 0; - - vf_close_all_fonts(); - tfm_close_all (); -} - -/* The following are need to implement virtual fonts - According to documentation, the vf "subroutine" - must have state pushed and must have - w,v,y, and z set to zero. The current font - is determined by the virtual font header, which - may be undefined */ - -static int saved_dvi_font[VF_NESTING_MAX]; -static int num_saved_fonts = 0; - -void -dvi_vf_init (int dev_font_id) -{ - dvi_push(); - - dvi_state.w = 0; dvi_state.x = 0; - dvi_state.y = 0; dvi_state.z = 0; - - /* do not reset dvi_state.d. */ - if (num_saved_fonts < VF_NESTING_MAX) { - saved_dvi_font[num_saved_fonts++] = current_font; - } else - ERROR("Virtual fonts nested too deeply!"); - current_font = dev_font_id; -} - -/* After VF subroutine is finished, we simply pop the DVI stack */ -void -dvi_vf_finish (void) -{ - dvi_pop(); - if (num_saved_fonts > 0) - current_font = saved_dvi_font[--num_saved_fonts]; - else { - ERROR("Tried to pop an empty font stack"); - } -} - - -/* Scan various specials */ -#include "dpxutil.h" - -/* This need to allow 'true' prefix for unit and - * length value must be divided by current magnification. - */ -static int -read_length (double *vp, double mag, const char **pp, const char *endptr) -{ - char *q; - const char *p = *pp; - double v, u = 1.0; - const char *_ukeys[] = { -#define K_UNIT__PT 0 -#define K_UNIT__IN 1 -#define K_UNIT__CM 2 -#define K_UNIT__MM 3 -#define K_UNIT__BP 4 - "pt", "in", "cm", "mm", "bp", - NULL - }; - int k, error = 0; - - q = parse_float_decimal(&p, endptr); - if (!q) { - *vp = 0.0; *pp = p; - return -1; - } - - v = atof(q); - RELEASE(q); - - q = parse_c_ident(&p, endptr); - if (q) { - char *qq = q; - 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", qq); - error = -1; - break; - } - RELEASE(qq); - } - - *vp = v * u; *pp = p; - return error; -} - - -static int -scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, - unsigned *minorversion, - int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw, - const char *buf, UNSIGNED_QUAD size) -{ - char *q; - const char *p = buf, *endptr; - int ns_pdf = 0, error = 0; - - endptr = p + size; - - skip_white(&p, endptr); - - q = parse_c_ident(&p, endptr); - if (q && !strcmp(q, "pdf")) { - skip_white(&p, endptr); - if (p < endptr && *p == ':') { - p++; - skip_white(&p, endptr); - RELEASE(q); - q = parse_c_ident(&p, endptr); ns_pdf = 1; - } - } - skip_white(&p, endptr); - - if (q) { - if (!strcmp(q, "landscape")) { - *lm = 1; - } else if (ns_pdf && !strcmp(q, "pagesize")) { - while (!error && p < endptr) { - char *kp = parse_c_ident(&p, endptr); - if (!kp) - break; - else { - skip_white(&p, endptr); - if (!strcmp(kp, "width")) { - error = read_length(wd, dvi_tell_mag(), &p, endptr); - if (!error) - *wd *= dvi_tell_mag(); - } else if (!strcmp(kp, "height")) { - error = read_length(ht, dvi_tell_mag(), &p, endptr); - if (!error) - *ht *= dvi_tell_mag(); - } else if (!strcmp(kp, "xoffset")) { - error = read_length(xo, dvi_tell_mag(), &p, endptr); - if (!error) - *xo *= dvi_tell_mag(); - } else if (!strcmp(kp, "yoffset")) { - error = read_length(yo, dvi_tell_mag(), &p, endptr); - if (!error) - *yo *= dvi_tell_mag(); - } - RELEASE(kp); - } - skip_white(&p, endptr); - } - } else if (!strcmp(q, "papersize")) { - char qchr = 0; - if (*p == '=') p++; - skip_white(&p, endptr); - if (p < endptr && (*p == '\'' || *p == '\"')) { - qchr = *p; p++; - skip_white(&p, endptr); - } - error = read_length(wd, 1.0, &p, endptr); - if (!error) { - skip_white(&p, endptr); - if (p < endptr && *p == ',') { - p++; skip_white(&p, endptr); - } - error = read_length(ht, 1.0, &p, endptr); - skip_white(&p, endptr); - } - if (!error && qchr) { /* Check if properly quoted */ - if (p >= endptr || *p != qchr) - error = -1; - } - } else if (minorversion && ns_pdf && !strcmp(q, "minorversion")) { - char *kv; - if (*p == '=') p++; - skip_white(&p, endptr); - kv = parse_float_decimal(&p, endptr); - if (kv) { - *minorversion = (unsigned)strtol(kv, NULL, 10); - RELEASE(kv); - } - } else if (ns_pdf && !strcmp(q, "encrypt") && do_enc) { - *do_enc = 1; - *owner_pw = *user_pw = 0; - while (!error && p < endptr) { - char *kp = parse_c_ident(&p, endptr); - if (!kp) - break; - else { - pdf_obj *obj; - skip_white(&p, endptr); - if (!strcmp(kp, "ownerpw")) { - if ((obj = parse_pdf_string(&p, endptr))) { - strncpy(owner_pw, pdf_string_value(obj), MAX_PWD_LEN); - pdf_release_obj(obj); - } else - error = -1; - } else if (!strcmp(kp, "userpw")) { - if ((obj = parse_pdf_string(&p, endptr))) { - strncpy(user_pw, pdf_string_value(obj), MAX_PWD_LEN); - pdf_release_obj(obj); - } else - error = -1; - } else if (!strcmp(kp, "length")) { - if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { - *key_bits = (unsigned) pdf_number_value(obj); - } else - error = -1; - if (obj) - pdf_release_obj(obj); - } else if (!strcmp(kp, "perm")) { - if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { - *permission = (unsigned) pdf_number_value(obj); - } else - error = -1; - if (obj) - pdf_release_obj(obj); - } else - error = -1; - RELEASE(kp); - } - skip_white(&p, endptr); - } - } - RELEASE(q); - } - - return error; -} - - -void -dvi_scan_specials (long page_no, - double *page_width, double *page_height, - double *x_offset, double *y_offset, char *landscape, - unsigned *minorversion, - int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw) -{ - FILE *fp = dvi_file; - long offset; - unsigned char opcode; - - if (page_no >= num_pages) - ERROR("Invalid page number: %u", page_no); - offset = page_loc[page_no]; - - seek_absolute(fp, offset); - while ((opcode = fgetc(fp)) != EOP) { - - if (opcode <= SET_CHAR_127 || - (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63)) - continue; - else if (opcode == XXX1 || opcode == XXX2 || - opcode == XXX3 || opcode == XXX4) { - UNSIGNED_QUAD size = 0UL; - char buf[1024]; - switch (opcode) { - case XXX1: size = get_and_buffer_unsigned_byte(fp); break; - case XXX2: size = get_and_buffer_unsigned_pair(fp); break; - case XXX3: size = get_and_buffer_unsigned_triple(fp); break; - case XXX4: size = get_and_buffer_unsigned_quad(fp); break; - } - size = MIN(size, 1024); - if (fread(buf, sizeof(char), size, fp) != size) - ERROR("Reading DVI file failed!"); - if (scan_special(page_width, page_height, x_offset, y_offset, landscape, - minorversion, do_enc, key_bits, permission, owner_pw, user_pw, buf, size)) - WARN("Reading special command failed: \"%.*s\"", size, buf); - continue; - } - - /* Skipping... */ - switch (opcode) { - case BOP: - get_and_buffer_bytes(fp, 44); - break; - case NOP: case PUSH: case POP: - case W0: case X0: case Y0: case Z0: - break; - case SET1: case PUT1: case RIGHT1: case DOWN1: - case W1: case X1: case Y1: case Z1: case FNT1: - get_and_buffer_unsigned_byte(fp); - break; - - case SET2: case PUT2: case RIGHT2: case DOWN2: - case W2: case X2: case Y2: case Z2: case FNT2: - get_and_buffer_signed_pair(fp); - break; - - case SET3: case PUT3: case RIGHT3: case DOWN3: - case W3: case X3: case Y3: case Z3: case FNT3: - get_and_buffer_signed_triple(fp); - break; - - case SET4: case PUT4: case RIGHT4: case DOWN4: - case W4: case X4: case Y4: case Z4: case FNT4: - get_and_buffer_signed_quad(fp); - break; - - case SET_RULE: case PUT_RULE: - get_and_buffer_bytes(fp, 8); - break; - - case FNT_DEF1: do_fntdef1(); break; - case FNT_DEF2: do_fntdef2(); break; - case FNT_DEF3: do_fntdef3(); break; - case FNT_DEF4: do_fntdef4(); break; - -#ifdef XETEX - case XDV_GLYPH_STRING: - { - UNSIGNED_PAIR count; - get_and_buffer_unsigned_quad(fp); /* width */ - count = get_and_buffer_unsigned_pair(fp); /* glyph count */ - get_and_buffer_bytes(fp, count * 6); /* 2 bytes ID + 4 bytes x-location per glyph */ - } - break; - case XDV_GLYPH_ARRAY: - { - UNSIGNED_PAIR count; - get_and_buffer_unsigned_quad(fp); /* width */ - count = get_and_buffer_unsigned_pair(fp); /* glyph count */ - get_and_buffer_bytes(fp, count * 10); /* 2 bytes ID + 8 bytes x,y-location per glyph */ - } - break; - case XDV_NATIVE_FONT_DEF: - do_native_font_def(1); - break; - case XDV_PIC_FILE: - /* params: flags[1] t[4][6] p[2] len[2] path[l] */ - { - UNSIGNED_PAIR len; - get_and_buffer_bytes(fp, 1 + 4 * 6 + 2); - len = get_and_buffer_unsigned_pair(fp); /* length of pathname */ - get_and_buffer_bytes(fp, len); - } - break; -#endif - - case PTEXDIR: - get_and_buffer_unsigned_byte(fp); - break; - - case POST: -#ifdef XETEX - if (linear && dvi_page_buf_index == 1) { - /* this is actually an indication that we've reached the end of the input */ - return; - } - /* else fall through to error case */ -#endif - default: /* case PRE: case POST_POST: and others */ - ERROR("Unexpected opcode %d at pos=0x%x", opcode, tell_position(fp)); - break; - } - } - - return; -} - diff --git a/Build/source/texk/dvipdfm-x/src/dvipdfmx.c b/Build/source/texk/dvipdfm-x/src/dvipdfmx.c deleted file mode 100644 index 85deb9fa32f..00000000000 --- a/Build/source/texk/dvipdfm-x/src/dvipdfmx.c +++ /dev/null @@ -1,1043 +0,0 @@ -/* - - This is DVIPDFMx, an eXtended version of DVIPDFM by Mark A. Wicks. - - Copyright (C) 2002-2013 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "system.h" -#include "mem.h" - -#include "dpxconf.h" -#include "dpxfile.h" -#include "dpxutil.h" - -#include "dvi.h" - -#include "pdflimits.h" -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfparse.h" -#include "pdfencrypt.h" - -#include "spc_tpic.h" -#include "specials.h" - -#include "mpost.h" - -#include "fontmap.h" -#include "pdffont.h" -#include "pdfximage.h" -#include "cid.h" - -#include "dvipdfmx.h" - -#include "error.h" - -#ifdef XETEX -#include "tt_aux.h" -#endif - -int compat_mode = 0; /* 0 = dvipdfmx, 1 = dvipdfm */ - -static int verbose = 0; - -static int mp_mode = 0; - -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_PDFDOC_NO_DEST_REMOVE (1 << 4) - -static char ignore_colors = 0; -static double annot_grow = 0.0; -static int bookmark_open = 0; -static double mag = 1.0; -static int font_dpi = 600; -static int really_quiet = 0; -/* - * Precision is essentially limited to 0.01pt. - * See, dev_set_string() in pdfdev.c. - */ -static int pdfdecimaldigits = 2; - -/* Image cache life in hours */ -/* 0 means erase all old images and leave new images */ -/* -1 means erase all old images and also erase new images */ -/* -2 means ignore image cache (default) */ -static int image_cache_life = -2; - -/* Encryption */ -static int do_encryption = 0; -static unsigned key_bits = 40; -static unsigned permission = 0x003C; - -/* Page device */ -static double paper_width = 595.0; -static double paper_height = 842.0; -static double x_offset = 72.0; -static double y_offset = 72.0; -static char landscape_mode = 0; - - -char *dvi_filename = NULL, *pdf_filename = NULL; - -static void -read_config_file (const char *config); - -static void -set_default_pdf_filename(void) -{ - const char *dvi_base; - - dvi_base = xbasename(dvi_filename); - if (mp_mode && - strlen(dvi_base) > 4 && - FILESTRCASEEQ(".mps", dvi_base + strlen(dvi_base) - 4)) { - pdf_filename = NEW(strlen(dvi_base)+1, char); - strncpy(pdf_filename, dvi_base, strlen(dvi_base) - 4); - pdf_filename[strlen(dvi_base)-4] = '\0'; - } else if (strlen(dvi_base) > 4 && - (FILESTRCASEEQ(".dvi", dvi_base+strlen(dvi_base)-4) -#ifdef XETEX - || FILESTRCASEEQ(".xdv", dvi_base+strlen(dvi_base)-4) -#endif - )) { - pdf_filename = NEW(strlen(dvi_base)+1, char); - strncpy(pdf_filename, dvi_base, strlen(dvi_base)-4); - pdf_filename[strlen(dvi_base)-4] = '\0'; - } else { - pdf_filename = NEW(strlen(dvi_base)+5, char); - strcpy(pdf_filename, dvi_base); - } - - strcat (pdf_filename, ".pdf"); -} - -static void -show_version (void) -{ - fprintf (stdout, "\nThis is dvipdfmx-%s by the DVIPDFMx project team,\n", VERSION); - fprintf (stdout, "modified for TeX Live,\n"); - fprintf (stdout, "an extended version of dvipdfm-0.13.2c developed by Mark A. Wicks.\n"); - fprintf (stdout, "\nCopyright (C) 2002-2013 by the DVIPDFMx project team\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"); - fprintf (stdout, "(at your option) any later version.\n"); -} - -static void -show_usage (void) -{ - fprintf (stdout, "\nUsage: dvipdfmx [options] dvifile\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, "-f filename\tSet font map file name [cid-x.map]\n"); - fprintf (stdout, "-g dimension\tAnnotation \"grow\" amount [0.0in]\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"); - fprintf (stdout, "-t \t\tEmbed thumbnail images of PNG format [dvifile.1] \n"); - 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 \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\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 optimize PDF destinations.\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, "-D template\tPS->PDF conversion command line template [none]\n"); - fprintf (stdout, "-E \t\tEnable DVIPDFM emulation mode\n"); - fprintf (stdout, "-I number\tImage cache life in hours [-2]\n"); - fprintf (stdout, " \t 0: erase all old images and leave new images\n"); - fprintf (stdout, " \t-1: erase all old images and also erase new images\n"); - fprintf (stdout, " \t-2: ignore image cache\n"); - fprintf (stdout, "-K number\tEncryption key length [40]\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 \t\tEnable PDF encryption\n"); - 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"); -} - -static void -usage (void) -{ - if (really_quiet) - return; - fprintf(stdout, "\nTry \"dvipdfmx --help\" for more information.\n"); - exit(1); -} - - -static int -read_length (double *vp, const char **pp, const char *endptr) -{ - char *q; - const char *p = *pp; - double v, u = 1.0; - const char *_ukeys[] = { -#define K_UNIT__PT 0 -#define K_UNIT__IN 1 -#define K_UNIT__CM 2 -#define K_UNIT__MM 3 -#define K_UNIT__BP 4 - "pt", "in", "cm", "mm", "bp", - NULL - }; - int k, error = 0; - - q = parse_float_decimal(&p, endptr); - if (!q) { - *vp = 0.0; *pp = p; - return -1; - } - - v = atof(q); - RELEASE(q); - - q = parse_c_ident(&p, endptr); - if (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); - error = -1; - break; - } - RELEASE(q); - } - - *vp = v * u; *pp = p; - return error; -} - -static void -select_paper (const char *paperspec) -{ - const struct paper *pi; - int error = 0; - - pi = paperinfo(paperspec); - if (pi && papername(pi)) { - paper_width = paperpswidth (pi); - paper_height = paperpsheight(pi); - } else { - const char *p = paperspec, *endptr, *comma; - comma = strchr(p, ','); - endptr = p + strlen(p); - if (!comma) - ERROR("Unrecognized paper format: %s", paperspec); - error = read_length(&paper_width, &p, comma); - p = comma + 1; - error = read_length(&paper_height, &p, endptr); - } - if (error || paper_width <= 0.0 || paper_height <= 0.0) - ERROR("Invalid paper size: %s (%.2fx%.2f)", paperspec, paper_width, paper_height); -} - -struct page_range -{ - long first, last; -} *page_ranges = NULL; - -int num_page_ranges = 0; -int max_page_ranges = 0; - -static void -select_pages (const char *pagespec) -{ - char *q; - const char *p = pagespec; - - while (*p != '\0') { - /* Enlarge page range table if necessary */ - if (num_page_ranges >= max_page_ranges) { - max_page_ranges += 4; - page_ranges = RENEW(page_ranges, max_page_ranges, struct page_range); - } - - page_ranges[num_page_ranges].first = 0; - page_ranges[num_page_ranges].last = 0; - - for ( ; *p && isspace(*p); p++); - q = parse_unsigned(&p, p + strlen(p)); /* Can't be signed. */ - if (q) { /* '-' is allowed here */ - page_ranges[num_page_ranges].first = atoi(q) - 1; - page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; - RELEASE(q); - } - for ( ; *p && isspace(*p); p++); - - if (*p == '-') { - for (++p; *p && isspace(*p); p++); - page_ranges[num_page_ranges].last = -1; - if (*p) { - q = parse_unsigned(&p, p + strlen(p)); - if (q) { - page_ranges[num_page_ranges].last = atoi(q) - 1; - RELEASE(q); - } - for ( ; *p && isspace(*p); p++); - } - } else { - page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; - } - - num_page_ranges++; - - if (*p == ',') - p++; - else { - for ( ; *p && isspace(*p); p++); - if (*p) - ERROR("Bad page range specification: %s", p); - } - } - return; -} - -#define POP_ARG() {argv += 1; argc -= 1;} -/* It doesn't work as expected (due to dvi filename). */ -#define CHECK_ARG(n,m) if (argc < (n) + 1) {\ - if (!really_quiet)\ - fprintf(stderr, "\nMissing %s after \"-%c\".\n", (m), *flag);\ - usage();\ -} - -static void -set_verbose (int argc, char *argv[]) -{ - while (argc > 0) { - if(*argv[0] == '-') { - char *flag; - - for (flag = argv[0] + 1; *flag != 0; flag++) { - if (*flag == '-') - break; - if (*flag == 'q') - really_quiet = 1; - if (*flag == 'v') - verbose++; - } - } - POP_ARG(); - } - - if (!really_quiet) { - int i; - - for (i = 0; i < verbose; i++) { - dvi_set_verbose(); - pdf_dev_set_verbose(); - pdf_doc_set_verbose(); - pdf_enc_set_verbose(); - pdf_obj_set_verbose(); - pdf_fontmap_set_verbose(); - dpx_file_set_verbose(); - } - } -} - - -static void -do_args (int argc, char *argv[]) -{ - while (argc > 0 && *argv[0] == '-') { - char *flag, *nextptr; - const char *nnextptr; - - for (flag = argv[0] + 1; *flag != 0; flag++) { - switch (*flag) { - case '-': - if (++flag) { - if (!strcmp(flag, "help")) { - show_version(); - show_usage(); - exit(0); - } else if (!strcmp(flag, "version")) { - show_version(); - exit(0); - } - } - if (!really_quiet) - fprintf(stderr, "Unknown option in \"--%s\"", flag); - usage(); - break; - case 'D': - CHECK_ARG(1, "PS->PDF conversion command line template"); - set_distiller_template(argv[1]); - POP_ARG(); - break; - case 'r': - CHECK_ARG(1, "bitmap font dpi"); - font_dpi = atoi(argv[1]); - if (font_dpi <= 0) - ERROR("Invalid bitmap font dpi specified: %s", argv[1]); - POP_ARG(); - break; - case 'm': - CHECK_ARG(1, "magnification value"); - mag = strtod(argv[1], &nextptr); - if (mag < 0.0 || nextptr == argv[1]) - ERROR("Invalid magnification specifiied: %s", argv[1]); - POP_ARG(); - break; - case 'g': - CHECK_ARG(1, "annotation \"grow\" amount"); - nnextptr = nextptr = argv[1]; - read_length(&annot_grow, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'x': - CHECK_ARG(1, "horizontal offset value"); - nnextptr = nextptr = argv[1]; - read_length(&x_offset, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'y': - CHECK_ARG(1, "vertical offset value"); - nnextptr = nextptr = argv[1]; - read_length(&y_offset, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'o': - CHECK_ARG(1, "output file name"); - pdf_filename = NEW (strlen(argv[1])+1,char); - strcpy(pdf_filename, argv[1]); - POP_ARG(); - break; - case 's': - CHECK_ARG(1, "page selection specification"); - select_pages(argv[1]); - POP_ARG(); - break; - case 't': - pdf_doc_enable_manual_thumbnails(); - break; - case 'p': - CHECK_ARG(1, "paper format/size"); - select_paper(argv[1]); - POP_ARG(); - break; - case 'c': - ignore_colors = 1; - break; - case 'l': - landscape_mode = 1; - break; - case 'f': - CHECK_ARG(1, "fontmap file name"); - if (opt_flags & OPT_FONTMAP_FIRST_MATCH) - pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_APPEND); - else - pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_REPLACE); - POP_ARG(); - break; - case 'q': case 'v': - break; - case 'V': - { - int ver_minor; - - if (isdigit(*(flag+1))) { - flag++; - ver_minor = atoi(flag); - } else { - CHECK_ARG(1, "PDF minor version number"); - ver_minor = atoi(argv[1]); - POP_ARG(); - } - if (ver_minor < PDF_VERSION_MIN) { - WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", - ver_minor, PDF_VERSION_MIN); - ver_minor = PDF_VERSION_MIN; - } else if (ver_minor > PDF_VERSION_MAX) { - WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", - ver_minor, PDF_VERSION_MAX); - ver_minor = PDF_VERSION_MAX; - } - pdf_set_version((unsigned) ver_minor); - } - break; - case 'z': - { - int level; - - if (isdigit(*(flag+1))) { - flag++; - level = atoi(flag); - } else { - CHECK_ARG(1, "compression level"); - level = atoi(argv[1]); - POP_ARG(); - } - pdf_set_compression(level); - } - break; - case 'd': - if (compat_mode) { - WARN("dvipdfm \"-d\" option not supported."); - break; - } - if (isdigit(*(flag+1))) { - flag++; - pdfdecimaldigits = atoi(flag); - } else { - CHECK_ARG(1, "number of fractional digits"); - pdfdecimaldigits = atoi(argv[1]); - POP_ARG(); - } - break; - case 'I': - CHECK_ARG(1, "image cache life in hours"); - image_cache_life = atoi(argv[1]); - POP_ARG(); - break; - case 'S': - do_encryption = 1; - break; - case 'K': - CHECK_ARG(1, "encryption key length"); - key_bits = (unsigned) atoi(argv[1]); - if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) - ERROR("Invalid encryption key length specified: %s", argv[1]); - POP_ARG(); - break; - case 'P': - CHECK_ARG(1, "encryption permission flag"); - permission = (unsigned) strtoul(argv[1], &nextptr, 0); - if (nextptr == argv[1]) - ERROR("Invalid encryption permission flag: %s", argv[1]); - POP_ARG(); - break; - case 'O': - /* Bookmark open level */ - CHECK_ARG(1, "bookmark open level"); - bookmark_open = atoi(argv[1]); - POP_ARG(); - break; - case 'M': - mp_mode = 1; - break; - case 'C': - CHECK_ARG(1, "a number"); - { - long flags; - - flags = (unsigned) strtol(argv[1], &nextptr, 0); - if (nextptr == argv[1]) - ERROR("Invalid flag: %s", argv[1]); - if (flags < 0) - opt_flags = -flags; - else - opt_flags |= flags; - } - POP_ARG(); - break; - case 'E': - compat_mode = 1; - break; - case 'i': - CHECK_ARG(1, "subsidiary config file"); - read_config_file(argv[1]); - POP_ARG(); - break; - case 'e': - if (compat_mode) { - WARN("dvipdfm \"-e\" option not supported."); - break; - } /* else fall through */ - default: - if (!really_quiet) - fprintf(stderr, "Unknown option in \"-%s\"", flag); - usage(); - break; - } - } - POP_ARG(); - } - - if (argc > 1) { - if (!really_quiet) - fprintf(stderr, "Multiple dvi filenames?"); - usage(); - } else if (argc > 0) { - /* - * The only legitimate way to have argc == 0 here is - * do_args was called from config file. In that case, there is - * no dvi file name. Check for that case . - */ - if (!mp_mode && !FILESTRCASEEQ(".dvi", argv[0] + strlen(argv[0]) - 4)) { - dvi_filename = NEW(strlen(argv[0]) + 5, char); - strcpy(dvi_filename, argv[0]); - strcat(dvi_filename, ".dvi"); - } else { - dvi_filename = NEW(strlen(argv[0]) + 1, char); - strcpy(dvi_filename, argv[0]); - } - } -} - -static void -cleanup (void) -{ - if (dvi_filename) - RELEASE(dvi_filename); - if (pdf_filename) - RELEASE(pdf_filename); - if (page_ranges) - RELEASE(page_ranges); -} - -static void -read_config_file (const char *config) -{ - const char *start, *end; - char *option; - FILE *fp; - - fp = DPXFOPEN(config, DPX_RES_TYPE_TEXT); - if (!fp) { - WARN("Could not open config file \"%s\".", config); - return; - } - while ((start = mfgets (work_buffer, WORK_BUFFER_SIZE, fp)) != NULL) { - char *argv[2]; - int argc; - - argc = 0; - end = work_buffer + strlen(work_buffer); - skip_white (&start, end); - if (start >= end) - continue; - /* Build up an argument list as if it were passed on the command - line */ - if ((option = parse_ident (&start, end))) { - argc = 1; - argv[0] = NEW (strlen(option)+2, char); - strcpy (argv[0]+1, option); - RELEASE (option); - *argv[0] = '-'; - skip_white (&start, end); - if (start < end) { - argc += 1; - if (*start == '"') { - argv[1] = parse_c_string (&start, end); - } - else - argv[1] = parse_ident (&start, end); - } - } - do_args (argc, argv); - while (argc > 0) { - RELEASE (argv[--argc]); - } - } - if (fp) - MFCLOSE(fp); -} - -static void -system_default (void) -{ - if (systempapername() != NULL) { - select_paper(systempapername()); - } else if (defaultpapername() != NULL) { - select_paper(defaultpapername()); - } -} - -void -error_cleanup (void) -{ - pdf_close_images(); /* delete temporary files */ - pdf_error_cleanup(); - if (pdf_filename) { - remove(pdf_filename); - if (!really_quiet) - fprintf(stderr, "\nOutput file removed.\n"); - } -} - -#define SWAP(v1,v2) do {\ - double _tmp = (v1);\ - (v1) = (v2);\ - (v2) = _tmp;\ - } while (0) - -static void -do_dvi_pages (void) -{ - long page_no, page_count, i, step; - double page_width, page_height; - pdf_rect mediabox; - - spc_exec_at_begin_document(); - - if (num_page_ranges == 0) { - if (!page_ranges) { - page_ranges = NEW(1, struct page_range); - max_page_ranges = 1; - } - page_ranges[0].first = 0; - page_ranges[0].last = -1; /* last page */ - num_page_ranges = 1; - } - - page_width = paper_width; - page_height = paper_height; - page_count = 0; - - mediabox.llx = 0.0; - mediabox.lly = 0.0; - mediabox.urx = paper_width; - mediabox.ury = paper_height; - - pdf_doc_set_mediabox(0, &mediabox); /* Root node */ - - for (i = 0; i < num_page_ranges; i++) { - if (page_ranges[i].last < 0) - page_ranges[i].last += dvi_npages(); - - step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; - page_no = page_ranges[i].first; - for (;;) { - if (page_no < dvi_npages()) { - double w, h, xo, yo; - char lm; - - MESG("[%d", page_no+1); - /* Users want to change page size even after page is started! */ - w = page_width; h = page_height; lm = landscape_mode; - xo = x_offset; yo = y_offset; - dvi_scan_specials(page_no, &w, &h, &xo, &yo, &lm, NULL, NULL, NULL, NULL, NULL, NULL); - if (lm != landscape_mode) { - SWAP(w, h); - landscape_mode = lm; - } - if (page_width != w || page_height != h) { - page_width = w; - page_height = h; - } - if (x_offset != xo || y_offset != yo) { - x_offset = xo; - y_offset = yo; - } - if (page_width != paper_width || - page_height != paper_height) { - mediabox.llx = 0.0; - mediabox.lly = 0.0; - mediabox.urx = page_width; - mediabox.ury = page_height; - pdf_doc_set_mediabox(page_count+1, &mediabox); - } - dvi_do_page(page_no, - page_width, page_height, x_offset, y_offset); - page_count++; - MESG("]"); - } - - if (step > 0 && - page_no >= page_ranges[i].last) - break; - else if (step < 0 && - page_no <= page_ranges[i].last) - break; - else { - page_no += step; - } - } - } - - if (page_count < 1) { - ERROR("No pages fall in range!"); - } - - spc_exec_at_end_document(); -} - -static void -do_mps_pages (void) -{ - FILE *fp; - - /* _FIXME_ */ - fp = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); - if (fp) { - mps_do_page(fp); - MFCLOSE(fp); - } else { - long i, page_no, step, page_count = 0; - char *filename; - /* Process filename.1, filename.2,... */ - filename = NEW(strlen(dvi_filename) + 16 + 1, char); - for (i = 0; i < num_page_ranges; i++) { - if (page_ranges[i].last < 0) - ERROR("Invalid page number for MPS input: -1"); - - step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; - page_no = page_ranges[i].first; - for (;;) { - sprintf(filename, "%s.%ld", dvi_filename, page_no + 1); - fp = MFOPEN(filename, FOPEN_RBIN_MODE); - if (fp) { - MESG("[%ld<%s>", page_no + 1, filename); - mps_do_page(fp); - page_count++; - MESG("]"); - MFCLOSE(fp); - } - if (step > 0 && - page_no >= page_ranges[i].last) - break; - else if (step < 0 && - page_no <= page_ranges[i].last) - break; - else { - page_no += step; - } - } - } - RELEASE(filename); - if (page_count == 0) - ERROR("No page output for \"%s\".", dvi_filename); - } -} - - -/* TODO: MetaPost mode */ -#if defined(MIKTEX) -# define main Main -#endif -int CDECL -main (int argc, char *argv[]) -{ - double dvi2pts; - char *base; - -#ifdef MIKTEX - miktex_initialize(); -#else - kpse_set_program_name(argv[0], "dvipdfmx"); /* we pretend to be dvipdfmx for kpse purposes */ -#ifdef WIN32 - texlive_gs_init (); -#endif -#endif - - if (argc > 1 && - (STREQ (argv[1], "--xbb") || -#ifndef XETEX - STREQ (argv[1], "--dvipdfm") || -#endif - STREQ (argv[1], "--ebb"))) { - argc--; - base = argv++[1]+2; - } else - base = kpse_program_basename (argv[0]); - - if (FILESTRCASEEQ (base, "extractbb") || FILESTRCASEEQ (base, "xbb")) - return extractbb (argc, argv); - if (FILESTRCASEEQ (base, "ebb")) { - compat_mode = 1; - return extractbb (argc, argv); - } - -#ifndef XETEX - if (FILESTRCASEEQ (base, "dvipdfm")) - compat_mode = 1; - else -#endif - free (base); - - if (argc < 2) { - if (!really_quiet) - fprintf(stderr, "No dvi filename specified."); - usage(); - return 1; - } - - paperinit(); - system_default(); - - argv+=1; - argc-=1; - - set_verbose(argc, argv); - /* quiet mode cannot be set in config file */ - if (really_quiet) - shut_up(really_quiet); - - pdf_init_fontmaps(); /* This must come before parsing options... */ - - read_config_file(DPX_CONFIG_FILE); - - do_args (argc, argv); - -#ifndef MIKTEX - kpse_init_prog("", font_dpi, NULL, NULL); - kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf); -#endif - pdf_font_set_dpi(font_dpi); - dpx_delete_old_cache(image_cache_life); - - if (!dvi_filename) { - WARN("No dvi filename specified."); - usage(); - return 1; - } - - /* Check for ".dvi" at end of argument name */ - if (pdf_filename == NULL) - set_default_pdf_filename(); - - MESG("%s -> %s\n", dvi_filename, pdf_filename); - - pdf_enc_compute_id_string(dvi_filename, pdf_filename); - if (do_encryption) { - if (key_bits > 40 && pdf_get_version() < 4) - ERROR("Chosen key length requires at least PDF 1.4. " - "Use \"-V 4\" to change."); - pdf_enc_set_passwd(key_bits, permission, NULL, NULL); - } - - if (mp_mode) { - x_offset = 0.0; - y_offset = 0.0; - dvi2pts = 0.01; /* dvi2pts controls accuracy. */ - } else { - unsigned ver_minor = 0; - char owner_pw[MAX_PWD_LEN], user_pw[MAX_PWD_LEN]; - /* Dependency between DVI and PDF side is rather complicated... */ - dvi2pts = dvi_init(dvi_filename, mag); - if (dvi2pts == 0.0) - ERROR("dvi_init() failed!"); - - pdf_doc_set_creator(dvi_comment()); - - if (do_encryption) - /* command line takes precedence */ - dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, - &ver_minor, NULL, NULL, NULL, NULL, NULL); - else { - dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, - &ver_minor, &do_encryption, &key_bits, &permission, owner_pw, user_pw); - if (do_encryption) { - if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) - ERROR("Invalid encryption key length specified: %u", key_bits); - else if (key_bits > 40 && pdf_get_version() < 4) - ERROR("Chosen key length requires at least PDF 1.4. " - "Use \"-V 4\" to change."); - do_encryption = 1; - pdf_enc_set_passwd(key_bits, permission, owner_pw, user_pw); - } - } - if (ver_minor >= PDF_VERSION_MIN && ver_minor <= PDF_VERSION_MAX) { - pdf_set_version(ver_minor); - } - if (landscape_mode) { - SWAP(paper_width, paper_height); - } - } - - pdf_files_init(); - - /* 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, do_encryption, - paper_width, paper_height, annot_grow, bookmark_open, - !(opt_flags & OPT_PDFDOC_NO_DEST_REMOVE)); - - /* Ignore_colors placed here since - * they are considered as device's capacity. - */ - pdf_init_device(dvi2pts, pdfdecimaldigits, ignore_colors); - - if (opt_flags & OPT_CIDFONT_FIXEDPITCH) - CIDFont_set_flags(CIDFONT_FORCE_FIXEDPITCH); - - /* Please move this to spc_init_specials(). */ - if (opt_flags & OPT_TPIC_TRANSPARENT_FILL) - tpic_set_fill_mode(1); - - if (mp_mode) { - do_mps_pages(); - } else { - do_dvi_pages(); - } - - pdf_files_close(); - - /* Order of close... */ - pdf_close_device (); - /* pdf_close_document flushes XObject (image) and other resources. */ - pdf_close_document(); - - pdf_close_fontmaps(); /* pdf_font may depend on fontmap. */ - - if (!mp_mode) - dvi_close(); - - MESG("\n"); - cleanup(); - - paperdone(); -#ifdef MIKTEX - miktex_uninitialize (); -#endif - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/src/epdf.c b/Build/source/texk/dvipdfm-x/src/epdf.c deleted file mode 100644 index 46e1a75d15c..00000000000 --- a/Build/source/texk/dvipdfm-x/src/epdf.c +++ /dev/null @@ -1,968 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -/* - * Concatinating content streams are only supported for streams that only uses - * single FlateDecode filter, i.e., - * - * /Filter /FlateDecode or /Filter [/FlateDecode] - * - * TrimBox, BleedBox, ArtBox, Rotate ... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "mfileio.h" -#include "error.h" -#include "dvipdfmx.h" - -#include "pdfobj.h" -#include "pdfdev.h" -#include "pdfdoc.h" - -#ifdef XETEX -#include "pdfdraw.h" -#include "pdfparse.h" -#endif - -#include "pdfximage.h" - -#include "epdf.h" - -#ifdef XETEX -#if HAVE_ZLIB -#include -static int add_stream_flate (pdf_obj *dst, const void *data, long len); -#endif -static int rect_equal (pdf_obj *rect1, pdf_obj *rect2); - -static int concat_stream (pdf_obj *dst, pdf_obj *src); - -/* - * From PDFReference15_v6.pdf (p.119 and p.834) - * - * MediaBox rectangle (Required; inheritable) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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 -rect_equal (pdf_obj *rect1, pdf_obj *rect2) -{ - int i; - - if (!rect1 || !rect2) - return 0; - for (i = 0; i < 4; i++) { - if (pdf_number_value(pdf_get_array(rect1, i)) != - pdf_number_value(pdf_get_array(rect2, i))) - return 0; - } - - return 1; -} - -static pdf_obj* -pdf_get_page_obj (pdf_file *pf, long page_no, - pdf_obj **ret_bbox, pdf_obj **ret_resources) -{ - pdf_obj *page_tree; - pdf_obj *bbox = NULL, *resources = NULL, *rotate = NULL; - long page_idx; - - /* - * Get Page Tree. - */ - page_tree = NULL; - { - pdf_obj *trailer, *catalog; - pdf_obj *markinfo, *tmp; - - trailer = pdf_file_get_trailer(pf); - - if (pdf_lookup_dict(trailer, "Encrypt")) { - WARN("This PDF document is encrypted."); - pdf_release_obj(trailer); - return NULL; - } - - catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); - 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); - - markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); - if (markinfo) { - tmp = pdf_lookup_dict(markinfo, "Marked"); - if (PDF_OBJ_BOOLEANTYPE(tmp) && pdf_boolean_value(tmp)) - WARN("File contains tagged PDF. Ignoring tags."); - pdf_release_obj(markinfo); - } - - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - pdf_release_obj(catalog); - } - if (!page_tree) { - WARN("Page tree not found."); - return NULL; - } - - /* - * 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); - pdf_release_obj(page_tree); - return NULL; - } - page_no = page_idx+1; - } - - /* - * Seek correct page. Get Media/Crop Box. - * Media box and resources can be inherited. - */ - { - pdf_obj *kids_ref, *kids; - pdf_obj *crop_box = NULL; - pdf_obj *tmp; - - tmp = pdf_lookup_dict(page_tree, "Resources"); - resources = tmp ? pdf_deref_obj(tmp) : pdf_new_dict(); - - 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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(tmp); - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { - if (rotate) - pdf_release_obj(rotate); - rotate = tmp; - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { -#if 0 - pdf_merge_dict(tmp, resources); -#endif - if (resources) - 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); - 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; - } - - if (ret_bbox != NULL) - *ret_bbox = bbox; - if (ret_resources != NULL) - *ret_resources = resources; - - 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; - 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++; - } - 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; - } - /* 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; - } - pdf_release_obj(contents); - contents = content_new; - } - - return contents; -} -#endif - -int -pdf_include_page (pdf_ximage *ximage, FILE *image_file, const char *filename) -{ - pdf_file *pf; - xform_info info; - pdf_obj *contents = NULL, *catalog; - pdf_obj *page = NULL, *resources = NULL, *markinfo = NULL; - - pf = pdf_open(filename, image_file); - if (!pf) - return -1; - - if (pdf_file_get_version(pf) > pdf_get_version()) - goto too_recent; - - pdf_ximage_init_form_info(&info); - - page = pdf_doc_get_page(pf, pdf_ximage_get_page(ximage), NULL, - &info.bbox, &resources); - - if(!page) - goto error_silent; - - catalog = pdf_file_get_catalog(pf); - markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); - if (markinfo) { - pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(markinfo, "Marked")); - pdf_release_obj(markinfo); - if (!PDF_OBJ_BOOLEANTYPE(tmp)) { - if (tmp) - pdf_release_obj(tmp); - goto error; - } else if (pdf_boolean_value(tmp)) - WARN("File contains tagged PDF. Ignoring tags."); - pdf_release_obj(tmp); - } - - contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents")); - pdf_release_obj(page); - - /* - * Handle page content stream. - */ - { - pdf_obj *content_new; - - if (!contents) { - /* - * Empty page - */ - content_new = pdf_new_stream(0); - /* TODO: better don't include anything if the page is empty */ - } else if (PDF_OBJ_STREAMTYPE(contents)) { - /* - * We must import the stream because its dictionary - * may contain indirect references. - */ - content_new = pdf_import_object(contents); - } else if (PDF_OBJ_ARRAYTYPE(contents)) { - /* - * Concatenate all content streams. - */ - int idx, len = pdf_array_length(contents); - content_new = pdf_new_stream(STREAM_COMPRESS); - for (idx = 0; idx < len; idx++) { - pdf_obj *content_seg = pdf_deref_obj(pdf_get_array(contents, idx)); - if (!PDF_OBJ_STREAMTYPE(content_seg) || - pdf_concat_stream(content_new, content_seg) < 0) { - pdf_release_obj(content_seg); - pdf_release_obj(content_new); - goto error; - } - pdf_release_obj(content_seg); - } - } else - goto error; - - if (contents) - pdf_release_obj(contents); - contents = content_new; - } - - /* - * Add entries to contents stream dictionary. - */ - { - pdf_obj *contents_dict, *bbox, *matrix; - - contents_dict = pdf_stream_dict(contents); - pdf_add_dict(contents_dict, - pdf_new_name("Type"), - pdf_new_name("XObject")); - pdf_add_dict(contents_dict, - pdf_new_name("Subtype"), - pdf_new_name("Form")); - pdf_add_dict(contents_dict, - pdf_new_name("FormType"), - pdf_new_number(1.0)); - - bbox = pdf_new_array(); - pdf_add_array(bbox, pdf_new_number(info.bbox.llx)); - pdf_add_array(bbox, pdf_new_number(info.bbox.lly)); - pdf_add_array(bbox, pdf_new_number(info.bbox.urx)); - pdf_add_array(bbox, pdf_new_number(info.bbox.ury)); - - pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox); - - matrix = pdf_new_array(); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - - pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix); - - pdf_add_dict(contents_dict, - pdf_new_name("Resources"), - pdf_import_object(resources)); - pdf_release_obj(resources); - } - - pdf_close(pf); - - pdf_ximage_set_form(ximage, &info, contents); - - return 0; - - error: - WARN("Cannot parse document. Broken PDF file?"); - error_silent: - if (resources) - pdf_release_obj(resources); - if (markinfo) - pdf_release_obj(markinfo); - if (page) - pdf_release_obj(page); - if (contents) - pdf_release_obj(contents); - - pdf_close(pf); - - return -1; - - too_recent: - pdf_close(pf); - WARN("PDF version of input file more recent than in output file."); - if (compat_mode) { - WARN("Converting. Use \"-V\" switch to change output PDF version."); - return 1; - } else { - WARN("Use \"-V\" switch to change output PDF version."); - return -1; - } -} - -#ifdef XETEX -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; - const char *clip_path, *end_path; - char *save_path, *temp; - pdf_tmatrix M; - double stack[6]; - pdf_file *pf; - - pf = pdf_open(NULL, image_file); - if (!pf) - return -1; - - pdf_dev_currentmatrix(&M); - pdf_invertmatrix(&M); - M.e += x_user; M.f += y_user; - page_tree = pdf_get_page_obj (pf, pageNo, NULL, NULL); - if (!page_tree) { - pdf_close(pf); - return -1; - } - - contents = pdf_get_page_content(page_tree); - pdf_release_obj(page_tree); - if (!contents) { - pdf_close(pf); - return -1; - } - - pdf_doc_add_page_content(" ", 1); - - save_path = malloc(pdf_stream_length(contents) + 1); - strncpy(save_path, (const char *) pdf_stream_dataptr(contents), pdf_stream_length(contents)); - clip_path = save_path; - end_path = clip_path + pdf_stream_length(contents); - depth = 0; - - for (; clip_path < end_path; clip_path++) { - int color_dimen = 0; /* silence uninitialized warning */ - 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, pf); - 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; - } - } - } - free(save_path); - - pdf_release_obj(contents); - pdf_close(pf); - - return 0; -} - -#define WBUF_SIZE 4096 -#if HAVE_ZLIB -static int -add_stream_flate (pdf_obj *dst, const void *data, long len) -{ - z_stream z; - Bytef wbuf[WBUF_SIZE]; - - z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - z.next_in = (Bytef *) data; z.avail_in = len; - z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; - - if (inflateInit(&z) != Z_OK) { - WARN("inflateInit() failed."); - return -1; - } - - for (;;) { - int status; - status = inflate(&z, Z_NO_FLUSH); - if (status == Z_STREAM_END) - break; - else if (status != Z_OK) { - WARN("inflate() failed. Broken PDF file?"); - inflateEnd(&z); - return -1; - } - - if (z.avail_out == 0) { - pdf_add_stream(dst, wbuf, WBUF_SIZE); - z.next_out = wbuf; - z.avail_out = WBUF_SIZE; - } - } - - if (WBUF_SIZE - z.avail_out > 0) - pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); - - return (inflateEnd(&z) == Z_OK ? 0 : -1); -} -#endif - -static int -concat_stream (pdf_obj *dst, pdf_obj *src) -{ - const char *stream_data; - long stream_length; - pdf_obj *stream_dict; - pdf_obj *filter; - - if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) - ERROR("Invalid type."); - - stream_data = pdf_stream_dataptr(src); - stream_length = pdf_stream_length (src); - stream_dict = pdf_stream_dict (src); - - if (pdf_lookup_dict(stream_dict, "DecodeParms")) { - WARN("DecodeParams not supported."); - return -1; - } - - filter = pdf_lookup_dict(stream_dict, "Filter"); - if (!filter) { - pdf_add_stream(dst, stream_data, stream_length); - return 0; -#if HAVE_ZLIB - } else { - char *filter_name; - if (PDF_OBJ_NAMETYPE(filter)) { - filter_name = pdf_name_value(filter); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } else if (PDF_OBJ_ARRAYTYPE(filter)) { - if (pdf_array_length(filter) > 1) { - WARN("Multiple DecodeFilter not supported."); - return -1; - } else { - filter_name = pdf_name_value(pdf_get_array(filter, 0)); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } - } else - ERROR("Broken PDF file?"); -#endif /* HAVE_ZLIB */ - } - - return -1; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/src/jpegimage.c b/Build/source/texk/dvipdfm-x/src/jpegimage.c deleted file mode 100644 index a397a373fb2..00000000000 --- a/Build/source/texk/dvipdfm-x/src/jpegimage.c +++ /dev/null @@ -1,920 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* - * JPEG SUPPORT - * - * Accroding to Libjpeg document: - * - * CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK - * JPEG files: 0 represents 100% ink coverage, rather than 0% ink as you'd - * expect.... - * - * To wrok with this problem, we must detect whether CMYK JPEG file is - * created by Photoshop. But there are no reliable way to determine this. - * - * According to Adobe Technical Note #5516, - * "Supporting the DCT Filters in PostScript Level 2", Section 18, p.27. - * - * DCTDecode ignores and skips any APPE marker segment does not begin with - * the `Adobe' 5-character string. - * - * PDF Reference Manual 4th ed., p.61-62. - * - * The JPEG filter implementation in Adobe Acrobat products does not - * support features of the JPEG standard that are irrelevant to images. - * In addition, certain choices have been made regarding reserved marker - * codes and other optional features of the standard. For details, see - * Adobe Technical Note #5116, Supporting the DCT Filters in PostScript - * Level 2. - */ - -#include "system.h" -#include "error.h" -#include "mem.h" - -#include "mfileio.h" -#include "numbers.h" - -#include "dvipdfmx.h" - -#include "pdfobj.h" - -#include "jpegimage.h" -#include "pdfcolor.h" - -#include "pdfximage.h" - -#define JPEG_DEBUG_STR "JPEG" -#define JPEG_DEBUG 3 - -#ifdef HAVE_LIBJPEG -#include -#endif /* HAVE_LIBJPEG */ - -/* JPEG Markers */ -typedef enum { - JM_SOF0 = 0xc0, - JM_SOF1 = 0xc1, - JM_SOF2 = 0xc2, - JM_SOF3 = 0xc3, - JM_SOF5 = 0xc5, - JM_DHT = 0xc4, - JM_SOF6 = 0xc6, - JM_SOF7 = 0xc7, - JM_SOF9 = 0xc9, - JM_SOF10 = 0xca, - JM_SOF11 = 0xcb, - JM_DAC = 0xcc, - JM_SOF13 = 0xcd, - JM_SOF14 = 0xce, - JM_SOF15 = 0xcf, - - JM_RST0 = 0xd0, - JM_RST1 = 0xd1, - JM_RST2 = 0xd2, - JM_RST3 = 0xd3, - JM_RST4 = 0xd4, - JM_RST5 = 0xd5, - JM_RST6 = 0xd6, - JM_RST7 = 0xd7, - - JM_SOI = 0xd8, - JM_EOI = 0xd9, - JM_SOS = 0xda, - JM_DQT = 0xdb, - JM_DNL = 0xdc, - JM_DRI = 0xdd, - JM_DHP = 0xde, - JM_EXP = 0xdf, - - JM_APP0 = 0xe0, - JM_APP1 = 0xe1, - JM_APP2 = 0xe2, - JM_APP14 = 0xee, - JM_APP15 = 0xef, - - JM_COM = 0xfe -} JPEG_marker; - -typedef enum { - JS_APPn_JFIF, - JS_APPn_ADOBE, - JS_APPn_ICC -} JPEG_APPn_sig; - -struct JPEG_APPn_JFIF /* APP0 */ -{ - unsigned short version; - unsigned char units; /* 0: only aspect ratio - * 1: dots per inch - * 2: dots per cm - */ - unsigned short Xdensity; - unsigned short Ydensity; - unsigned char Xthumbnail; - unsigned char Ythumbnail; - unsigned char *thumbnail; /* Thumbnail data. */ -}; - -struct JPEG_APPn_ICC /* APP2 */ -{ - unsigned char seq_id; - unsigned char num_chunks; - unsigned char *chunk; - - /* Length of ICC profile data in this chunk. */ - unsigned short length; -}; - -struct JPEG_APPn_Adobe /* APP14 */ -{ - unsigned short version; - unsigned short flag0; - unsigned short flag1; - unsigned char transform; /* color transform code */ -}; - -struct JPEG_ext -{ - JPEG_marker marker; - JPEG_APPn_sig app_sig; - void *app_data; -}; - -#define MAX_COUNT 1024 -struct JPEG_info -{ - unsigned short height; - unsigned short width; - - unsigned char bits_per_component; - unsigned char num_components; - - /* Application specific extensions */ - int flags; - int num_appn, max_appn; - struct JPEG_ext *appn; - - /* Skip chunks not necessary. */ - char skipbits[MAX_COUNT / 8 + 1]; -}; - -#define HAVE_APPn_JFIF (1 << 0) -#define HAVE_APPn_ADOBE (1 << 1) -#define HAVE_APPn_ICC (1 << 2) -#define HAVE_APPn_Exif (1 << 3) - -static int JPEG_scan_file (struct JPEG_info *j_info, FILE *fp); -static int JPEG_copy_stream (struct JPEG_info *j_info, - pdf_obj *stream, FILE *fp, int flags); /* flags unused yet */ - -static void JPEG_info_init (struct JPEG_info *j_info); -static void JPEG_info_clear (struct JPEG_info *j_info); -static pdf_obj *JPEG_get_iccp (struct JPEG_info *j_info); -static void jpeg_get_density (struct JPEG_info *j_info, - double *xdensity, double *ydensity); - -int -check_for_jpeg (FILE *fp) -{ - unsigned char jpeg_sig[2]; - - rewind(fp); - if (fread(jpeg_sig, sizeof(unsigned char), 2, fp) != 2) - return 0; - else if (jpeg_sig[0] != 0xff || jpeg_sig[1] != JM_SOI) - return 0; - - return 1; -} - -int -jpeg_include_image (pdf_ximage *ximage, FILE *fp) -{ - pdf_obj *stream; - pdf_obj *stream_dict; - pdf_obj *colorspace; - int colortype; - ximage_info info; - struct JPEG_info j_info; - - if (!check_for_jpeg(fp)) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - rewind(fp); - return -1; - } - /* File position is 2 here... */ - - pdf_ximage_init_image_info(&info); - - JPEG_info_init(&j_info); - - if (JPEG_scan_file(&j_info, fp) < 0) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - JPEG_info_clear(&j_info); - return -1; - } - - switch (j_info.num_components) { - case 1: - colortype = PDF_COLORSPACE_TYPE_GRAY; - break; - case 3: - colortype = PDF_COLORSPACE_TYPE_RGB; - break; - case 4: - colortype = PDF_COLORSPACE_TYPE_CMYK; - break; - default: - WARN("%s: Unknown color space (num components: %d)", - JPEG_DEBUG_STR, info.num_components); - JPEG_info_clear(&j_info); - return -1; - } - - /* JPEG image use DCTDecode. */ - stream = pdf_new_stream (0); - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, - pdf_new_name("Filter"), pdf_new_name("DCTDecode")); - - colorspace = NULL; - if (j_info.flags & HAVE_APPn_ICC) { - pdf_obj *icc_stream, *intent; - - icc_stream = JPEG_get_iccp(&j_info); - - if (!icc_stream) - colorspace = NULL; - else { - int cspc_id; - - if (iccp_check_colorspace(colortype, - pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)) < 0) - colorspace = NULL; - else { - cspc_id = iccp_load_profile(NULL, /* noname */ - pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)); - if (cspc_id < 0) - colorspace = NULL; - else { - colorspace = pdf_get_colorspace_reference(cspc_id); - intent = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)); - if (intent) - pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); - } - } - pdf_release_obj(icc_stream); - } - } - - /* No ICC or invalid ICC profile. */ - if (!colorspace) { - switch (colortype) { - case PDF_COLORSPACE_TYPE_GRAY: - colorspace = pdf_new_name("DeviceGray"); - break; - case PDF_COLORSPACE_TYPE_RGB: - colorspace = pdf_new_name("DeviceRGB"); - break; - case PDF_COLORSPACE_TYPE_CMYK: - colorspace = pdf_new_name("DeviceCMYK"); - break; - } - } - pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); - -#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4) - - if (IS_ADOBE_CMYK(j_info)) { - pdf_obj *decode; - int i; - - WARN("Adobe CMYK JPEG: Inverted color assumed."); - decode = pdf_new_array(); - for (i = 0; i < j_info.num_components; i++) { - pdf_add_array(decode, pdf_new_number(1.0)); - pdf_add_array(decode, pdf_new_number(0.0)); - } - pdf_add_dict(stream_dict, pdf_new_name("Decode"), decode); - } - - /* Copy file */ - JPEG_copy_stream(&j_info, stream, fp, 0); - - info.width = j_info.width; - info.height = j_info.height; - info.bits_per_component = j_info.bits_per_component; - info.num_components = j_info.num_components; - - jpeg_get_density(&j_info, &info.xdensity, &info.ydensity); - - pdf_ximage_set_image(ximage, &info, stream); - JPEG_info_clear(&j_info); - - return 0; -} - -static void -jpeg_get_density (struct JPEG_info *j_info, - double *xdensity, double *ydensity) -{ - if (compat_mode) { - *xdensity = *ydensity = 72.0 / 100.0; - return; - } - - *xdensity = *ydensity = 1.0; - - if (j_info->flags & HAVE_APPn_JFIF) { - struct JPEG_APPn_JFIF *app_data; - 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) { - app_data = (struct JPEG_APPn_JFIF *)j_info->appn[i].app_data; - switch (app_data->units) { - case 1: /* pixels per inch */ - *xdensity = 72.0 / app_data->Xdensity; - *ydensity = 72.0 / app_data->Ydensity; - break; - case 2: /* pixels per centimeter */ - *xdensity = 72.0 / 2.54 / app_data->Xdensity; - *ydensity = 72.0 / 2.54 / app_data->Ydensity; - break; - default: - break; - } - } - } -} - -static void -JPEG_info_init (struct JPEG_info *j_info) -{ - j_info->width = 0; - j_info->height = 0; - j_info->bits_per_component = 0; - j_info->num_components = 0; - - j_info->flags = 0; - j_info->num_appn = 0; - j_info->max_appn = 0; - j_info->appn = NULL; - - memset(j_info->skipbits, 0, MAX_COUNT / 8 + 1); -} - -static void -JPEG_release_APPn_data (JPEG_marker marker, JPEG_APPn_sig app_sig, void *app_data) -{ - if (marker == JM_APP0 && - app_sig == JS_APPn_JFIF) { - struct JPEG_APPn_JFIF *data; - - data = (struct JPEG_APPn_JFIF *) app_data; - if (data->thumbnail) - RELEASE(data->thumbnail); - data->thumbnail = NULL; - - RELEASE(data); - } else if (marker == JM_APP2 && - app_sig == JS_APPn_ICC) { - struct JPEG_APPn_ICC *data; - - data = (struct JPEG_APPn_ICC *) app_data; - if (data->chunk) - RELEASE(data->chunk); - data->chunk = NULL; - - RELEASE(data); - } else if (marker == JM_APP14 && - app_sig == JS_APPn_ADOBE) { - struct JPEG_APPn_Adobe *data; - - data = (struct JPEG_APPn_Adobe *) app_data; - - RELEASE(data); - } -} - -static void -JPEG_info_clear (struct JPEG_info *j_info) -{ - if (j_info->num_appn > 0 && - j_info->appn != NULL) { - int i; - - for (i = 0; i < j_info->num_appn; i++) - JPEG_release_APPn_data(j_info->appn[i].marker, - j_info->appn[i].app_sig, j_info->appn[i].app_data); - RELEASE(j_info->appn); - } - j_info->appn = NULL; - j_info->num_appn = 0; - j_info->max_appn = 0; - j_info->flags = 0; -} - -static pdf_obj * -JPEG_get_iccp (struct JPEG_info *j_info) -{ - pdf_obj *icc_stream; - struct JPEG_APPn_ICC *icc; - int i, prev_id = 0, num_icc_seg = -1; - - icc_stream = pdf_new_stream(STREAM_COMPRESS); - for (i = 0; i < j_info->num_appn; i++) { - if (j_info->appn[i].marker != JM_APP2 || - j_info->appn[i].app_sig != JS_APPn_ICC) - continue; - icc = (struct JPEG_APPn_ICC *) j_info->appn[i].app_data; - if (num_icc_seg < 0 && prev_id == 0) { - num_icc_seg = icc->num_chunks; - /* ICC chunks are sorted? */ - } else if (icc->seq_id != prev_id + 1 || - num_icc_seg != icc->num_chunks || - icc->seq_id > icc->num_chunks) { - WARN("Invalid JPEG ICC chunk: %d (p:%d, n:%d)", - icc->seq_id, prev_id, icc->num_chunks); - pdf_release_obj(icc_stream); - icc_stream = NULL; - break; - } - pdf_add_stream(icc_stream, icc->chunk, icc->length); - prev_id = icc->seq_id; - num_icc_seg = icc->num_chunks; - } - - return icc_stream; -} - -static JPEG_marker -JPEG_get_marker (FILE *fp) -{ - int c; - - c = fgetc(fp); - if (c != 255) - return -1; - - for (;;) { - c = fgetc(fp); - if (c < 0) - return -1; - else if (c > 0 && c < 255) { - return c; - } - } - - return -1; -} - -static int -add_APPn_marker (struct JPEG_info *j_info, - JPEG_marker marker, int app_sig, void *app_data) -{ - int n; - - if (j_info->num_appn >= j_info->max_appn) { - j_info->max_appn += 16; - j_info->appn = RENEW(j_info->appn, j_info->max_appn, struct JPEG_ext); - } - n = j_info->num_appn; - - j_info->appn[n].marker = marker; - j_info->appn[n].app_sig = app_sig; - j_info->appn[n].app_data = app_data; - - j_info->num_appn += 1; - - return n; -} - -static unsigned short -read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_Adobe *app_data; - - app_data = NEW(1, struct JPEG_APPn_Adobe); - app_data->version = get_unsigned_pair(fp); - app_data->flag0 = get_unsigned_pair(fp); - app_data->flag1 = get_unsigned_pair(fp); - app_data->transform = get_unsigned_byte(fp); - - add_APPn_marker(j_info, JM_APP14, JS_APPn_ADOBE, app_data); - - return 7; -} - -#ifdef XETEX -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; - int num_fields, tag, type; - int value = 0, num = 0, den = 0; /* silence uninitialized warnings */ - 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); - 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; -} -#endif - -static unsigned short -read_APP0_JFIF (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_JFIF *app_data; - unsigned short thumb_data_len; - - app_data = NEW(1, struct JPEG_APPn_JFIF); - app_data->version = get_unsigned_pair(fp); - app_data->units = get_unsigned_byte(fp); - app_data->Xdensity = get_unsigned_pair(fp); - app_data->Ydensity = get_unsigned_pair(fp); - app_data->Xthumbnail = get_unsigned_byte(fp); - app_data->Ythumbnail = get_unsigned_byte(fp); - thumb_data_len = 3 * app_data->Xthumbnail * app_data->Ythumbnail; - if (thumb_data_len > 0) { - app_data->thumbnail = NEW(thumb_data_len, unsigned char); - fread(app_data->thumbnail, 1, thumb_data_len, fp); - } else { - app_data->thumbnail = NULL; - } - - add_APPn_marker(j_info, JM_APP0, JS_APPn_JFIF, app_data); - - return (9 + thumb_data_len); -} - -static unsigned short -read_APP0_JFXX (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - get_unsigned_byte(fp); - /* Extension Code: - * - * 0x10: Thumbnail coded using JPEG - * 0x11: Thumbnail stored using 1 byte/pixel - * 0x13: Thumbnail stored using 3 bytes/pixel - */ - seek_relative(fp, length-1); /* Thunbnail image */ - - /* Ignore */ - - return length; -} - -static unsigned short -read_APP2_ICC (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_ICC *app_data; - - app_data = NEW(1, struct JPEG_APPn_ICC); - app_data->seq_id = get_unsigned_byte(fp); /* Starting at 1 */ - app_data->num_chunks = get_unsigned_byte(fp); - app_data->length = length - 2; - app_data->chunk = NEW(app_data->length, unsigned char); - fread(app_data->chunk, 1, app_data->length, fp); - - add_APPn_marker(j_info, JM_APP2, JS_APPn_ICC, app_data); - - return length; -} - -static int -JPEG_copy_stream (struct JPEG_info *j_info, - pdf_obj *stream, FILE *fp, int flags) /* flags unused yet */ -{ - JPEG_marker marker; - long length, nb_read; - int found_SOFn, count; - - rewind(fp); - count = 0; - found_SOFn = 0; - while (!found_SOFn && - count < MAX_COUNT && - (marker = JPEG_get_marker(fp)) >= 0) { - if (marker == JM_SOI || - (marker >= JM_RST0 && marker <= JM_RST7)) { - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - pdf_add_stream(stream, work_buffer, 2); - count++; - continue; - } - length = get_unsigned_pair(fp) - 2; - switch (marker) { - case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: - case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: - case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: - case JM_SOF15: - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - work_buffer[2] = ((length + 2) >> 8) & 0xff; - work_buffer[3] = (length + 2) & 0xff; - pdf_add_stream(stream, work_buffer, 4); - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - if (nb_read > 0) - pdf_add_stream(stream, work_buffer, nb_read); - length -= nb_read; - } - found_SOFn = 1; - break; - default: - if (j_info->skipbits[count / 8] & (1 << (7 - (count % 8)))) { - /* skip */ - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - length -= nb_read; - } - } else { - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - work_buffer[2] = ((length + 2) >> 8) & 0xff; - work_buffer[3] = (length + 2) & 0xff; - pdf_add_stream(stream, work_buffer, 4); - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - if (nb_read > 0) - pdf_add_stream(stream, work_buffer, nb_read); - length -= nb_read; - } - } - } - count++; - } - - while ((length = fread(work_buffer, - sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) { - pdf_add_stream(stream, work_buffer, length); - } - - return (found_SOFn ? 0 : -1); -} - -static int -JPEG_scan_file (struct JPEG_info *j_info, FILE *fp) -{ - JPEG_marker marker; - unsigned short length; - int found_SOFn, count; - char app_sig[128]; - - rewind(fp); - count = 0; - found_SOFn = 0; - while (!found_SOFn && - (marker = JPEG_get_marker(fp)) >= 0) { - if (marker == JM_SOI || - (marker >= JM_RST0 && marker <= JM_RST7)) { - count++; - continue; - } - length = get_unsigned_pair(fp) - 2; - switch (marker) { - case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: - case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: - case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: - case JM_SOF15: - j_info->bits_per_component = get_unsigned_byte(fp); - j_info->height = get_unsigned_pair(fp); - j_info->width = get_unsigned_pair(fp); - j_info->num_components = get_unsigned_byte(fp); - found_SOFn = 1; - break; - case JM_APP0: - if (length > 5) { - if (fread(app_sig, sizeof(char), 5, fp) != 5) - return -1; - length -= 5; - if (!memcmp(app_sig, "JFIF\000", 5)) { - j_info->flags |= HAVE_APPn_JFIF; - length -= read_APP0_JFIF(j_info, fp, length); - } else if (!memcmp(app_sig, "JFXX", 5)) { - length -= read_APP0_JFXX(j_info, fp, length); - } - } - seek_relative(fp, length); - break; - case JM_APP2: - if (length >= 14) { - if (fread(app_sig, sizeof(char), 12, fp) != 12) - return -1; - length -= 12; - if (!memcmp(app_sig, "ICC_PROFILE\000", 12)) { - j_info->flags |= HAVE_APPn_ICC; - length -= read_APP2_ICC(j_info, fp, length); - if (count < MAX_COUNT) { - j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); - } - } - } - seek_relative(fp, length); - break; - case JM_APP14: - if (length > 5) { - if (fread(app_sig, sizeof(char), 5, fp) != 5) - return -1; - length -= 5; - if (!memcmp(app_sig, "Adobe", 5)) { - j_info->flags |= HAVE_APPn_ADOBE; - length -= read_APP14_Adobe(j_info, fp, length); - } else { - if (count < MAX_COUNT) { - j_info->skipbits[count/8] |= (1 << (7 - (count % 8))); - } - } - } - seek_relative(fp, length); - break; - default: - seek_relative(fp, length); - if (marker >= JM_APP0 && - marker <= JM_APP15) { - if (count < MAX_COUNT) { - j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); - } - } - break; - } - count++; - } - - return (found_SOFn ? 0 : -1); -} - -int -jpeg_get_bbox (FILE *fp, long *width, long *height, - double *xdensity, double *ydensity) -{ - struct JPEG_info j_info; - - JPEG_info_init(&j_info); - - if (JPEG_scan_file(&j_info, fp) < 0) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - JPEG_info_clear(&j_info); - return -1; - } - - *width = j_info.width; - *height = j_info.height; - - jpeg_get_density(&j_info, xdensity, ydensity); - - JPEG_info_clear(&j_info); - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/src/pdfcolor.c b/Build/source/texk/dvipdfm-x/src/pdfcolor.c deleted file mode 100644 index 988f4ec6e4a..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfcolor.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -/* No page independence here... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfdoc.h" -#include "pdfdraw.h" - -#include "pdfcolor.h" - - -static int verbose = 0; -void -pdf_color_set_verbose (void) -{ - verbose++; -} - -#ifndef XETEX -/* This function returns PDF_COLORSPACE_TYPE_GRAY, - * PDF_COLORSPACE_TYPE_RGB or PDF_COLORSPACE_TYPE_CMYK. - */ -int -pdf_color_type (const pdf_color *color) -{ - ASSERT(color); - - return -color->num_components; -} -#endif - -int -pdf_color_rgbcolor (pdf_color *color, double r, double g, double b) -{ - ASSERT(color); - - if (r < 0.0 || r > 1.0) { - WARN("Invalid color value specified: red=%g", r); - return -1; - } - if (g < 0.0 || g > 1.0) { - WARN("Invalid color value specified: green=%g", g); - return -1; - } - if (b < 0.0 || b > 1.0) { - WARN("Invalid color value specified: blue=%g", b); - return -1; - } - color->values[0] = r; - color->values[1] = g; - color->values[2] = b; - - color->num_components = 3; - - return 0; -} - -int -pdf_color_cmykcolor (pdf_color *color, - double c, double m, double y, double k) -{ - ASSERT(color); - - if (c < 0.0 || c > 1.0) { - WARN("Invalid color value specified: cyan=%g", c); - return -1; - } - if (m < 0.0 || m > 1.0) { - WARN("Invalid color value specified: magenta=%g", m); - return -1; - } - if (y < 0.0 || y > 1.0) { - WARN("Invalid color value specified: yellow=%g", y); - return -1; - } - if (k < 0.0 || k > 1.0) { - WARN("Invalid color value specified: black=%g", k); - return -1; - } - - color->values[0] = c; - color->values[1] = m; - color->values[2] = y; - color->values[3] = k; - - color->num_components = 4; - - return 0; -} - -int -pdf_color_graycolor (pdf_color *color, double g) -{ - ASSERT(color); - - if (g < 0.0 || g > 1.0) { - WARN("Invalid color value specified: gray=%g", g); - return -1; - } - - color->values[0] = g; - - color->num_components = 1; - - return 0; -} - - -void -pdf_color_copycolor (pdf_color *color1, const pdf_color *color2) -{ - ASSERT(color1 && color2); - - memcpy(color1, color2, sizeof(pdf_color)); -} - -#ifndef XETEX -/* Brighten up a color. f == 0 means no change, f == 1 means white. */ -void -pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f) -{ - ASSERT(dst && src); - - if (f == 1.0) { - pdf_color_white(dst); - } else { - double f0, f1; - int n; - - n = dst->num_components = src->num_components; - f1 = n == 4 ? 0.0 : f; /* n == 4 is CMYK, others are RGB and Gray */ - f0 = 1.0-f; - - while (n--) - dst->values[n] = f0 * src->values[n] + f1; - } -} -#endif - -int -pdf_color_is_white (const pdf_color *color) -{ - int n; - double f; - - ASSERT(color); - - n = color->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - f = 1.0; - break; - case 4: /* CMYK */ - f = 0.0; - break; - default: - return 0; - } - - while (n--) - if (color->values[n] != f) - return 0; - - return 1; -} - -#ifndef XETEX -int -pdf_color_to_string (const pdf_color *color, char *buffer) -{ - int i, len = 0; - - for (i = 0; i < color->num_components; i++) { - len += sprintf(buffer+len, " %g", ROUND(color->values[i], 0.001)); - } - return len; -} -#endif - -pdf_color current_fill = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -pdf_color current_stroke = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -#ifndef XETEX -/* - * This routine is not a real color matching. - */ -int -pdf_color_compare (const pdf_color *color1, const pdf_color *color2) -{ - int n; - - n = color1->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - case 4: /* CMYK */ - break; - default: - return -1; - } - - if (n != color2->num_components) - return -1; - - while (n--) - if (color1->values[n] != color2->values[n]) - return -1; - - return 0; -} -#endif - -int -pdf_color_is_valid (const pdf_color *color) -{ - int n; - - n = color->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - case 4: /* CMYK */ - break; - default: - return 0; - } - - while (n--) - if (color->values[n] < 0.0 || color->values[n] > 1.0) { - WARN("Invalid color value: %g", color->values[n]); - return 0; - } - - return 1; -} - -/* Dvipdfm special */ -pdf_color default_color = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -void -pdf_color_set_default (const pdf_color *color) -{ - pdf_color_copycolor(&default_color, color); -} - -#define DEV_COLOR_STACK_MAX 128 - -static struct { - int current; - pdf_color stroke[DEV_COLOR_STACK_MAX]; - pdf_color fill[DEV_COLOR_STACK_MAX]; -} color_stack; - -void -pdf_color_clear_stack (void) -{ - if (color_stack.current > 0) { - WARN("You've mistakenly made a global color change within nested colors."); - } - color_stack.current = 0; - pdf_color_black(color_stack.stroke); - pdf_color_black(color_stack.fill); - return; -} - -#ifndef XETEX -void -pdf_color_set (pdf_color *sc, pdf_color *fc) -{ - pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); - pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); - pdf_dev_reset_color(0); -} -#endif - -void -pdf_color_push (pdf_color *sc, pdf_color *fc) -{ - if (color_stack.current >= DEV_COLOR_STACK_MAX-1) { - WARN("Color stack overflow. Just ignore."); - } else { - color_stack.current++; - pdf_color_set(sc, fc); - } - return; -} - -void -pdf_color_pop (void) -{ - if (color_stack.current <= 0) { - WARN("Color stack underflow. Just ignore."); - } else { - color_stack.current--; - pdf_dev_reset_color(0); - } - return; -} - -void -pdf_color_get_current (pdf_color **sc, pdf_color **fc) -{ - *sc = &color_stack.stroke[color_stack.current]; - *fc = &color_stack.fill[color_stack.current]; - return; -} - -#ifdef XETEX -/* 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) -{ - if (color_stack.current > 0) { - current_stroke = color_stack.stroke[color_stack.current]; - current_fill = color_stack.fill[color_stack.current]; - } -} -#endif - -/***************************** COLOR SPACE *****************************/ - -static int pdf_colorspace_defineresource (const char *ident, - int subtype, - void *cdata, pdf_obj *resource); - -static int pdf_colorspace_findresource (const char *ident, - int subtype, const void *cdata); - -#if 0 -struct calgray_cdata -{ - double white_point[3]; /* required, second component must - * be equal to 1.0 - */ - double black_point[3]; /* optional, default: [0 0 0] */ - double gamma; /* optional, default: 1.0 */ -}; - -struct calrgb_cdata -{ - double white_point[3]; /* required, second component must - * be equal to 1.0 - */ - double black_point[3]; /* optional, default: [0 0 0] */ - double gamma[3]; /* optional, default: [1 1 1] */ - double matrix[9]; /* optional, default: identity - * [1 0 0 0 1 0 0 0 1] - */ -}; - -static void -release_calrgb (void *cdata) -{ - struct calrgb_cdata *calrgb; - - if (cdata) { - calrgb = (struct calrgb_cdata *) cdata; - RELEASE(calrgb); - } -} - -static int -compare_calrgb (const char *ident1, const void *cdata1, - const char *ident2, const void *cdata2) -{ - struct calrgb_cdata *calrgb1; - struct calrgb_cdata *calrgb2; - - if (ident1 && ident2 && - !strcmp(ident1, ident2)) { - return 0; - } -} - -static void -init_calrgb (struct calrgb_cdata *calrgb) -{ - ASSERT(calrgb); - - calrgb->white_point[0] = 1.0; - calrgb->white_point[1] = 1.0; - calrgb->white_point[2] = 1.0; - - calrgb->black_point[0] = 0.0; - calrgb->black_point[1] = 0.0; - calrgb->black_point[2] = 0.0; - - calrgb->gamma[0] = 1.0; - calrgb->gamma[1] = 1.0; - calrgb->gamma[2] = 1.0; - - calrgb->matrix[0] = 1.0; - calrgb->matrix[1] = 0.0; - calrgb->matrix[2] = 0.0; - - calrgb->matrix[3] = 0.0; - calrgb->matrix[4] = 1.0; - calrgb->matrix[5] = 0.0; - - calrgb->matrix[6] = 0.0; - calrgb->matrix[7] = 0.0; - calrgb->matrix[8] = 1.0; -} - -static int -valid_calrgb (struct calrgb_cdata *calrgb) -{ - if (calrgb->white_point[1] != 1.0 || - calrgb->white_point[0] <= 0.0 || - calrgb->white_point[2] <= 0.0) - return 0; - - if (calrgb->black_point[0] < 0.0 || - calrgb->black_point[1] < 0.0 || - calrgb->black_point[2] < 0.0) - return 0; - - if (calrgb->gamma[0] < 0.0 || - calrgb->gamma[1] < 0.0 || - calrgb->gamma[2] < 0.0) - return 0; - - /* matrix should be invertible? */ - - return 1; -} - -static pdf_obj * -pdf_color_make_calrgb_resource (struct calrgb_cdata *calrgb) -{ - pdf_obj *colorspace; - pdf_obj *calparams, *tmp_array; - - ASSERT(calrgb); - - if (!valid_calrgb(calrgb)) - return NULL; - - colorspace = pdf_new_array(); - calparams = pdf_new_dict(); - - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(1.0)); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("WhitePoint"), tmp_array); - - if (calrgb->black_point[0] != 0.0 || - calrgb->black_point[1] != 0.0 || - calrgb->black_point[2] != 0.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("BlackPoint"), tmp_array); - } - - if (calrgb->gamma[0] != 1.0 || - calrgb->gamma[1] != 1.0 || - calrgb->gamma[2] != 1.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("Gamma"), tmp_array); - } - - if (calrgb->matrix[0] != 1.0 || - calrgb->matrix[1] != 0.0 || - calrgb->matrix[2] != 0.0 || - calrgb->matrix[3] != 0.0 || - calrgb->matrix[4] != 1.0 || - calrgb->matrix[5] != 0.0 || - calrgb->matrix[6] != 0.0 || - calrgb->matrix[7] != 0.0 || - calrgb->matrix[8] != 1.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[2], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[3], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[4], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[5], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[6], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[7], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[8], 0.001))); - pdf_add_dict(calparams, pdf_new_name("Matrix"), tmp_array); - } - - pdf_add_array(colorspace, pdf_new_name("CalRGB")); - pdf_add_array(colorspace, calparams); - - return colorspace; -} -#endif - -static unsigned char nullbytes16[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static struct -{ - int major; - int minor; -} icc_versions[] = { - {0, 0}, /* PDF-1.0, we don't support them */ - {0, 0}, /* PDF-1.1, we don't support them */ - {0, 0}, /* PDF-1.2, we don't support them */ - {0x02, 0x10}, /* PDF-1.3 */ - {0x02, 0x20}, /* PDF-1.4 */ - {0x04, 0x00} /* PDF-1.5 */ -}; - -static int -iccp_version_supported (int major, int minor) -{ - int pdf_ver; - - pdf_ver = pdf_get_version(); - if (pdf_ver < 6) { - if (icc_versions[pdf_ver].major < major) - return 0; - else if (icc_versions[pdf_ver].major == major && - icc_versions[pdf_ver].minor < minor) - return 0; - else { - return 1; - } - } - - return 0; -} - -typedef unsigned long iccSig; -static iccSig -str2iccSig (const void *s) -{ - const char *p; - - p = (const char *) s; - - return (iccSig) ((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); -} - -typedef struct -{ - long X, Y, Z; /* s15Fixed16Numeber */ -} iccXYZNumber; - -typedef struct -{ - long size; - iccSig CMMType; - long version; - iccSig devClass; - iccSig colorSpace; - iccSig PCS; /* Profile Connection Space */ - char creationDate[12]; - iccSig acsp; - iccSig platform; - char flags[4]; - iccSig devMnfct; - iccSig devModel; - char devAttr[8]; - long intent; - iccXYZNumber illuminant; - iccSig creator; - unsigned char ID[16]; /* MD5 checksum with Rendering intent, - * Header attrs, Profile ID fields are - * set to zeros. - */ - /* 28 bytes reserved - must be set to zeros */ -} iccHeader; - -#define iccNullSig 0 -static void -iccp_init_iccHeader (iccHeader *icch) -{ - ASSERT(icch); - - icch->size = 0; - icch->CMMType = iccNullSig; - icch->version = 0xFFFFFF; - icch->devClass = iccNullSig; - icch->colorSpace = iccNullSig; - icch->PCS = iccNullSig; - memset(icch->creationDate, 0, 12); - icch->acsp = str2iccSig("ascp"); - icch->platform = iccNullSig; - memset(icch->flags, 0, 4); - icch->devMnfct = iccNullSig; - icch->devModel = iccNullSig; - memset(icch->devAttr, 0, 8); - icch->intent = 0; - icch->illuminant.X = 0; - icch->illuminant.Y = 0; - icch->illuminant.Z = 0; - icch->creator = iccNullSig; - memset(icch->ID, 0, 16); -} - -#define ICC_INTENT_TYPE(n) ((int) (((n) >> 16) & 0xff)) -#define ICC_INTENT_PERCEPTUAL 0 -#define ICC_INTENT_RELATIVE 1 -#define ICC_INTENT_SATURATION 2 -#define ICC_INTENT_ABSOLUTE 3 - -/* - * In ICC profile stream dicrionary, there is /Range whose values must - * "match the information in the profile". But where is those values in? - * - * How should I treat rendering intent? - */ -struct iccbased_cdata -{ - long sig; /* 'i' 'c' 'c' 'b' */ - - unsigned char checksum[16]; /* 16 bytes MD5 Checksum */ - int colorspace; /* input colorspace: - * RGB, Gray, CMYK, (Lab?) - */ - int alternate; /* alternate colorspace (id), unused */ -}; - -#define check_sig(d,p,q,r,s) ((d) && (d)->sig == ((p)<<24|(q)<<16|(r)<<8|(s))) - -static void -init_iccbased_cdata (struct iccbased_cdata *cdata) -{ - ASSERT(cdata); - - cdata->sig = ('i' << 24|'c' << 16|'c' << 8|'b'); - memset(cdata->checksum, 0, 16); - cdata->colorspace = PDF_COLORSPACE_TYPE_INVALID; - cdata->alternate = -1; - - return; -} - -static void -release_iccbased_cdata (struct iccbased_cdata *cdata) -{ - ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); - - RELEASE(cdata); -} - -static int -get_num_components_iccbased (const struct iccbased_cdata *cdata) -{ - int num_components = 0; - - ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); - - switch (cdata->colorspace) { - case PDF_COLORSPACE_TYPE_RGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_CMYK: - num_components = 4; - break; - case PDF_COLORSPACE_TYPE_GRAY: - num_components = 1; - break; - case PDF_COLORSPACE_TYPE_CIELAB: - num_components = 3; - break; - } - - return num_components; -} - -static int -compare_iccbased (const char *ident1, const struct iccbased_cdata *cdata1, - const char *ident2, const struct iccbased_cdata *cdata2) -{ - if (cdata1 && cdata2) { - - ASSERT(check_sig(cdata1, 'i', 'c', 'c', 'b')); - ASSERT(check_sig(cdata2, 'i', 'c', 'c', 'b')); - - if (memcmp(cdata1->checksum, nullbytes16, 16) && - memcmp(cdata2->checksum, nullbytes16, 16)) { - return memcmp(cdata1->checksum, cdata2->checksum, 16); - } - if (cdata1->colorspace != cdata2->colorspace) { - return (cdata1->colorspace - cdata2->colorspace); - } - - /* Continue if checksum unknown and colorspace is same. */ - } - - if (ident1 && ident2) - return strcmp(ident1, ident2); - - /* No way to compare */ - return -1; -} - -int -iccp_check_colorspace (int colortype, const void *profile, long proflen) -{ - iccSig colorspace; - const unsigned char *p; - - if (!profile || proflen < 128) - return -1; - - p = (const unsigned char *) profile; - - colorspace = str2iccSig(p + 16); - - switch (colortype) { - case PDF_COLORSPACE_TYPE_CALRGB: - case PDF_COLORSPACE_TYPE_RGB: - if (colorspace != str2iccSig("RGB ")) { - return -1; - } - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - case PDF_COLORSPACE_TYPE_GRAY: - if (colorspace != str2iccSig("GRAY")) { - return -1; - } - break; - case PDF_COLORSPACE_TYPE_CMYK: - if (colorspace != str2iccSig("CMYK")) { - return -1; - } - break; - default: - return -1; - break; - } - - return 0; -} - -pdf_obj * -iccp_get_rendering_intent (const void *profile, long proflen) -{ - pdf_obj *ri = NULL; - const unsigned char *p; - long intent; - - if (!profile || proflen < 128) - return NULL; - - p = (const unsigned char *) profile; - - intent = (p[64] << 24)|(p[65] << 16)|(p[66] << 8)|p[67]; - switch (ICC_INTENT_TYPE(intent)) { - case ICC_INTENT_SATURATION: - ri = pdf_new_name("Saturation"); - break; - case ICC_INTENT_PERCEPTUAL: - ri = pdf_new_name("Perceptual"); - break; - case ICC_INTENT_ABSOLUTE: - ri = pdf_new_name("AbsoluteColorimetric"); - break; - case ICC_INTENT_RELATIVE: - ri = pdf_new_name("RelativeColorimetric"); - break; - default: - WARN("Invalid rendering intent type: %d", ICC_INTENT_TYPE(intent)); - ri = NULL; - } - - return ri; -} - -#define sget_signed_long(p) ((long) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) -#define sget_signed_short(p) ((short) ((p)[0] << 8|(p)[1])) -#define get_iccSig(p) ((iccSig) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) - -static int -iccp_unpack_header (iccHeader *icch, - const void *profile, long proflen, int check_size) -{ - const unsigned char *p, *endptr; - - if (check_size) { - if (!profile || proflen < 128 || - proflen % 4 != 0) { - WARN("Profile size: %ld", proflen); - return -1; - } - } - - p = (const unsigned char *) profile; - endptr = p + 128; - - icch->size = sget_signed_long(p); - if (check_size) { - if (icch->size != proflen) { - WARN("ICC Profile size: %ld(header) != %ld", icch->size, proflen); - return -1; - } - } - p += 4; - - icch->CMMType = str2iccSig(p); - p += 4; - icch->version = sget_signed_long(p); - p += 4; - icch->devClass = str2iccSig(p); - p += 4; - icch->colorSpace = str2iccSig(p); - p += 4; - icch->PCS = str2iccSig(p); - p += 4; - memcpy(icch->creationDate, p, 12); - p += 12; - icch->acsp = str2iccSig(p); /* acsp */ - if (icch->acsp != str2iccSig("acsp")) { - WARN("Invalid ICC profile: not \"acsp\" - %c%c%c%c ", - p[0], p[1], p[2], p[3]); - return -1; - } - p += 4; - icch->platform = str2iccSig(p); - p += 4; - memcpy(icch->flags, p, 4); - p += 4; - icch->devMnfct = str2iccSig(p); - p += 4; - icch->devModel = str2iccSig(p); - p += 4; - memcpy(icch->devAttr, p, 8); - p += 8; - icch->intent = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; - p += 4; - icch->illuminant.X = sget_signed_long(p); - p += 4; - icch->illuminant.Y = sget_signed_long(p); - p += 4; - icch->illuminant.Z = sget_signed_long(p); - p += 4; - icch->creator = str2iccSig(p); - p += 4; - memcpy(icch->ID, p, 16); - p += 16; - - /* 28 bytes reserved - must be set to zeros */ - for (; p < endptr; p++) { - if (*p != '\0') { - WARN("Reserved pad not zero: %02x (at offset %ld in ICC profile header.)", - *p, 128 - ((long) (endptr - p))); - return -1; - } - } - - return 0; -} - -/* MD5 checksum with Rendering intent, - * Header attrs, Profile ID fields are - * set to zeros. - */ -#define ICC_HEAD_SECT1_START 0 -#define ICC_HEAD_SECT1_LENGTH 56 -/* 8 bytes devAttr, 4 bytes intent */ -#define ICC_HEAD_SECT2_START 68 -#define ICC_HEAD_SECT2_LENGTH 16 -/* 16 bytes ID (checksum) */ -#define ICC_HEAD_SECT3_START 100 -#define ICC_HEAD_SECT3_LENGTH 28 - -#include "dpxcrypt.h" -static void -iccp_get_checksum (unsigned char *checksum, const void *profile, long proflen) -{ - const unsigned char *p; - MD5_CONTEXT md5; - - p = (const unsigned char *) profile; - - MD5_init (&md5); - MD5_write(&md5, p + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); - MD5_write(&md5, nullbytes16, 12); - MD5_write(&md5, p + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); - MD5_write(&md5, nullbytes16, 16); - MD5_write(&md5, p + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); - - /* body */ - MD5_write(&md5, p + 128, proflen - 128); - - MD5_final(checksum, &md5); -} - -static void -print_iccp_header (iccHeader *icch, unsigned char *checksum) -{ - int i; - - ASSERT(icch); - -#define print_iccSig(s,t) if ((s) == 0) {\ - MESG("pdf_color>> %s:\t(null)\n", (t)); \ - } else if (!isprint(((s) >> 24) & 0xff) || \ - !isprint(((s) >> 16) & 0xff) || \ - !isprint(((s) >> 8) & 0xff) || \ - !isprint((s) & 0xff)) { \ - MESG("pdf_color>> %s:\t(invalid)\n", (t)); \ - } else { \ - MESG("pdf_color>> %s:\t%c%c%c%c\n", (t), \ - ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, \ - ((s) >> 8) & 0xff, (s) & 0xff); \ -} - - MESG("\n"); - MESG("pdf_color>> ICC Profile Info\n"); - MESG("pdf_color>> Profile Size:\t%ld bytes\n", icch->size); - print_iccSig(icch->CMMType, "CMM Type"); - MESG("pdf_color>> Profile Version:\t%d.%01d.%01d\n", - (icch->version >> 24) & 0xff, - (icch->version >> 20) & 0x0f, - (icch->version >> 16) & 0x0f); - print_iccSig(icch->devClass, "Device Class"); - print_iccSig(icch->colorSpace, "Color Space"); - print_iccSig(icch->PCS, "Connection Space"); - MESG("pdf_color>> Creation Date:\t"); - for (i = 0; i < 12; i += 2) { - if (i == 0) - MESG("%04u", - sget_unsigned_pair((unsigned char *) icch->creationDate)); - else { - MESG(":%02u", - sget_unsigned_pair((unsigned char *) (&icch->creationDate[i]))); - } - } - MESG("\n"); - print_iccSig(icch->platform, "Primary Platform"); - MESG("pdf_color>> Profile Flags:\t%02x:%02x:%02x:%02x\n", - icch->flags[0], icch->flags[1], icch->flags[2], icch->flags[3]); - print_iccSig(icch->devMnfct, "Device Mnfct"); - print_iccSig(icch->devModel, "Device Model"); - MESG("pdf_color>> Device Attr:\t"); - for (i = 0; i < 8; i++) { - if (i == 0) - MESG("%02x", icch->devAttr[i]); - else - MESG(":%02x", icch->devAttr[i]); - } - MESG("\n"); - MESG("pdf_color>> Rendering Intent:\t"); - switch (ICC_INTENT_TYPE(icch->intent)) { - case ICC_INTENT_SATURATION: - MESG("Saturation"); - break; - case ICC_INTENT_PERCEPTUAL: - MESG("Perceptual"); - break; - case ICC_INTENT_ABSOLUTE: - MESG("Absolute Colorimetric"); - break; - case ICC_INTENT_RELATIVE: - MESG("Relative Colorimetric"); - break; - default: - MESG("(invalid)"); - break; - } - MESG("\n"); - print_iccSig(icch->creator, "Creator"); - MESG("pdf_color>> Illuminant (XYZ):\t"); - MESG("%.3f %.3f %.3f\n", - (double) icch->illuminant.X / 0x10000, - (double) icch->illuminant.Y / 0x10000, - (double) icch->illuminant.Z / 0x10000); - MESG("pdf_color>> Checksum:\t"); - if (!memcmp(icch->ID, nullbytes16, 16)) { - MESG("(null)"); - } else { - for (i = 0; i < 16; i++) { - if (i == 0) - MESG("%02x", icch->ID[i]); - else - MESG(":%02x", icch->ID[i]); - } - } - MESG("\n"); - if (checksum) { - MESG("pdf_color>> Calculated:\t"); - for (i = 0; i < 16; i++) { - if (i == 0) - MESG("%02x", checksum[i]); - else - MESG(":%02x", checksum[i]); - } - MESG("\n"); - } - - return; -} - - -static int -iccp_devClass_allowed (int dev_class) -{ - int colormode; - - colormode = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - - switch (colormode) { -#if 0 - case PDF_DEV_COLORMODE_PDFX1: - break; - case PDF_DEV_COLORMODE_PDFX3: - if (dev_class != str2iccSig("prtr")) { - return 0; - } - break; -#endif - default: - if (dev_class != str2iccSig("scnr") && - dev_class != str2iccSig("mntr") && - dev_class != str2iccSig("prtr") && - dev_class != str2iccSig("spac")) { - return 0; - } - break; - } - - - return 1; -} - -int -iccp_load_profile (const char *ident, - const void *profile, long proflen) -{ - int cspc_id; - pdf_obj *resource; - pdf_obj *stream; - pdf_obj *stream_dict; - iccHeader icch; - int colorspace; - unsigned char checksum[16]; - struct iccbased_cdata *cdata; - - iccp_init_iccHeader(&icch); - if (iccp_unpack_header(&icch, profile, proflen, 1) < 0) { /* check size */ - WARN("Invalid ICC profile header in \"%s\"", ident); - print_iccp_header(&icch, NULL); - return -1; - } - - if (!iccp_version_supported((icch.version >> 24) & 0xff, - (icch.version >> 16) & 0xff)) { - WARN("ICC profile format spec. version %d.%01d.%01d" - " not supported in current PDF version setting.", - (icch.version >> 24) & 0xff, - (icch.version >> 20) & 0x0f, - (icch.version >> 16) & 0x0f); - WARN("ICC profile not embedded."); - print_iccp_header(&icch, NULL); - return -1; - } - - if (!iccp_devClass_allowed(icch.devClass)) { - WARN("Unsupported ICC Profile Device Class:"); - print_iccp_header(&icch, NULL); - return -1; - } - - if (icch.colorSpace == str2iccSig("RGB ")) { - colorspace = PDF_COLORSPACE_TYPE_RGB; - } else if (icch.colorSpace == str2iccSig("GRAY")) { - colorspace = PDF_COLORSPACE_TYPE_GRAY; - } else if (icch.colorSpace == str2iccSig("CMYK")) { - colorspace = PDF_COLORSPACE_TYPE_CMYK; - } else { - WARN("Unsupported input color space."); - print_iccp_header(&icch, NULL); - return -1; - } - - iccp_get_checksum(checksum, profile, proflen); - if (memcmp(icch.ID, nullbytes16, 16) && - memcmp(icch.ID, checksum, 16)) { - WARN("Invalid ICC profile: Inconsistent checksum."); - print_iccp_header(&icch, checksum); - return -1; - } - - cdata = NEW(1, struct iccbased_cdata); - init_iccbased_cdata(cdata); - cdata->colorspace = colorspace; - memcpy(cdata->checksum, checksum, 16); - - cspc_id = pdf_colorspace_findresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, cdata); - if (cspc_id >= 0) { - if (verbose) - MESG("(ICCP:[id=%d])", cspc_id); - release_iccbased_cdata(cdata); - return cspc_id; - } - if (verbose > 1) { - print_iccp_header(&icch, checksum); - } - - resource = pdf_new_array(); - - stream = pdf_new_stream(STREAM_COMPRESS); - pdf_add_array(resource, pdf_new_name("ICCBased")); - pdf_add_array(resource, pdf_ref_obj (stream)); - - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, pdf_new_name("N"), - pdf_new_number(get_num_components_iccbased(cdata))); - - pdf_add_stream (stream, profile, proflen); - pdf_release_obj(stream); - - cspc_id = pdf_colorspace_defineresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, - cdata, resource); - - return cspc_id; -} - -#ifdef XETEX -#define WBUF_SIZE 4096 -static unsigned char wbuf[WBUF_SIZE]; - -static pdf_obj * -iccp_load_file_stream (unsigned char *checksum, long length, FILE *fp) -{ - pdf_obj *stream; - MD5_CONTEXT md5; - long nb_read; - - rewind(fp); - - if (fread(wbuf, 1, 128, fp) != 128) { - return NULL; - } - length -= 128; - - stream = pdf_new_stream(STREAM_COMPRESS); - - MD5_init (&md5); - MD5_write(&md5, wbuf + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); - MD5_write(&md5, nullbytes16, 12); - MD5_write(&md5, wbuf + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); - MD5_write(&md5, nullbytes16, 16); - MD5_write(&md5, wbuf + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); - - pdf_add_stream(stream, wbuf, 128); - - /* body */ - while (length > 0) { - nb_read = fread(wbuf, 1, MIN(length, WBUF_SIZE), fp); - MD5_write(&md5, wbuf, nb_read); - pdf_add_stream(stream, wbuf, nb_read); - length -= nb_read; - } - - MD5_final(checksum, &md5); - - - return stream; -} - -int -pdf_colorspace_load_ICCBased (const char *ident, const char *filename) -{ - int cspc_id; - FILE *fp; - pdf_obj *resource; - pdf_obj *stream; - pdf_obj *stream_dict; - iccHeader icch; - int colorspace; - long size; - unsigned char checksum[16]; - struct iccbased_cdata *cdata; - - - fp = DPXFOPEN(filename, DPX_RES_TYPE_ICCPROFILE); - if (!fp) - return -1; - - size = file_size(fp); - if (size < 128) { - MFCLOSE(fp); - return -1; - } - if (fread(wbuf, 1, 128, fp) != 128) { - DPXFCLOSE(fp); - return -1; - } - - iccp_init_iccHeader(&icch); - if (iccp_unpack_header(&icch, wbuf, 128, 0) < 0) { - WARN("Invalid ICC profile header in \"%s\"", ident); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - if (icch.size > size) { - WARN("File size smaller than recorded in header: %ld %ld", - icch.size, size); - DPXFCLOSE(fp); - return -1; - } - - if (!iccp_version_supported((icch.version >> 24) & 0xff, - (icch.version >> 16) & 0xff)) { - WARN("ICC profile format spec. version %d.%01d.%01d" - " not supported in current PDF version setting.", - (icch.version >> 24) & 0xff, - (icch.version >> 20) & 0x0f, - (icch.version >> 16) & 0x0f); - WARN("ICC profile not embedded."); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - if (!iccp_devClass_allowed(icch.devClass)) { - WARN("Unsupported ICC Profile Device Class:"); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - if (icch.colorSpace == str2iccSig("RGB ")) { - colorspace = PDF_COLORSPACE_TYPE_RGB; - } else if (icch.colorSpace == str2iccSig("GRAY")) { - colorspace = PDF_COLORSPACE_TYPE_GRAY; - } else if (icch.colorSpace == str2iccSig("CMYK")) { - colorspace = PDF_COLORSPACE_TYPE_CMYK; - } else { - WARN("Unsupported input color space."); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - stream = iccp_load_file_stream(checksum, icch.size, fp); - DPXFCLOSE(fp); - - if (!stream) { - WARN("Loading ICC Profile failed...: %s", filename); - return -1; - } - - if (memcmp(icch.ID, nullbytes16, 16) && - memcmp(icch.ID, checksum, 16)) { - WARN("Invalid ICC profile: Inconsistent checksum."); - print_iccp_header(&icch, NULL); - pdf_release_obj(stream); - return -1; - } - - cdata = NEW(1, struct iccbased_cdata); - init_iccbased_cdata(cdata); - cdata->colorspace = colorspace; - memcpy(cdata->checksum, checksum, 16); - - cspc_id = pdf_colorspace_findresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, cdata); - if (cspc_id >= 0) { - if (verbose) - MESG("(ICCP:[id=%d])", cspc_id); - release_iccbased_cdata(cdata); - pdf_release_obj(stream); - return cspc_id; - } - if (verbose > 1) { - print_iccp_header(&icch, checksum); - } - - resource = pdf_new_array(); - - pdf_add_array(resource, pdf_new_name("ICCBased")); - pdf_add_array(resource, pdf_ref_obj (stream)); - - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, pdf_new_name("N"), - pdf_new_number(get_num_components_iccbased(cdata))); - pdf_release_obj(stream); - - cspc_id = pdf_colorspace_defineresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, - cdata, resource); - - return cspc_id; -} -#endif - -typedef struct { - char *ident; - int subtype; - - pdf_obj *resource; - pdf_obj *reference; - - void *cdata; -} pdf_colorspace; - -static struct { - int count; - int capacity; - pdf_colorspace *colorspaces; -} cspc_cache = { - 0, 0, NULL -}; - -int -pdf_colorspace_findresource (const char *ident, - int type, const void *cdata) -{ - pdf_colorspace *colorspace; - int cspc_id, cmp = -1; - - for (cspc_id = 0; - cmp && cspc_id < cspc_cache.count; cspc_id++) { - colorspace = &cspc_cache.colorspaces[cspc_id]; - if (colorspace->subtype != type) - continue; - - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - cmp = compare_iccbased(ident, cdata, - colorspace->ident, colorspace->cdata); - break; - } - if (!cmp) - return cspc_id; - } - - return -1; /* not found */ -} - -static void -pdf_init_colorspace_struct (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - colorspace->ident = NULL; - colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; - - colorspace->resource = NULL; - colorspace->reference = NULL; - colorspace->cdata = NULL; - - return; -} - -static void -pdf_clean_colorspace_struct (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - if (colorspace->ident) - RELEASE(colorspace->ident); - if (colorspace->resource) - pdf_release_obj(colorspace->resource); - if (colorspace->reference) - pdf_release_obj(colorspace->reference); - colorspace->resource = NULL; - colorspace->reference = NULL; - - if (colorspace->cdata) { - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - release_iccbased_cdata(colorspace->cdata); - break; - } - } - colorspace->cdata = NULL; - colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; - - return; -} - -static void -pdf_flush_colorspace (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - if (colorspace->resource) - pdf_release_obj(colorspace->resource); - if (colorspace->reference) - pdf_release_obj(colorspace->reference); - - colorspace->resource = NULL; - colorspace->reference = NULL; -} - -int -pdf_colorspace_defineresource (const char *ident, - int subtype, void *cdata, pdf_obj *resource) -{ - int cspc_id; - pdf_colorspace *colorspace; - - if (cspc_cache.count >= cspc_cache.capacity) { - cspc_cache.capacity += 16; - cspc_cache.colorspaces = RENEW(cspc_cache.colorspaces, - cspc_cache.capacity, pdf_colorspace); - } - cspc_id = cspc_cache.count; - colorspace = &cspc_cache.colorspaces[cspc_id]; - - pdf_init_colorspace_struct(colorspace); - if (ident) { - colorspace->ident = NEW(strlen(ident) + 1, char); - strcpy(colorspace->ident, ident); - } - colorspace->subtype = subtype; - colorspace->cdata = cdata; - colorspace->resource = resource; - - if (verbose) { - MESG("(ColorSpace:%s", ident); - if (verbose > 1) { - switch (subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - MESG("[ICCBased]"); - break; - case PDF_COLORSPACE_TYPE_CALRGB: - MESG("[CalRGB]"); - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - MESG("[CalGray]"); - break; - } - } - MESG(")"); - } - - cspc_cache.count++; - - return cspc_id; -} - -pdf_obj * -pdf_get_colorspace_reference (int cspc_id) -{ - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - if (!colorspace->reference) { - colorspace->reference = pdf_ref_obj(colorspace->resource); - pdf_release_obj(colorspace->resource); /* .... */ - colorspace->resource = NULL; - } - - return pdf_link_obj(colorspace->reference); -} - -#if 0 -int -pdf_get_colorspace_num_components (int cspc_id) -{ - pdf_colorspace *colorspace; - int num_components; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - num_components = get_num_components_iccbased(colorspace->cdata); - break; - case PDF_COLORSPACE_TYPE_DEVICEGRAY: - num_components = 1; - break; - case PDF_COLORSPACE_TYPE_DEVICERGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_DEVICECMYK: - num_components = 4; - break; - case PDF_COLORSPACE_TYPE_CALRGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - num_components = 1; - break; - default: - num_components = 0; - break; - } - - return num_components; -} - -int -pdf_get_colorspace_subtype (int cspc_id) -{ - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - - return colorspace->subtype; -} -#endif - -void -pdf_init_colors (void) -{ - cspc_cache.count = 0; - cspc_cache.capacity = 0; - cspc_cache.colorspaces = NULL; -} - -void -pdf_close_colors (void) -{ - int i; - - for (i = 0; i < cspc_cache.count; i++) { - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[i]; - pdf_flush_colorspace(colorspace); - pdf_clean_colorspace_struct(colorspace); - } - RELEASE(cspc_cache.colorspaces); - cspc_cache.colorspaces = NULL; - cspc_cache.count = cspc_cache.capacity = 0; - -} - -#define PDF_COLORSPACE_FAMILY_DEVICE 0 -#define PDF_COLORSPACE_FAMILY_CIEBASED 1 -#define PDF_COLORSPACE_FAMILY_SPECIAL 2 diff --git a/Build/source/texk/dvipdfm-x/src/pdfdev.c b/Build/source/texk/dvipdfm-x/src/pdfdev.c deleted file mode 100644 index f68da6247bc..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfdev.c +++ /dev/null @@ -1,2015 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "mfileio.h" -#include "numbers.h" - -#include "pdfdoc.h" -#include "pdfobj.h" - -#include "pdffont.h" -#include "fontmap.h" -#include "cmap.h" -#include "pdfximage.h" - -#include "pdfdraw.h" -#include "pdfcolor.h" - -#include "pdflimits.h" - -#include "pdfdev.h" - -static int verbose = 0; - -void -pdf_dev_set_verbose (void) -{ - verbose++; -} - -/* Not working yet... */ -double -pdf_dev_scale (void) -{ - return 1.0; -} - -/* - * Unit conversion, formatting and others. - */ - -#define TEX_ONE_HUNDRED_BP 6578176 -static struct { - double dvi2pts; - long min_bp_val; /* Shortest resolvable distance in the output PDF. */ - int precision; /* Number of decimal digits (in fractional part) kept. */ -} dev_unit = { - 0.0, - 658, - 2 -}; - - -double -dev_unit_dviunit (void) -{ - return (1.0/dev_unit.dvi2pts); -} - -#define DEV_PRECISION_MAX 8 -static unsigned long ten_pow[10] = { - 1ul, 10ul, 100ul, 1000ul, 10000ul, 100000ul, 1000000ul, 10000000ul, 100000000ul, 1000000000ul -}; - -static double ten_pow_inv[10] = { - 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001 -}; - -#define bpt2spt(b) ( (spt_t) round( (b) / dev_unit.dvi2pts ) ) -#define spt2bpt(s) ( (s) * dev_unit.dvi2pts ) -#define dround_at(v,p) (ROUND( (v), ten_pow_inv[(p)] )) - -static int -p_itoa (long value, char *buf) -{ - int sign, ndigits; - char *p = buf; - - if (value < 0) { - *p++ = '-'; - value = -value; - sign = 1; - } else { - sign = 0; - } - - ndigits = 0; - /* Generate at least one digit in reverse order */ - do { - p[ndigits++] = (value % 10) + '0'; - value /= 10; - } while (value != 0); - - /* Reverse the digits */ - { - int i; - - for (i = 0; i < ndigits / 2 ; i++) { - char tmp = p[i]; - p[i] = p[ndigits-i-1]; - p[ndigits-i-1] = tmp; - } - } - p[ndigits] = '\0'; - - return (sign ? ndigits + 1 : ndigits); -} - -/* ... */ -static int -p_dtoa (double value, int prec, char *buf) -{ - const long p[10] = { 1, 10, 100, 1000, 10000, - 100000, 1000000, 10000000, 100000000, 1000000000 }; - long i, f; - char *c = buf; - int n; - - if (value < 0) { - value = -value; - *c++ = '-'; - n = 1; - } else - n = 0; - - i = (long) value; - f = (long) ((value-i)*p[prec] + 0.5); - - if (f == p[prec]) { - f = 0; - i++; - } - - if (i) { - int m = p_itoa(i, c); - c += m; - n += m; - } else if (!f) { - *(c = buf) = '0'; - n = 1; - } - - if (f) { - int j = prec; - - *c++ = '.'; - - while (j--) { - c[j] = (f % 10) + '0'; - f /= 10; - } - c += prec-1; - n += 1+prec; - - while (*c == '0') { - c--; - n--; - } - } - - *(++c) = 0; - - return n; -} - -static int -dev_sprint_bp (char *buf, spt_t value, spt_t *error) -{ - double value_in_bp; - double error_in_bp; - int prec = dev_unit.precision; - - value_in_bp = spt2bpt(value); - if (error) { - error_in_bp = value_in_bp - dround_at(value_in_bp, prec); - *error = bpt2spt(error_in_bp); - } - - return p_dtoa(value_in_bp, prec, buf); -} - -/* They are affected by precision (set at device initialization). */ -int -pdf_sprint_matrix (char *buf, const pdf_tmatrix *M) -{ - int len; - int prec2 = MIN(dev_unit.precision + 2, DEV_PRECISION_MAX); - int prec0 = MAX(dev_unit.precision, 2); - - len = p_dtoa(M->a, prec2, buf); - buf[len++] = ' '; - len += p_dtoa(M->b, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->c, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->d, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->e, prec0, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->f, prec0, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_rect (char *buf, const pdf_rect *rect) -{ - int len; - - len = p_dtoa(rect->llx, dev_unit.precision, buf); - buf[len++] = ' '; - len += p_dtoa(rect->lly, dev_unit.precision, buf+len); - buf[len++] = ' '; - len += p_dtoa(rect->urx, dev_unit.precision, buf+len); - buf[len++] = ' '; - len += p_dtoa(rect->ury, dev_unit.precision, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_coord (char *buf, const pdf_coord *p) -{ - int len; - - len = p_dtoa(p->x, dev_unit.precision, buf); - buf[len++] = ' '; - len += p_dtoa(p->y, dev_unit.precision, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_length (char *buf, double value) -{ - int len; - - len = p_dtoa(value, dev_unit.precision, buf); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - - -int -pdf_sprint_number (char *buf, double value) -{ - int len; - - len = p_dtoa(value, DEV_PRECISION_MAX, buf); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - - -static struct -{ - /* Text composition (direction) mode is ignored (always same - * as font's writing mode) if autorotate is unset (value zero). - */ - int autorotate; - - /* - * Ignore color migrated to here. This is device's capacity. - * colormode 0 for ignore colors - */ - int colormode; - -} dev_param = { - 1, /* autorotate */ - 1, /* colormode */ -}; - -/* - * Text handling routines. - */ - -/* Motion state: - * GRAPHICS_MODE Initial state (not within BT/ET block nor in string) - * TEXT_MODE Text section is started via BT operator but not - * in string. - * STRING_MODE In string. A string or array of strings are currently - * in process. May started '[', '<' or '('. - */ -#define GRAPHICS_MODE 1 -#define TEXT_MODE 2 -#define STRING_MODE 3 - -static int motion_state = GRAPHICS_MODE; - -#define FORMAT_BUF_SIZE 4096 -static char format_buffer[FORMAT_BUF_SIZE]; - -/* - * In PDF, vertical text positioning is always applied when current font - * is vertical font. While ASCII pTeX manages current writing direction - * and font's WMode separately. - * - * 000/101 WMODE_HH/VV h(v) font, h(v) direction. - * 001 WMODE_HV -90 deg. rotated - * 100 WMODE_VH +90 deg. rotated - * 011 WMODE_HD +90 deg. rotated - * 111 WMODE_VD 180 deg. rotated - - * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode - * is applied. - */ -#define TEXT_WMODE_HH 0 -#define TEXT_WMODE_HV 1 -#define TEXT_WMODE_VH 4 -#define TEXT_WMODE_VV 5 -#define TEXT_WMODE_HD 3 -#define TEXT_WMODE_VD 7 - -#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 5) == 0 ? 0 : 1) -#define ROTATE_TEXT(m) ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV) - -static struct { - - /* Current font. - * This is index within dev_fonts. - */ - int font_id; - - /* Dvipdfmx does compression of text by doing text positioning - * in relative motion and uses string array [(foo) -250 (bar)] - * with kerning (negative kern is used for white space as suited - * for TeX). This is offset within current string. - */ - spt_t offset; - - /* This is reference point of strings. - * It may include error correction induced by rounding. - */ - spt_t ref_x; - spt_t ref_y; - - /* Using text raise and leading is highly recommended for - * text extraction to work properly. But not implemented yet. - * We can't do consice output for \TeX without this. - */ - spt_t raise; /* unused */ - spt_t leading; /* unused */ - - /* This is not always text matrix but rather font matrix. - * We do not use horizontal scaling in PDF text state parameter - * since they always apply scaling in fixed direction regardless - * of writing mode. - */ - struct { - double slant; - double extend; - int rotate; /* TEXT_WMODE_XX */ - } matrix; - - /* Fake bold parameter: - * If bold_param is positive, use text rendering mode - * fill-then-stroke with stroking line width specified - * by bold_param. - */ - double bold_param; - - /* Text composition (direction) mode. */ - int dir_mode; - - /* internal */ - - /* Flag indicating text matrix to be forcibly reset. - * Enabled if synthetic font features (slant, extend, etc) - * are used for current font or when text rotation mode - * changes. - */ - int force_reset; - - /* This information is duplicated from dev[font_id].format. - * Set to 1 if font is composite (Type0) font. - */ - int is_mb; -} text_state = { - -1, /* font */ - 0, /* offset */ - 0, 0, /* ref_x, ref_y */ - 0, 0, /* raise, leading */ - {0.0, 1.0, 0}, - - 0.0, /* Experimental boldness param */ - - 0, /* dir_mode */ - - /* internal */ - 0, /* force_reset */ - 0 /* is_mb */ -}; - -#define PDF_FONTTYPE_SIMPLE 1 -#define PDF_FONTTYPE_BITMAP 2 -#define PDF_FONTTYPE_COMPOSITE 3 - -struct dev_font { - /* Needs to be big enough to hold name "Fxxx" - * where xxx is number of largest font - */ - char short_name[7]; /* Resource name */ - int used_on_this_page; - - char *tex_name; /* String identifier of this font */ - spt_t sptsize; /* Point size */ - - /* Returned values from font/encoding layer: - * - * The font_id and enc_id is font and encoding (CMap) identifier - * used in pdf_font or encoding/cmap layer. - * The PDF object "resource" is an indirect reference object - * pointing font resource of this font. The used_chars is somewhat - * misleading, this is actually used_glyphs in CIDFont for Type0 - * and is 65536/8 bytes binary data with each bits representing - * whether the glyph is in-use or not. It is 256 char array for - * simple font. - */ - int font_id; - int enc_id; -#ifdef XETEX - unsigned short *ft_to_gid; - - /* if >= 0, index of a dev_font that really has the resource and used_chars */ - int real_font_index; -#endif - - pdf_obj *resource; - char *used_chars; - - /* Font format: - * simple, composite or bitmap. - */ - int format; - - /* Writing mode: - * Non-zero for vertical. Duplicated from CMap. - */ - int wmode; - - /* Syntetic Font: - * - * We use text matrix for creating extended or slanted font, - * but not with font's FontMatrix since TrueType and Type0 - * font don't support them. - */ - double extend; - double slant; - double bold; /* Boldness prameter */ - - /* Compatibility */ - int mapc; /* Nasty workaround for Omega */ - - /* There are no font metric format supporting four-bytes - * charcter code. So we should provide an option to specify - * UCS group and plane. - */ - int ucs_group; - int ucs_plane; - - int is_unicode; -}; -static struct dev_font *dev_fonts = NULL; - -static int num_dev_fonts = 0; -static int max_dev_fonts = 0; -static int num_phys_fonts = 0; - -#define CURRENTFONT() ((text_state.font_id < 0) ? NULL : &(dev_fonts[text_state.font_id])) -#define GET_FONT(n) (&(dev_fonts[(n)])) - - -static void -dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - pdf_tmatrix tm; - int len = 0; - - /* slant is negated for vertical font so that right-side - * is always lower. */ - switch (rotate) { - case TEXT_WMODE_VH: - /* Vertical font */ - tm.a = slant ; tm.b = 1.0; - tm.c = -extend; tm.d = 0.0 ; - break; - case TEXT_WMODE_HV: - /* Horizontal font */ - tm.a = 0.0; tm.b = -extend; - tm.c = 1.0; tm.d = -slant ; - break; - case TEXT_WMODE_HH: - /* Horizontal font */ - tm.a = extend; tm.b = 0.0; - tm.c = slant ; tm.d = 1.0; - break; - case TEXT_WMODE_VV: - /* Vertical font */ - tm.a = 1.0; tm.b = -slant; - tm.c = 0.0; tm.d = extend; - break; - case TEXT_WMODE_HD: - /* Horizontal font */ - tm.a = 0.0; tm.b = extend; - tm.c = -1.0; tm.d = slant ; - break; - case TEXT_WMODE_VD: - /* Vertical font */ - tm.a = -1.0; tm.b = slant; - tm.c = 0.0; tm.d = -extend; - break; - } - tm.e = xpos * dev_unit.dvi2pts; - tm.f = ypos * dev_unit.dvi2pts; - - format_buffer[len++] = ' '; - len += pdf_sprint_matrix(format_buffer+len, &tm); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'm'; - - pdf_doc_add_page_content(format_buffer, len); /* op: Tm */ - - text_state.ref_x = xpos; - text_state.ref_y = ypos; - text_state.matrix.slant = slant; - text_state.matrix.extend = extend; - text_state.matrix.rotate = rotate; -} - -/* - * reset_text_state() outputs a BT and does any necessary coordinate - * transformations to get ready to ship out text. - */ - -static void -reset_text_state (void) -{ - /* - * We need to reset the line matrix to handle slanted fonts. - */ - pdf_doc_add_page_content(" BT", 3); /* op: BT */ - /* - * text_state.matrix is identity at top of page. - * This sometimes write unnecessary "Tm"s when transition from - * GRAPHICS_MODE to TEXT_MODE occurs. - */ - if (text_state.force_reset || - text_state.matrix.slant != 0.0 || - text_state.matrix.extend != 1.0 || - ROTATE_TEXT(text_state.matrix.rotate)) { - dev_set_text_matrix(0, 0, - text_state.matrix.slant, - text_state.matrix.extend, - text_state.matrix.rotate); - } - text_state.ref_x = 0; - text_state.ref_y = 0; - text_state.offset = 0; - text_state.force_reset = 0; -} - -static void -text_mode (void) -{ - switch (motion_state) { - case TEXT_MODE: - break; - case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ - break; - case GRAPHICS_MODE: - reset_text_state(); - break; - } - motion_state = TEXT_MODE; - text_state.offset = 0; -} - -void -graphics_mode (void) -{ - switch (motion_state) { - case GRAPHICS_MODE: - break; - case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ - /* continue */ - case TEXT_MODE: - pdf_doc_add_page_content(" ET", 3); /* op: ET */ - text_state.force_reset = 0; - text_state.font_id = -1; - break; - } - motion_state = GRAPHICS_MODE; -} - -static void -start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - spt_t delx, dely, error_delx, error_dely; - spt_t desired_delx, desired_dely; - int len = 0; - - delx = xpos - text_state.ref_x; - dely = ypos - text_state.ref_y; - /* - * Precompensating for line transformation matrix. - * - * Line transformation matrix L for horizontal font in horizontal - * mode and it's inverse I is - * - * | e 0| | 1/e 0| - * L_hh = | | , I_hh = | | - * | s 1| |-s/e 1| - * - * For vertical font in vertical mode, - * - * | 1 -s| | 1 s/e| - * L_vv = | | , I_vv = | | - * | 0 e| | 0 1/e| - * - * For vertical font in horizontal mode, - * - * | s 1| | 0 1| - * L_vh = | | = L_vv x | | - * |-e 0| |-1 0| - * - * | 0 -1| - * I_vh = | | x I_vv - * | 1 0| - * - * For horizontal font in vertical mode, - * - * | 0 -e| | 0 -1| - * L_hv = | | = L_hh x | | - * | 1 -s| | 1 0| - * - * | 0 1| - * I_hv = | | x I_hh - * |-1 0| - * - */ - switch (rotate) { - case TEXT_WMODE_VH: - /* Vertical font in horizontal mode: rot = +90 - * | 0 -1/e| - * d_user = d x I_vh = d x | | - * | 1 s/e| - */ - desired_delx = dely; - desired_dely = (spt_t) (-(delx - dely*slant)/extend); - - /* error_del is in device space - * - * | 0 1| - * e = e_user x | | = (-e_user_y, e_user_x) - * |-1 0| - * - * We must care about rotation here but not extend/slant... - * The extend and slant actually is font matrix. - */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); - error_delx = -error_delx; - break; - case TEXT_WMODE_HV: - /* Horizontal font in vertical mode: rot = -90 - * - * |-s/e 1| - * d_user = d x I_hv = d x | | - * |-1/e 0| - */ - desired_delx = (spt_t)(-(dely + delx*slant)/extend); - desired_dely = delx; - - /* - * e = (e_user_y, -e_user_x) - */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); - error_dely = -error_dely; - break; - case TEXT_WMODE_HH: - /* Horizontal font in horizontal mode: - * | 1/e 0| - * d_user = d x I_hh = d x | | - * |-s/e 1| - */ - desired_delx = (spt_t)((delx - dely*slant)/extend); - desired_dely = dely; - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); - break; - case TEXT_WMODE_VV: - /* Vertical font in vertical mode: - * | 1 s/e| - * d_user = d x I_vv = d x | | - * | 0 1/e| - */ - desired_delx = delx; - desired_dely = (spt_t)((dely + delx*slant)/extend); - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); - break; - case TEXT_WMODE_HD: - /* Horizontal font in down-to-up mode: rot = +90 - * - * | s/e -1| - * d_user = d x -I_hv = d x | | - * | 1/e 0| - */ - desired_delx = -(spt_t)(-(dely + delx*slant)/extend); - desired_dely = -delx; - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); - error_delx = -error_delx; - error_dely = -error_dely; - break; - case TEXT_WMODE_VD: - /* Vertical font in down-to-up mode: rot = 180 - * |-1 -s/e| - * d_user = d x -I_vv = d x | | - * | 0 -1/e| - */ - desired_delx = -delx; - desired_dely = -(spt_t)((dely + delx*slant)/extend); - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); - error_delx = -error_delx; - error_dely = -error_dely; - break; - } - pdf_doc_add_page_content(format_buffer, len); /* op: */ - /* - * dvipdfm wrongly using "TD" in place of "Td". - * The TD operator set leading, but we are not using T* etc. - */ - pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ - - /* Error correction */ - text_state.ref_x = xpos - error_delx; - text_state.ref_y = ypos - error_dely; - - text_state.offset = 0; -} - -static void -string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - switch (motion_state) { - case STRING_MODE: - break; - case GRAPHICS_MODE: - reset_text_state(); - /* continue */ - case TEXT_MODE: - if (text_state.force_reset) { - dev_set_text_matrix(xpos, ypos, slant, extend, rotate); - pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2); /* op: */ - text_state.force_reset = 0; - } else { - start_string(xpos, ypos, slant, extend, rotate); - } - break; - } - motion_state = STRING_MODE; -} - -/* - * The purpose of the following routine is to force a Tf only - * when it's actually necessary. This became a problem when the - * VF code was added. The VF spec says to instantiate the - * first font contained in the VF file before drawing a virtual - * character. However, that font may not be used for - * many characters (e.g. small caps fonts). For this reason, - * dev_select_font() should not force a "physical" font selection. - * This routine prevents a PDF Tf font selection until there's - * really a character in that font. - */ - -static int -dev_set_font (int font_id) -{ - struct dev_font *font; - int text_rotate; - double font_scale; - int len; - int vert_dir, vert_font; - - /* text_mode() must come before text_state.is_mb is changed. */ - text_mode(); - - font = GET_FONT(font_id); - ASSERT(font); /* Caller should check font_id. */ - - text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; - - vert_font = font->wmode ? 1 : 0; - if (dev_param.autorotate) { - vert_dir = text_state.dir_mode; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 2)|vert_dir; - - if (font->slant != text_state.matrix.slant || - font->extend != text_state.matrix.extend || - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - text_state.matrix.slant = font->slant; - text_state.matrix.extend = font->extend; - text_state.matrix.rotate = text_rotate; - - if (!font->resource) { - font->resource = pdf_get_font_reference(font->font_id); - font->used_chars = pdf_get_font_usedchars(font->font_id); - } - - if (!font->used_on_this_page) { - pdf_doc_add_page_resource("Font", - font->short_name, - pdf_link_obj(font->resource)); - font->used_on_this_page = 1; - } - - font_scale = (double) font->sptsize * dev_unit.dvi2pts; - len = sprintf(format_buffer, " /%s", font->short_name); /* space not necessary. */ - format_buffer[len++] = ' '; - len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'f'; - pdf_doc_add_page_content(format_buffer, len); /* op: Tf */ - - if (font->bold > 0.0 || font->bold != text_state.bold_param) { - if (font->bold <= 0.0) - len = sprintf(format_buffer, " 0 Tr"); - else - len = sprintf(format_buffer, " 2 Tr %.2f w", font->bold); /* _FIXME_ */ - pdf_doc_add_page_content(format_buffer, len); /* op: Tr w */ - } - text_state.bold_param = font->bold; - - text_state.font_id = font_id; - - return 0; -} - - -/* Access text state parameters. - */ -#if 0 -int -pdf_dev_currentfont (void) -{ - return text_state.font_id; -} - -double -pdf_dev_get_font_ptsize (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->sptsize * dev_unit.dvi2pts; - } - - return 1.0; -} -#endif - -int -pdf_dev_get_font_wmode (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->wmode; - } - - return 0; -} - -static unsigned char sbuf0[FORMAT_BUF_SIZE]; -static unsigned char sbuf1[FORMAT_BUF_SIZE]; - -static int -handle_multibyte_string (struct dev_font *font, - const unsigned char **str_ptr, int *str_len, int ctype) -{ - const unsigned char *p; - int i, length; - - p = *str_ptr; - length = *str_len; - -#ifdef XETEX - if (ctype == -1) { /* freetype glyph indexes */ - if (font->ft_to_gid) { - /* convert freetype glyph indexes to physical GID */ - const unsigned char *inbuf = p; - unsigned char *outbuf = sbuf0; - for (i = 0; i < length; i += 2) { - unsigned int gid; - gid = *inbuf++ << 8; - gid += *inbuf++; - gid = font->ft_to_gid[gid]; - *outbuf++ = gid >> 8; - *outbuf++ = gid & 0xff; - } - p = sbuf0; - length = outbuf - sbuf0; - } - } - else -#endif - /* _FIXME_ */ - if (font->is_unicode) { /* UCS-4 */ - if (ctype == 1) { - if (length * 4 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i++) { - sbuf1[i*4 ] = font->ucs_group; - sbuf1[i*4+1] = font->ucs_plane; - sbuf1[i*4+2] = '\0'; - sbuf1[i*4+3] = p[i]; - } - length *= 4; - } else if (ctype == 2) { - int len = 0; - - if (length * 2 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i += 2, len += 4) { - sbuf1[len ] = font->ucs_group; - if ((p[i] & 0xf8) == 0xd8) { - int c; - /* Check for valid surrogate pair. */ - if ((p[i] & 0xfc) != 0xd8 || i + 2 >= length || (p[i+2] & 0xfc) != 0xdc) { - WARN("Invalid surrogate p[%d]=%02X...", i, p[i]); - return -1; - } - c = (((p[i] & 0x03) << 10) | (p[i+1] << 2) | (p[i+2] & 0x03)) + 0x100; - sbuf1[len+1] = (c >> 8) & 0xff; - sbuf1[len+2] = c & 0xff; - i += 2; - } else { - sbuf1[len+1] = font->ucs_plane; - sbuf1[len+2] = p[i]; - } - sbuf1[len+3] = p[i+1]; - } - length = len; - } - p = sbuf1; - } else if (ctype == 1 && font->mapc >= 0) { - /* Omega workaround... - * Translate single-byte chars to double byte code space. - */ - if (length * 2 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i++) { - sbuf1[i*2 ] = (font->mapc & 0xff); - sbuf1[i*2+1] = p[i]; - } - length *= 2; - p = sbuf1; - } - - /* - * Font is double-byte font. Output is assumed to be 16-bit fixed length - * encoding. - * TODO: A character decomposed to multiple characters. - */ - if (font->enc_id >= 0) { - const unsigned char *inbuf; - unsigned char *outbuf; - long inbytesleft, outbytesleft; - CMap *cmap; - - cmap = CMap_cache_get(font->enc_id); - inbuf = p; - outbuf = sbuf0; - inbytesleft = length; - outbytesleft = FORMAT_BUF_SIZE; - - CMap_decode(cmap, - &inbuf, &inbytesleft, &outbuf, &outbytesleft); - if (inbytesleft != 0) { - WARN("CMap conversion failed. (%d bytes remains)", inbytesleft); - return -1; - } - length = FORMAT_BUF_SIZE - outbytesleft; - p = sbuf0; - } - - *str_ptr = p; - *str_len = length; - return 0; -} - - -static pdf_coord *dev_coords = NULL; -static int num_dev_coords = 0; -static int max_dev_coords = 0; - -void pdf_dev_get_coord(double *xpos, double *ypos) -{ - if (num_dev_coords > 0) { - *xpos = dev_coords[num_dev_coords-1].x; - *ypos = dev_coords[num_dev_coords-1].y; - } else { - *xpos = *ypos = 0.0; - } -} - -void pdf_dev_push_coord(double xpos, double ypos) -{ - if (num_dev_coords >= max_dev_coords) { - max_dev_coords += 4; - dev_coords = RENEW(dev_coords, max_dev_coords, pdf_coord); - } - dev_coords[num_dev_coords].x = xpos; - dev_coords[num_dev_coords].y = ypos; - num_dev_coords++; -} - -void pdf_dev_pop_coord(void) -{ - if (num_dev_coords > 0) num_dev_coords--; -} - -/* - * ctype: -#ifdef XETEX - * -1 input string contains 2-byte Freetype glyph index values -#endif - * 0 byte-width of char can be variable and input string - * is properly encoded. - * n Single character cosumes n bytes in input string. - * - * _FIXME_ - * --> - * selectfont(font_name, point_size) and show_string(pos, string) - */ -void -pdf_dev_set_string (spt_t xpos, spt_t ypos, - const void *instr_ptr, int instr_len, - spt_t width, - int font_id, int ctype) -{ - struct dev_font *font; - const unsigned char *str_ptr; /* Pointer to the reencoded string. */ - int length, i, len = 0; - spt_t kern, delh, delv; - spt_t text_xorigin; - spt_t text_yorigin; - - if (font_id < 0 || font_id >= num_dev_fonts) { - ERROR("Invalid font: %d (%d)", font_id, num_dev_fonts); - return; - } - if (font_id != text_state.font_id) { - dev_set_font(font_id); - } - - font = CURRENTFONT(); - if (!font) { - ERROR("Currentfont not set."); - return; - } - - text_xorigin = text_state.ref_x; - text_yorigin = text_state.ref_y; - - str_ptr = instr_ptr; - length = instr_len; - - if (font->format == PDF_FONTTYPE_COMPOSITE) { - if (handle_multibyte_string(font, &str_ptr, &length, ctype) < 0) { - ERROR("Error in converting input string..."); - return; - } - if (font->used_chars != NULL) { - for (i = 0; i < length; i += 2) - add_to_used_chars2(font->used_chars, - (unsigned short) (str_ptr[i] << 8)|str_ptr[i+1]); - } - } else { - if (font->used_chars != NULL) { - for (i = 0; i < length; i++) - font->used_chars[str_ptr[i]] = 1; - } - } - - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); - } - - /* - * Kern is in units of character units, i.e., 1000 = 1 em. - * - * Positive kern means kerning (reduce excess white space). - * - * The following formula is of the form a*x/b where a, x, and b are signed long - * integers. Since in integer arithmetic (a*x) could overflow and a*(x/b) would - * not be accurate, we use floating point arithmetic rather than trying to do - * this all with integer arithmetic. - * - * 1000.0 / (font->extend * font->sptsize) is caluculated each times... - * Is accuracy really a matter? Character widths are always rounded to integer - * (in 1000 units per em) but dvipdfmx does not take into account of this... - */ - - if (text_state.dir_mode==0) { - /* Left-to-right */ - delh = text_xorigin + text_state.offset - xpos; - delv = ypos - text_yorigin; - } else if (text_state.dir_mode==1) { - /* Top-to-bottom */ - delh = ypos - text_yorigin + text_state.offset; - delv = xpos - text_xorigin; - } else { - /* Bottom-to-top */ - delh = ypos + text_yorigin + text_state.offset; - delv = xpos + text_xorigin; - } - - /* White-space more than 3em is not considered as a part of single text. - * So we will break string mode in that case. - * Dvipdfmx spend most of time processing strings with kern = 0 (but far - * more times in font handling). - * You may want to use pre-calculated value for WORD_SPACE_MAX. - * More text compression may be possible by replacing kern with space char - * when -kern is equal to space char width. - */ -#define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize) - - if (text_state.force_reset || - labs(delv) > dev_unit.min_bp_val || - labs(delh) > WORD_SPACE_MAX(font)) { - text_mode(); - kern = 0; - } else { - kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize); - } - - /* Inaccucary introduced by rounding of character width appears within - * single text block. There are point_size/1000 rounding error per character. - * If you really care about accuracy, you should compensate this here too. - */ - if (motion_state != STRING_MODE) - string_mode(xpos, ypos, - font->slant, font->extend, text_state.matrix.rotate); - else if (kern != 0) { - /* - * Same issues as earlier. Use floating point for simplicity. - * This routine needs to be fast, so we don't call sprintf() or strcpy(). - */ - text_state.offset -= - (spt_t) (kern * font->extend * (font->sptsize / 1000.0)); - format_buffer[len++] = text_state.is_mb ? '>' : ')'; - if (font->wmode) - len += p_itoa(-kern, format_buffer + len); - else { - len += p_itoa( kern, format_buffer + len); - } - format_buffer[len++] = text_state.is_mb ? '<' : '('; - pdf_doc_add_page_content(format_buffer, len); /* op: */ - len = 0; - } - - if (text_state.is_mb) { - if (FORMAT_BUF_SIZE - len < 2 * length) - ERROR("Buffer overflow..."); - for (i = 0; i < length; i++) { - int first, second; - - first = (str_ptr[i] >> 4) & 0x0f; - second = str_ptr[i] & 0x0f; - format_buffer[len++] = ((first >= 10) ? first + 'W' : first + '0'); - format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0'); - } - } else { - len += pdfobj_escape_str(format_buffer + len, - FORMAT_BUF_SIZE - len, str_ptr, length); - } - /* I think if you really care about speed, you should avoid memcopy here. */ - pdf_doc_add_page_content(format_buffer, len); /* op: */ - - text_state.offset += width; -} - -void -pdf_init_device (double dvi2pts, int precision, int black_and_white) -{ - if (precision < 0 || - precision > DEV_PRECISION_MAX) - WARN("Number of decimal digits out of range [0-%d].", - DEV_PRECISION_MAX); - - if (precision < 0) { - dev_unit.precision = 0; - } else if (precision > DEV_PRECISION_MAX) { - dev_unit.precision = DEV_PRECISION_MAX; - } else { - dev_unit.precision = precision; - } - dev_unit.dvi2pts = dvi2pts; - dev_unit.min_bp_val = (long) ROUND(1.0/(ten_pow[dev_unit.precision]*dvi2pts), 1); - if (dev_unit.min_bp_val < 0) - dev_unit.min_bp_val = -dev_unit.min_bp_val; - - dev_param.colormode = (black_and_white ? 0 : 1); - - graphics_mode(); - pdf_color_clear_stack(); - pdf_dev_init_gstates(); - - num_dev_fonts = max_dev_fonts = 0; - dev_fonts = NULL; - num_dev_coords = max_dev_coords = 0; - dev_coords = NULL; -} - -void -pdf_close_device (void) -{ - if (dev_fonts) { - int i; - - for (i = 0; i < num_dev_fonts; i++) { - if (dev_fonts[i].tex_name) - RELEASE(dev_fonts[i].tex_name); - if (dev_fonts[i].resource) - pdf_release_obj(dev_fonts[i].resource); - dev_fonts[i].tex_name = NULL; - dev_fonts[i].resource = NULL; - } - RELEASE(dev_fonts); - } - if (dev_coords) RELEASE(dev_coords); - pdf_dev_clear_gstates(); -} - -/* - * BOP, EOP, and FONT section. - * BOP and EOP manipulate some of the same data structures - * as the font stuff. - */ -void -pdf_dev_reset_fonts (void) -{ - int i; - - for (i = 0; i < num_dev_fonts; i++) { - dev_fonts[i].used_on_this_page = 0; - } - - text_state.font_id = -1; - - text_state.matrix.slant = 0.0; - text_state.matrix.extend = 1.0; - text_state.matrix.rotate = TEXT_WMODE_HH; - - text_state.bold_param = 0.0; - - text_state.is_mb = 0; -} - -#ifdef XETEX -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; -} -#endif - -#if 0 -/* Not working */ -void -pdf_dev_set_origin (double phys_x, double phys_y) -{ - pdf_tmatrix M0, M1; - - pdf_dev_currentmatrix(&M0); - pdf_dev_currentmatrix(&M1); - pdf_invertmatrix(&M1); - M0.e = phys_x; M0.f = phys_y; - pdf_concatmatrix(&M1, &M0); - - pdf_dev_concat(&M1); -} -#endif - -void -pdf_dev_bop (const pdf_tmatrix *M) -{ - graphics_mode(); - - text_state.force_reset = 0; - - pdf_dev_gsave(); - pdf_dev_concat(M); - - pdf_dev_reset_fonts(); - pdf_dev_reset_color(0); -} - -void -pdf_dev_eop (void) -{ - int depth; - - graphics_mode(); - - depth = pdf_dev_current_depth(); - if (depth != 1) { - WARN("Unbalenced q/Q nesting...: %d", depth); - pdf_dev_grestore_to(0); - } else { - pdf_dev_grestore(); - } -} - -static void -print_fontmap (const char *font_name, fontmap_rec *mrec) -{ - if (!mrec) - return; - - MESG("\n"); - - MESG("fontmap: %s -> %s", font_name, mrec->font_name); - if (mrec->enc_name) - MESG("(%s)", mrec->enc_name); - if (mrec->opt.extend != 1.0) - MESG("[extend:%g]", mrec->opt.extend); - if (mrec->opt.slant != 0.0) - MESG("[slant:%g]", mrec->opt.slant); - if (mrec->opt.bold != 0.0) - MESG("[bold:%g]", mrec->opt.bold); - if (mrec->opt.flags & FONTMAP_OPT_NOEMBED) - MESG("[noemb]"); - if (mrec->opt.mapc >= 0) - MESG("[map:<%02x>]", mrec->opt.mapc); - if (mrec->opt.charcoll) - MESG("[csi:%s]", mrec->opt.charcoll); - if (mrec->opt.index) - MESG("[index:%d]", mrec->opt.index); - - switch (mrec->opt.style) { - case FONTMAP_STYLE_BOLD: - MESG("[style:bold]"); - break; - case FONTMAP_STYLE_ITALIC: - MESG("[style:italic]"); - break; - case FONTMAP_STYLE_BOLDITALIC: - MESG("[style:bolditalic]"); - break; - } - MESG("\n"); - -} - -/* _FIXME_ - * Font is identified with font_name and point_size as in DVI here. - * This may assign different resource name for same font at different - * point size even for scalable fonts. - */ -int -pdf_dev_locate_font (const char *font_name, spt_t ptsize) -{ - int i; - fontmap_rec *mrec; - struct dev_font *font; - - if (!font_name) - return -1; - - if (ptsize == 0) { - ERROR("pdf_dev_locate_font() called with the zero ptsize."); - return -1; - } - - for (i = 0; i < num_dev_fonts; i++) { - if (!strcmp(font_name, dev_fonts[i].tex_name) && ptsize == dev_fonts[i].sptsize) { - return i; - } - } - - /* - * Make sure we have room for a new one, even though we may not - * actually create one. - */ - if (num_dev_fonts >= max_dev_fonts) { - max_dev_fonts += 16; - dev_fonts = RENEW(dev_fonts, max_dev_fonts, struct dev_font); - } - - font = &dev_fonts[num_dev_fonts]; - - /* New font */ - mrec = pdf_lookup_fontmap_record(font_name); - - if (verbose > 1) - print_fontmap(font_name, mrec); - - font->font_id = pdf_font_findresource(font_name, ptsize * dev_unit.dvi2pts, mrec); - if (font->font_id < 0) - return -1; - - /* We found device font here. */ - font->short_name[0] = 'F'; - p_itoa(num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */ - num_phys_fonts++; - - font->used_on_this_page = 0; - - font->tex_name = NEW(strlen(font_name) + 1, char); - strcpy(font->tex_name, font_name); - font->sptsize = ptsize; - - switch (pdf_get_font_subtype(font->font_id)) { - case PDF_FONT_FONTTYPE_TYPE3: - font->format = PDF_FONTTYPE_BITMAP; - break; - case PDF_FONT_FONTTYPE_TYPE0: - font->format = PDF_FONTTYPE_COMPOSITE; - break; - default: - font->format = PDF_FONTTYPE_SIMPLE; - break; - } - - font->wmode = pdf_get_font_wmode (font->font_id); - font->enc_id = pdf_get_font_encoding(font->font_id); -#ifdef XETEX - font->ft_to_gid = pdf_get_font_ft_to_gid(font->font_id); -#endif - - font->resource = NULL; /* Don't ref obj until font is actually used. */ - font->used_chars = NULL; - - font->extend = 1.0; - font->slant = 0.0; - font->bold = 0.0; - font->mapc = -1; - font->is_unicode = 0; - font->ucs_group = 0; - font->ucs_plane = 0; - - if (mrec) { - font->extend = mrec->opt.extend; - font->slant = mrec->opt.slant; - font->bold = mrec->opt.bold; - if (mrec->opt.mapc >= 0) - font->mapc = (mrec->opt.mapc >> 8) & 0xff; - else { - font->mapc = -1; - } - if (mrec->enc_name && - !strcmp(mrec->enc_name, "unicode")) { - font->is_unicode = 1; - if (mrec->opt.mapc >= 0) { - font->ucs_group = (mrec->opt.mapc >> 24) & 0xff; - font->ucs_plane = (mrec->opt.mapc >> 16) & 0xff; - } else { - font->ucs_group = 0; - font->ucs_plane = 0; - } - } else { - font->is_unicode = 0; - } - } - - return num_dev_fonts++; -} - - -/* This does not remember current stroking width. */ -static int -dev_sprint_line (char *buf, spt_t width, - spt_t p0_x, spt_t p0_y, spt_t p1_x, spt_t p1_y) -{ - int len = 0; - double w; - - w = width * dev_unit.dvi2pts; - - len += p_dtoa(w, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), buf+len); - buf[len++] = ' '; - buf[len++] = 'w'; - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p0_x, NULL); - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p0_y, NULL); - buf[len++] = ' '; - buf[len++] = 'm'; - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_x, NULL); - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_y, NULL); - buf[len++] = ' '; - buf[len++] = 'l'; - buf[len++] = ' '; - buf[len++] = 'S'; - - return len; -} - -/* Not optimized. */ -#define PDF_LINE_THICKNESS_MAX 5.0 -void -pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) -{ - int len = 0; - double width_in_bp; - - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); - } - - graphics_mode(); - - format_buffer[len++] = ' '; - format_buffer[len++] = 'q'; - format_buffer[len++] = ' '; - /* Don't use too thick line. */ - width_in_bp = ((width < height) ? width : height) * dev_unit.dvi2pts; - if (width_in_bp < 0.0 || /* Shouldn't happen */ - width_in_bp > PDF_LINE_THICKNESS_MAX) { - pdf_rect rect; - - rect.llx = dev_unit.dvi2pts * xpos; - rect.lly = dev_unit.dvi2pts * ypos; - rect.urx = dev_unit.dvi2pts * width; - rect.ury = dev_unit.dvi2pts * height; - len += pdf_sprint_rect(format_buffer+len, &rect); - format_buffer[len++] = ' '; - format_buffer[len++] = 'r'; - format_buffer[len++] = 'e'; - format_buffer[len++] = ' '; - format_buffer[len++] = 'f'; - } else { - if (width > height) { - /* NOTE: - * A line width of 0 denotes the thinnest line that can be rendered at - * device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2, - * "Details of Graphics State Parameters", p. 185. - */ - if (height < dev_unit.min_bp_val) { - WARN("Too thin line: height=%ld (%g bp)", height, width_in_bp); - WARN("Please consider using \"-d\" option."); - } - len += dev_sprint_line(format_buffer+len, - height, - xpos, - ypos + height/2, - xpos + width, - ypos + height/2); - } else { - if (width < dev_unit.min_bp_val) { - WARN("Too thin line: width=%ld (%g bp)", width, width_in_bp); - WARN("Please consider using \"-d\" option."); - } - len += dev_sprint_line(format_buffer+len, - width, - xpos + width/2, - ypos, - xpos + width/2, - ypos + height); - } - } - format_buffer[len++] = ' '; - format_buffer[len++] = 'Q'; - pdf_doc_add_page_content(format_buffer, len); /* op: q re f Q */ -} - -/* Rectangle in device space coordinate. */ -void -pdf_dev_set_rect (pdf_rect *rect, - spt_t x_user, spt_t y_user, - spt_t width, spt_t height, spt_t depth) -{ - double dev_x, dev_y; - pdf_coord p0, p1, p2, p3; - double min_x, min_y, max_x, max_y; - - dev_x = x_user * dev_unit.dvi2pts; - dev_y = y_user * dev_unit.dvi2pts; - if (text_state.dir_mode) { - p0.x = dev_x - dev_unit.dvi2pts * depth; - p0.y = dev_y - dev_unit.dvi2pts * width; - p1.x = dev_x + dev_unit.dvi2pts * height; - p1.y = p0.y; - p2.x = p1.x; - p2.y = dev_y; - p3.x = p0.x; - p3.y = p2.y; - } else { - p0.x = dev_x; - p0.y = dev_y - dev_unit.dvi2pts * depth; - p1.x = dev_x + dev_unit.dvi2pts * width; - p1.y = p0.y; - p2.x = p1.x; - p2.y = dev_y + dev_unit.dvi2pts * height; - p3.x = p0.x; - p3.y = p2.y; - } - - pdf_dev_transform(&p0, NULL); /* currentmatrix */ - pdf_dev_transform(&p1, NULL); - pdf_dev_transform(&p2, NULL); - pdf_dev_transform(&p3, NULL); - - min_x = MIN(p0.x , p1.x); - min_x = MIN(min_x, p2.x); - min_x = MIN(min_x, p3.x); - - max_x = MAX(p0.x , p1.x); - max_x = MAX(max_x, p2.x); - max_x = MAX(max_x, p3.x); - - min_y = MIN(p0.y , p1.y); - min_y = MIN(min_y, p2.y); - min_y = MIN(min_y, p3.y); - - max_y = MAX(p0.y , p1.y); - max_y = MAX(max_y, p2.y); - max_y = MAX(max_y, p3.y); - - rect->llx = min_x; - rect->lly = min_y; - rect->urx = max_x; - rect->ury = max_y; - - return; -} - -int -pdf_dev_get_dirmode (void) -{ - return text_state.dir_mode; -} - -void -pdf_dev_set_dirmode (int text_dir) -{ - struct dev_font *font; - int text_rotate; - int vert_dir, vert_font; - - font = CURRENTFONT(); - - vert_font = (font && font->wmode) ? 1 : 0; - if (dev_param.autorotate) { - vert_dir = text_dir; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 2)|vert_dir; - - if (font && - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - - text_state.matrix.rotate = text_rotate; - text_state.dir_mode = text_dir; -} - -static void -dev_set_param_autorotate (int auto_rotate) -{ - struct dev_font *font; - int text_rotate, vert_font, vert_dir; - - font = CURRENTFONT(); - - vert_font = (font && font->wmode) ? 1 : 0; - if (auto_rotate) { - vert_dir = text_state.dir_mode; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 2)|vert_dir; - - if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - text_state.matrix.rotate = text_rotate; - dev_param.autorotate = auto_rotate; -} - -int -pdf_dev_get_param (int param_type) -{ - int value = 0; - - switch (param_type) { - case PDF_DEV_PARAM_AUTOROTATE: - value = dev_param.autorotate; - break; - case PDF_DEV_PARAM_COLORMODE: - value = dev_param.colormode; - break; - default: - ERROR("Unknown device parameter: %d", param_type); - } - - return value; -} - -void -pdf_dev_set_param (int param_type, int value) -{ - switch (param_type) { - case PDF_DEV_PARAM_AUTOROTATE: - dev_set_param_autorotate(value); - break; - case PDF_DEV_PARAM_COLORMODE: - dev_param.colormode = value; /* 0 for B&W */ - break; - default: - ERROR("Unknown device parameter: %d", param_type); - } - - return; -} - - -int -pdf_dev_put_image (int id, - transform_info *p, - double ref_x, - double ref_y) -{ - char *res_name; - pdf_tmatrix M, M1; - pdf_rect r; - int len = 0; - - if (num_dev_coords > 0) { - ref_x -= dev_coords[num_dev_coords-1].x; - ref_y -= dev_coords[num_dev_coords-1].y; - } - - pdf_copymatrix(&M, &(p->matrix)); - M.e += ref_x; M.f += ref_y; - /* Just rotate by -90, but not tested yet. Any problem if M has scaling? */ - if (dev_param.autorotate && - text_state.dir_mode) { - double tmp; - tmp = -M.a; M.a = M.b; M.b = tmp; - tmp = -M.c; M.c = M.d; M.d = tmp; - } - - graphics_mode(); - pdf_dev_gsave(); - - pdf_ximage_scale_image(id, &M1, &r, p); - pdf_concatmatrix(&M, &M1); - pdf_dev_concat(&M); - - /* Clip */ - if (p->flags & INFO_DO_CLIP) { -#if 0 - pdf_dev_newpath(); - pdf_dev_moveto(r.llx, r.lly); - pdf_dev_lineto(r.urx, r.lly); - pdf_dev_lineto(r.urx, r.ury); - pdf_dev_lineto(r.llx, r.ury); - pdf_dev_closepath(); - pdf_dev_clip(); - pdf_dev_newpath(); -#else - pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); -#endif - } - - res_name = pdf_ximage_get_resname(id); - len = sprintf(work_buffer, " /%s Do", res_name); - pdf_doc_add_page_content(work_buffer, len); /* op: Do */ - - pdf_dev_grestore(); - - pdf_doc_add_page_resource("XObject", - res_name, - pdf_ximage_get_reference(id)); - - return 0; -} - - -void -transform_info_clear (transform_info *info) -{ - /* Physical dimensions */ - info->width = 0.0; - info->height = 0.0; - info->depth = 0.0; - - info->bbox.llx = 0.0; - info->bbox.lly = 0.0; - info->bbox.urx = 0.0; - info->bbox.ury = 0.0; - - /* Transformation matrix */ - pdf_setmatrix(&(info->matrix), 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - - info->flags = 0; -} diff --git a/Build/source/texk/dvipdfm-x/src/pdfdoc.c b/Build/source/texk/dvipdfm-x/src/pdfdoc.c deleted file mode 100644 index 052587a288c..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfdoc.c +++ /dev/null @@ -1,2745 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -/* - * TODO: Many things... - * {begin,end}_{bead,article}, box stack, name tree (not limited to dests)... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" - -#include "numbers.h" - -#include "pdfobj.h" -#include "pdfparse.h" -#include "pdfnames.h" - -#include "pdfencrypt.h" - -#include "pdfdev.h" -#include "pdfdraw.h" -#include "pdfcolor.h" - -#include "pdfresource.h" -#include "pdffont.h" -#include "pdfximage.h" - -#include "pdflimits.h" - -#if HAVE_LIBPNG -#include "pngimage.h" -#endif -#include "jpegimage.h" - -#include "pdfdoc.h" - -#define PDFDOC_PAGES_ALLOC_SIZE 128u -#define PDFDOC_ARTICLE_ALLOC_SIZE 16 -#define PDFDOC_BEAD_ALLOC_SIZE 16 - -static int verbose = 0; - -static char manual_thumb_enabled = 0; -static char *thumb_basename = NULL; - -void -pdf_doc_enable_manual_thumbnails (void) -{ -#if HAVE_LIBPNG - manual_thumb_enabled = 1; -#else - WARN("Manual thumbnail is not supported without the libpng library."); -#endif -} - -static pdf_obj * -read_thumbnail (const char *thumb_filename) -{ - pdf_obj *image_ref; - int xobj_id; - FILE *fp; - - fp = MFOPEN(thumb_filename, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Could not open thumbnail file \"%s\"", thumb_filename); - return NULL; - } - if (!check_for_png(fp) && !check_for_jpeg(fp)) { - WARN("Thumbnail \"%s\" not a png/jpeg file!", thumb_filename); - MFCLOSE(fp); - return NULL; - } - MFCLOSE(fp); - - xobj_id = pdf_ximage_findresource(thumb_filename, 0, NULL); - if (xobj_id < 0) { - WARN("Could not read thumbnail file \"%s\".", thumb_filename); - image_ref = NULL; - } else { - image_ref = pdf_ximage_get_reference(xobj_id); - } - - return image_ref; -} - -void -pdf_doc_set_verbose (void) -{ - verbose++; - pdf_font_set_verbose(); - pdf_color_set_verbose(); - pdf_ximage_set_verbose(); -} - -typedef struct pdf_form -{ - char *ident; - - pdf_tmatrix matrix; - pdf_rect cropbox; - - pdf_obj *resources; - pdf_obj *contents; -} pdf_form; - -struct form_list_node -{ - int q_depth; - pdf_form form; - - struct form_list_node *prev; -}; - -#define USE_MY_MEDIABOX (1 << 0) -typedef struct pdf_page -{ - pdf_obj *page_obj; - pdf_obj *page_ref; - - int flags; - - double ref_x, ref_y; - pdf_rect cropbox; - - pdf_obj *resources; - - /* Contents */ - pdf_obj *background; - pdf_obj *contents; - - /* global bop, background, contents, global eop */ - pdf_obj *content_refs[4]; - - pdf_obj *annots; - pdf_obj *beads; -} pdf_page; - -typedef struct pdf_olitem -{ - pdf_obj *dict; - - int is_open; - - struct pdf_olitem *first; - struct pdf_olitem *parent; - - struct pdf_olitem *next; -} pdf_olitem; - -typedef struct pdf_bead -{ - char *id; - long page_no; - pdf_rect rect; -} pdf_bead; - -typedef struct pdf_article -{ - char *id; - pdf_obj *info; - long num_beads; - long max_beads; - pdf_bead *beads; -} pdf_article; - -struct name_dict -{ - const char *category; - struct ht_table *data; -}; - - -typedef struct pdf_doc -{ - struct { - pdf_obj *dict; - - pdf_obj *viewerpref; - pdf_obj *pagelabels; - pdf_obj *pages; - pdf_obj *names; - pdf_obj *threads; - } root; - - pdf_obj *info; - - struct { - pdf_rect mediabox; - pdf_obj *bop, *eop; - - long num_entries; /* This is not actually total number of pages. */ - long max_entries; - pdf_page *entries; - } pages; - - struct { - pdf_olitem *first; - pdf_olitem *current; - int current_depth; - } outlines; - - struct { - long num_entries; - long max_entries; - pdf_article *entries; - } articles; - - struct name_dict *names; - - int check_gotos; - struct ht_table gotos; - - struct { - int outline_open_depth; - double annot_grow; - } opt; - - struct form_list_node *pending_forms; - -} pdf_doc; -static pdf_doc pdoc; - -static void -pdf_doc_init_catalog (pdf_doc *p) -{ - p->root.viewerpref = NULL; - p->root.pagelabels = NULL; - p->root.pages = NULL; - p->root.names = NULL; - p->root.threads = NULL; - - p->root.dict = pdf_new_dict(); - pdf_set_root(p->root.dict); - - return; -} - -static void -pdf_doc_close_catalog (pdf_doc *p) -{ - pdf_obj *tmp; - - if (p->root.viewerpref) { - tmp = pdf_lookup_dict(p->root.dict, "ViewerPreferences"); - if (!tmp) { - pdf_add_dict(p->root.dict, - pdf_new_name("ViewerPreferences"), - pdf_ref_obj (p->root.viewerpref)); - } else if (PDF_OBJ_DICTTYPE(tmp)) { - pdf_merge_dict(p->root.viewerpref, tmp); - pdf_add_dict(p->root.dict, - pdf_new_name("ViewerPreferences"), - pdf_ref_obj (p->root.viewerpref)); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify ViewerPreferences."); - } - pdf_release_obj(p->root.viewerpref); - p->root.viewerpref = NULL; - } - - if (p->root.pagelabels) { - tmp = pdf_lookup_dict(p->root.dict, "PageLabels"); - if (!tmp) { - tmp = pdf_new_dict(); - pdf_add_dict(tmp, pdf_new_name("Nums"), pdf_link_obj(p->root.pagelabels)); - pdf_add_dict(p->root.dict, - pdf_new_name("PageLabels"), pdf_ref_obj(tmp)); - pdf_release_obj(tmp); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify PageLabels."); - } - pdf_release_obj(p->root.pagelabels); - p->root.pagelabels = NULL; - } - - pdf_add_dict(p->root.dict, - pdf_new_name("Type"), pdf_new_name("Catalog")); - pdf_release_obj(p->root.dict); - p->root.dict = NULL; - - return; -} - -/* - * Pages are starting at 1. - * The page count does not increase until the page is finished. - */ -#define LASTPAGE(p) (&(p->pages.entries[p->pages.num_entries])) -#define FIRSTPAGE(p) (&(p->pages.entries[0])) -#define PAGECOUNT(p) (p->pages.num_entries) -#define MAXPAGES(p) (p->pages.max_entries) - -static void -doc_resize_page_entries (pdf_doc *p, long size) -{ - if (size > MAXPAGES(p)) { - long i; - - p->pages.entries = RENEW(p->pages.entries, size, struct pdf_page); - for (i = p->pages.max_entries; i < size; i++) { - p->pages.entries[i].page_obj = NULL; - p->pages.entries[i].page_ref = NULL; - p->pages.entries[i].flags = 0; - p->pages.entries[i].resources = NULL; - p->pages.entries[i].background = NULL; - p->pages.entries[i].contents = NULL; - p->pages.entries[i].content_refs[0] = NULL; /* global bop */ - p->pages.entries[i].content_refs[1] = NULL; /* background */ - p->pages.entries[i].content_refs[2] = NULL; /* page body */ - p->pages.entries[i].content_refs[3] = NULL; /* global eop */ - p->pages.entries[i].annots = NULL; - p->pages.entries[i].beads = NULL; - } - p->pages.max_entries = size; - } - - return; -} - -static pdf_page * -doc_get_page_entry (pdf_doc *p, unsigned long page_no) -{ - pdf_page *page; - - if (page_no > 65535ul) { - ERROR("Page number %ul too large!", page_no); - } else if (page_no == 0) { - ERROR("Invalid Page number %ul.", page_no); - } - - if (page_no > MAXPAGES(p)) { - doc_resize_page_entries(p, page_no + PDFDOC_PAGES_ALLOC_SIZE); - } - - page = &(p->pages.entries[page_no - 1]); - - return page; -} - -static void pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height); -static void pdf_doc_close_page_tree (pdf_doc *p); - -static void pdf_doc_init_names (pdf_doc *p, int check_gotos); -static void pdf_doc_close_names (pdf_doc *p); - -static void pdf_doc_add_goto (pdf_obj *annot_dict); - -static void pdf_doc_init_docinfo (pdf_doc *p); -static void pdf_doc_close_docinfo (pdf_doc *p); - -static void pdf_doc_init_articles (pdf_doc *p); -static void pdf_doc_close_articles (pdf_doc *p); -static void pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth); -static void pdf_doc_close_bookmarks (pdf_doc *p); - -void -pdf_doc_set_bop_content (const char *content, unsigned length) -{ - pdf_doc *p = &pdoc; - - ASSERT(p); - - if (p->pages.bop) { - pdf_release_obj(p->pages.bop); - p->pages.bop = NULL; - } - - if (length > 0) { - p->pages.bop = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(p->pages.bop, content, length); - } else { - p->pages.bop = NULL; - } - - return; -} - -void -pdf_doc_set_eop_content (const char *content, unsigned length) -{ - pdf_doc *p = &pdoc; - - if (p->pages.eop) { - pdf_release_obj(p->pages.eop); - p->pages.eop = NULL; - } - - if (length > 0) { - p->pages.eop = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(p->pages.eop, content, length); - } else { - p->pages.eop = NULL; - } - - return; -} - -#ifndef HAVE_TM_GMTOFF -#ifndef HAVE_TIMEZONE - -/* auxiliary function to compute timezone offset on - systems that do not support the tm_gmtoff in struct tm, - or have a timezone variable. Such as i386-solaris. */ - -static long -compute_timezone_offset() -{ - const time_t now = time(NULL); - struct tm tm; - struct tm local; - time_t gmtoff; - - localtime_r(&now, &local); - gmtime_r(&now, &tm); - return (mktime(&local) - mktime(&tm)); -} - -#endif /* HAVE_TIMEZONE */ -#endif /* HAVE_TM_GMTOFF */ - -/* - * Docinfo - */ -static long -asn_date (char *date_string) -{ - long tz_offset; - time_t current_time; - struct tm *bd_time; - - time(¤t_time); - bd_time = localtime(¤t_time); - -#ifdef HAVE_TM_GMTOFF - tz_offset = bd_time->tm_gmtoff; -#else -# ifdef HAVE_TIMEZONE - tz_offset = -timezone; -# else - tz_offset = compute_timezone_offset(); -# endif /* HAVE_TIMEZONE */ -#endif /* HAVE_TM_GMTOFF */ - - sprintf(date_string, "D:%04d%02d%02d%02d%02d%02d%c%02ld'%02ld'", - bd_time->tm_year + 1900, bd_time->tm_mon + 1, bd_time->tm_mday, - bd_time->tm_hour, bd_time->tm_min, bd_time->tm_sec, - (tz_offset > 0) ? '+' : '-', labs(tz_offset) / 3600, - (labs(tz_offset) / 60) % 60); - - return strlen(date_string); -} - -static void -pdf_doc_init_docinfo (pdf_doc *p) -{ - p->info = pdf_new_dict(); - pdf_set_info(p->info); - - return; -} - -static void -pdf_doc_close_docinfo (pdf_doc *p) -{ - pdf_obj *docinfo = p->info; - - /* - * Excerpt from PDF Reference 4th ed., sec. 10.2.1. - * - * Any entry whose value is not known should be omitted from the dictionary, - * rather than included with an empty string as its value. - * - * .... - * - * Note: Although viewer applications can store custom metadata in the document - * information dictionary, it is inappropriate to store private content or - * structural information there; such information should be stored in the - * document catalog instead (see Section 3.6.1, Document Catalog ). - */ - const char *keys[] = { - "Title", "Author", "Subject", "Keywords", "Creator", "Producer", - "CreationDate", "ModDate", /* Date */ - NULL - }; - pdf_obj *value; - char *banner; - int i; - - for (i = 0; keys[i] != NULL; i++) { - value = pdf_lookup_dict(docinfo, keys[i]); - if (value) { - if (!PDF_OBJ_STRINGTYPE(value)) { - WARN("\"%s\" in DocInfo dictionary not string type.", keys[i]); - pdf_remove_dict(docinfo, keys[i]); - WARN("\"%s\" removed from DocInfo.", keys[i]); - } else if (pdf_string_length(value) == 0) { - /* The hyperref package often uses emtpy strings. */ - pdf_remove_dict(docinfo, keys[i]); - } - } - } - - banner = NEW(strlen(PACKAGE)+strlen(VERSION)+4, char); - sprintf(banner, "%s (%s)", PACKAGE, VERSION); - pdf_add_dict(docinfo, - pdf_new_name("Producer"), - pdf_new_string(banner, strlen(banner))); - RELEASE(banner); - - if (!pdf_lookup_dict(docinfo, "CreationDate")) { - char now[32]; - - asn_date(now); - pdf_add_dict(docinfo, - pdf_new_name ("CreationDate"), - pdf_new_string(now, strlen(now))); - } - - pdf_release_obj(docinfo); - p->info = NULL; - - return; -} - -static pdf_obj * -pdf_doc_get_page_resources (pdf_doc *p, const char *category) -{ - pdf_obj *resources; - pdf_page *currentpage; - pdf_obj *res_dict; - - if (!p || !category) { - return NULL; - } - - if (p->pending_forms) { - if (p->pending_forms->form.resources) { - res_dict = p->pending_forms->form.resources; - } else { - res_dict = p->pending_forms->form.resources = pdf_new_dict(); - } - } else { - currentpage = LASTPAGE(p); - if (currentpage->resources) { - res_dict = currentpage->resources; - } else { - res_dict = currentpage->resources = pdf_new_dict(); - } - } - resources = pdf_lookup_dict(res_dict, category); - if (!resources) { - resources = pdf_new_dict(); - pdf_add_dict(res_dict, pdf_new_name(category), resources); - } - - return resources; -} - -void -pdf_doc_add_page_resource (const char *category, - const char *resource_name, pdf_obj *resource_ref) -{ - pdf_doc *p = &pdoc; - pdf_obj *resources; - pdf_obj *duplicate; - - if (!PDF_OBJ_INDIRECTTYPE(resource_ref)) { - WARN("Passed non indirect reference..."); - resource_ref = pdf_ref_obj(resource_ref); /* leak */ - } - resources = pdf_doc_get_page_resources(p, category); - duplicate = pdf_lookup_dict(resources, resource_name); - if (duplicate && pdf_compare_reference(duplicate, resource_ref)) { - WARN("Conflicting page resource found (page: %ld, category: %s, name: %s).", - pdf_doc_current_page_number(), category, resource_name); - WARN("Ignoring..."); - pdf_release_obj(resource_ref); - } else { - pdf_add_dict(resources, pdf_new_name(resource_name), resource_ref); - } - - return; -} - -static void -doc_flush_page (pdf_doc *p, pdf_page *page, pdf_obj *parent_ref) -{ - pdf_obj *contents_array; - int count; - - pdf_add_dict(page->page_obj, - pdf_new_name("Type"), pdf_new_name("Page")); - pdf_add_dict(page->page_obj, - pdf_new_name("Parent"), parent_ref); - - /* - * Clipping area specified by CropBox is affected by MediaBox which - * might be inherit from parent node. If MediaBox of the root node - * does not have enough size to cover all page's imaging area, using - * CropBox here gives incorrect result. - */ - if (page->flags & USE_MY_MEDIABOX) { - pdf_obj *mediabox; - - mediabox = pdf_new_array(); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.llx, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.lly, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.urx, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.ury, 0.01))); - pdf_add_dict(page->page_obj, pdf_new_name("MediaBox"), mediabox); - } - - count = 0; - contents_array = pdf_new_array(); - if (page->content_refs[0]) { /* global bop */ - pdf_add_array(contents_array, page->content_refs[0]); - count++; - } else if (p->pages.bop && - pdf_stream_length(p->pages.bop) > 0) { - pdf_add_array(contents_array, pdf_ref_obj(p->pages.bop)); - count++; - } - if (page->content_refs[1]) { /* background */ - pdf_add_array(contents_array, page->content_refs[1]); - count++; - } - if (page->content_refs[2]) { /* page body */ - pdf_add_array(contents_array, page->content_refs[2]); - count++; - } - if (page->content_refs[3]) { /* global eop */ - pdf_add_array(contents_array, page->content_refs[3]); - count++; - } else if (p->pages.eop && - pdf_stream_length(p->pages.eop) > 0) { - pdf_add_array(contents_array, pdf_ref_obj(p->pages.eop)); - count++; - } - - if (count == 0) { - WARN("Page with empty content found!!!"); - } - page->content_refs[0] = NULL; - page->content_refs[1] = NULL; - page->content_refs[2] = NULL; - page->content_refs[3] = NULL; - - pdf_add_dict(page->page_obj, - pdf_new_name("Contents"), contents_array); - - - if (page->annots) { - pdf_add_dict(page->page_obj, - pdf_new_name("Annots"), pdf_ref_obj(page->annots)); - pdf_release_obj(page->annots); - } - if (page->beads) { - pdf_add_dict(page->page_obj, - pdf_new_name("B"), pdf_ref_obj(page->beads)); - pdf_release_obj(page->beads); - } - pdf_release_obj(page->page_obj); - pdf_release_obj(page->page_ref); - - page->page_obj = NULL; - page->page_ref = NULL; - page->annots = NULL; - page->beads = NULL; - - return; -} - -/* B-tree? */ -#define PAGE_CLUSTER 4 -static pdf_obj * -build_page_tree (pdf_doc *p, - pdf_page *firstpage, long num_pages, - pdf_obj *parent_ref) -{ - pdf_obj *self, *self_ref, *kids; - long i; - - self = pdf_new_dict(); - /* - * This is a slight kludge which allow the subtree dictionary - * generated by this routine to be merged with the real - * page_tree dictionary, while keeping the indirect object - * references right. - */ - self_ref = parent_ref ? pdf_ref_obj(self) : pdf_ref_obj(p->root.pages); - - pdf_add_dict(self, pdf_new_name("Type"), pdf_new_name("Pages")); - pdf_add_dict(self, pdf_new_name("Count"), pdf_new_number((double) num_pages)); - - if (parent_ref != NULL) - pdf_add_dict(self, pdf_new_name("Parent"), parent_ref); - - kids = pdf_new_array(); - if (num_pages > 0 && num_pages <= PAGE_CLUSTER) { - for (i = 0; i < num_pages; i++) { - pdf_page *page; - - page = firstpage + i; - if (!page->page_ref) - page->page_ref = pdf_ref_obj(page->page_obj); - pdf_add_array (kids, pdf_link_obj(page->page_ref)); - doc_flush_page(p, page, pdf_link_obj(self_ref)); - } - } else if (num_pages > 0) { - for (i = 0; i < PAGE_CLUSTER; i++) { - long start, end; - - start = (i*num_pages)/PAGE_CLUSTER; - end = ((i+1)*num_pages)/PAGE_CLUSTER; - if (end - start > 1) { - pdf_obj *subtree; - - subtree = build_page_tree(p, firstpage + start, end - start, - pdf_link_obj(self_ref)); - pdf_add_array(kids, pdf_ref_obj(subtree)); - pdf_release_obj(subtree); - } else { - pdf_page *page; - - page = firstpage + start; - if (!page->page_ref) - page->page_ref = pdf_ref_obj(page->page_obj); - pdf_add_array (kids, pdf_link_obj(page->page_ref)); - doc_flush_page(p, page, pdf_link_obj(self_ref)); - } - } - } - pdf_add_dict(self, pdf_new_name("Kids"), kids); - pdf_release_obj(self_ref); - - return self; -} - -static void -pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height) -{ - /* - * Create empty page tree. - * The docroot.pages is kept open until the document is closed. - * This allows the user to write to pages if he so choses. - */ - p->root.pages = pdf_new_dict(); - - p->pages.num_entries = 0; - p->pages.max_entries = 0; - p->pages.entries = NULL; - - p->pages.bop = NULL; - p->pages.eop = NULL; - - p->pages.mediabox.llx = 0.0; - p->pages.mediabox.lly = 0.0; - p->pages.mediabox.urx = media_width; - p->pages.mediabox.ury = media_height; - - return; -} - -static void -pdf_doc_close_page_tree (pdf_doc *p) -{ - pdf_obj *page_tree_root; - pdf_obj *mediabox; - long page_no; - - /* - * Do consistency check on forward references to pages. - */ - for (page_no = PAGECOUNT(p) + 1; page_no <= MAXPAGES(p); page_no++) { - pdf_page *page; - - page = doc_get_page_entry(p, page_no); - if (page->page_obj) { - WARN("Nonexistent page #%ld refered.", page_no); - pdf_release_obj(page->page_ref); - page->page_ref = NULL; - } - if (page->page_obj) { - WARN("Entry for a nonexistent page #%ld created.", page_no); - pdf_release_obj(page->page_obj); - page->page_obj = NULL; - } - if (page->annots) { - WARN("Annotation attached to a nonexistent page #%ld.", page_no); - pdf_release_obj(page->annots); - page->annots = NULL; - } - if (page->beads) { - WARN("Article beads attached to a nonexistent page #%ld.", page_no); - pdf_release_obj(page->beads); - page->beads = NULL; - } - if (page->resources) { - pdf_release_obj(page->resources); - page->resources = NULL; - } - } - - /* - * Connect page tree to root node. - */ - page_tree_root = build_page_tree(p, FIRSTPAGE(p), PAGECOUNT(p), NULL); - pdf_merge_dict (p->root.pages, page_tree_root); - pdf_release_obj(page_tree_root); - - /* They must be after build_page_tree() */ - if (p->pages.bop) { - pdf_add_stream (p->pages.bop, "\n", 1); - pdf_release_obj(p->pages.bop); - p->pages.bop = NULL; - } - if (p->pages.eop) { - pdf_add_stream (p->pages.eop, "\n", 1); - pdf_release_obj(p->pages.eop); - p->pages.eop = NULL; - } - - /* Create media box at root node and let the other pages inherit it. */ - mediabox = pdf_new_array(); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.llx, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.lly, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.urx, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.ury, 0.01))); - pdf_add_dict(p->root.pages, pdf_new_name("MediaBox"), mediabox); - - pdf_add_dict(p->root.dict, - pdf_new_name("Pages"), - pdf_ref_obj (p->root.pages)); - pdf_release_obj(p->root.pages); - p->root.pages = NULL; - - RELEASE(p->pages.entries); - p->pages.entries = NULL; - p->pages.num_entries = 0; - p->pages.max_entries = 0; - - return; -} - -/* - * From PDFReference15_v6.pdf (p.119 and p.834) - * - * MediaBox rectangle (Required; inheritable) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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. - */ - -pdf_obj * -pdf_doc_get_page (pdf_file *pf, long page_no, long *count_p, - pdf_rect *bbox, pdf_obj **resources_p) { - pdf_obj *page_tree = NULL; - pdf_obj *resources = NULL, *box = NULL, *rotate = NULL; - pdf_obj *catalog; - - catalog = pdf_file_get_catalog(pf); - - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - - if (!PDF_OBJ_DICTTYPE(page_tree)) - goto error; - - { - long count; - pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); - if (!PDF_OBJ_NUMBERTYPE(tmp)) { - if (tmp) - pdf_release_obj(tmp); - goto error; - } - count = pdf_number_value(tmp); - pdf_release_obj(tmp); - if (count_p) - *count_p = count; - if (page_no <= 0 || page_no > count) { - WARN("Page %ld does not exist.", page_no); - goto error_silent; - } - } - - /* - * Seek correct page. Get MediaBox, CropBox and Resources. - * (Note that these entries can be inherited.) - */ - { - pdf_obj *media_box = NULL, *crop_box = NULL, *kids, *tmp; - int depth = PDF_OBJ_MAX_DEPTH; - long page_idx = page_no-1, kids_length = 1, i = 0; - - while (--depth && i != kids_length) { - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) { - if (media_box) - pdf_release_obj(media_box); - media_box = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { - if (rotate) - pdf_release_obj(rotate); - rotate = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { - if (resources) - pdf_release_obj(resources); - resources = tmp; - } - - kids = pdf_deref_obj(pdf_lookup_dict(page_tree, "Kids")); - if (!kids) - break; - else if (!PDF_OBJ_ARRAYTYPE(kids)) { - pdf_release_obj(kids); - goto error; - } - 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)); - if (!PDF_OBJ_DICTTYPE(page_tree)) - goto error; - - tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); - if (PDF_OBJ_NUMBERTYPE(tmp)) { - /* Pages object */ - count = pdf_number_value(tmp); - pdf_release_obj(tmp); - } else if (!tmp) - /* Page object */ - count = 1; - else { - pdf_release_obj(tmp); - goto error; - } - - if (page_idx < count) - break; - - page_idx -= count; - } - - pdf_release_obj(kids); - } - - if (!depth || kids_length == i) { - if (media_box) - pdf_release_obj(media_box); - if (crop_box) - pdf_release_obj(crop_box); - goto error; - } - - if (crop_box) - box = crop_box; - else - if (!(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox"))) && - !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox"))) && - !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox"))) && - media_box) { - box = media_box; - media_box = NULL; - } - if (media_box) - pdf_release_obj(media_box); - } - - if (!PDF_OBJ_ARRAYTYPE(box) || pdf_array_length(box) != 4 || - !PDF_OBJ_DICTTYPE(resources)) - goto error; - - if (PDF_OBJ_NUMBERTYPE(rotate)) { - if (pdf_number_value(rotate)) - WARN("<< /Rotate %d >> found. (Not supported yet)", - (int) pdf_number_value(rotate)); - pdf_release_obj(rotate); - rotate = NULL; - } else if (rotate) - goto error; - - { - int i; - - for (i = 4; i--; ) { - double x; - pdf_obj *tmp = pdf_deref_obj(pdf_get_array(box, i)); - if (!PDF_OBJ_NUMBERTYPE(tmp)) { - pdf_release_obj(tmp); - goto error; - } - x = pdf_number_value(tmp); - switch (i) { - case 0: bbox->llx = x; break; - case 1: bbox->lly = x; break; - case 2: bbox->urx = x; break; - case 3: bbox->ury = x; break; - } - pdf_release_obj(tmp); - } - } - - pdf_release_obj(box); - - if (resources_p) - *resources_p = resources; - else if (resources) - pdf_release_obj(resources); - - return page_tree; - - error: - WARN("Cannot parse document. Broken PDF file?"); - error_silent: - if (box) - pdf_release_obj(box); - if (rotate) - pdf_release_obj(rotate); - if (resources) - pdf_release_obj(resources); - if (page_tree) - pdf_release_obj(page_tree); - - return NULL; -} - -#ifndef BOOKMARKS_OPEN_DEFAULT -#define BOOKMARKS_OPEN_DEFAULT 0 -#endif - -static int clean_bookmarks (pdf_olitem *item); -static int flush_bookmarks (pdf_olitem *item, - pdf_obj *parent_ref, - pdf_obj *parent_dict); - -static void -pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth) -{ - pdf_olitem *item; - -#define MAX_OUTLINE_DEPTH 256u - p->opt.outline_open_depth = - ((bm_open_depth >= 0) ? - bm_open_depth : MAX_OUTLINE_DEPTH - bm_open_depth); - - p->outlines.current_depth = 1; - - item = NEW(1, pdf_olitem); - item->dict = NULL; - item->next = NULL; - item->first = NULL; - item->parent = NULL; - item->is_open = 1; - - p->outlines.current = item; - p->outlines.first = item; - - return; -} - -static int -clean_bookmarks (pdf_olitem *item) -{ - pdf_olitem *next; - - while (item) { - next = item->next; - if (item->dict) - pdf_release_obj(item->dict); - if (item->first) - clean_bookmarks(item->first); - RELEASE(item); - - item = next; - } - - return 0; -} - -static int -flush_bookmarks (pdf_olitem *node, - pdf_obj *parent_ref, pdf_obj *parent_dict) -{ - int retval; - int count; - pdf_olitem *item; - pdf_obj *this_ref, *prev_ref, *next_ref; - - ASSERT(node->dict); - - this_ref = pdf_ref_obj(node->dict); - pdf_add_dict(parent_dict, - pdf_new_name("First"), pdf_link_obj(this_ref)); - - retval = 0; - for (item = node, prev_ref = NULL; - item && item->dict; item = item->next) { - if (item->first && item->first->dict) { - count = flush_bookmarks(item->first, this_ref, item->dict); - if (item->is_open) { - pdf_add_dict(item->dict, - pdf_new_name("Count"), - pdf_new_number(count)); - retval += count; - } else { - pdf_add_dict(item->dict, - pdf_new_name("Count"), - pdf_new_number(-count)); - } - } - pdf_add_dict(item->dict, - pdf_new_name("Parent"), - pdf_link_obj(parent_ref)); - if (prev_ref) { - pdf_add_dict(item->dict, - pdf_new_name("Prev"), - prev_ref); - } - if (item->next && item->next->dict) { - next_ref = pdf_ref_obj(item->next->dict); - pdf_add_dict(item->dict, - pdf_new_name("Next"), - pdf_link_obj(next_ref)); - } else { - next_ref = NULL; - } - - pdf_release_obj(item->dict); - item->dict = NULL; - - prev_ref = this_ref; - this_ref = next_ref; - retval++; - } - - pdf_add_dict(parent_dict, - pdf_new_name("Last"), - pdf_link_obj(prev_ref)); - - pdf_release_obj(prev_ref); - pdf_release_obj(node->dict); - node->dict = NULL; - - return retval; -} - -int -pdf_doc_bookmarks_up (void) -{ - pdf_doc *p = &pdoc; - pdf_olitem *parent, *item; - - item = p->outlines.current; - if (!item || !item->parent) { - WARN("Can't go up above the bookmark root node!"); - return -1; - } - parent = item->parent; - item = parent->next; - if (!parent->next) { - parent->next = item = NEW(1, pdf_olitem); - item->dict = NULL; - item->first = NULL; - item->next = NULL; - item->is_open = 0; - item->parent = parent->parent; - } - p->outlines.current = item; - p->outlines.current_depth--; - - return 0; -} - -int -pdf_doc_bookmarks_down (void) -{ - pdf_doc *p = &pdoc; - pdf_olitem *item, *first; - - item = p->outlines.current; - if (!item->dict) { - pdf_obj *tcolor, *action; - - WARN("Empty bookmark node!"); - WARN("You have tried to jump more than 1 level."); - - item->dict = pdf_new_dict(); - -#define TITLE_STRING "" - pdf_add_dict(item->dict, - pdf_new_name("Title"), - pdf_new_string(TITLE_STRING, strlen(TITLE_STRING))); - - tcolor = pdf_new_array(); - pdf_add_array(tcolor, pdf_new_number(1.0)); - pdf_add_array(tcolor, pdf_new_number(0.0)); - pdf_add_array(tcolor, pdf_new_number(0.0)); - pdf_add_dict (item->dict, - pdf_new_name("C"), pdf_link_obj(tcolor)); - pdf_release_obj(tcolor); - - pdf_add_dict (item->dict, - pdf_new_name("F"), pdf_new_number(1.0)); - -#define JS_CODE "app.alert(\"The author of this document made this bookmark item empty!\", 3, 0)" - action = pdf_new_dict(); - pdf_add_dict(action, - pdf_new_name("S"), pdf_new_name("JavaScript")); - pdf_add_dict(action, - pdf_new_name("JS"), pdf_new_string(JS_CODE, strlen(JS_CODE))); - pdf_add_dict(item->dict, - pdf_new_name("A"), pdf_link_obj(action)); - pdf_release_obj(action); - } - - item->first = first = NEW(1, pdf_olitem); - first->dict = NULL; - first->is_open = 0; - first->parent = item; - first->next = NULL; - first->first = NULL; - - p->outlines.current = first; - p->outlines.current_depth++; - - return 0; -} - -int -pdf_doc_bookmarks_depth (void) -{ - pdf_doc *p = &pdoc; - - return p->outlines.current_depth; -} - -void -pdf_doc_bookmarks_add (pdf_obj *dict, int is_open) -{ - pdf_doc *p = &pdoc; - pdf_olitem *item, *next; - - ASSERT(p && dict); - - item = p->outlines.current; - - if (!item) { - item = NEW(1, pdf_olitem); - item->parent = NULL; - p->outlines.first = item; - } else if (item->dict) { /* go to next item */ - item = item->next; - } - -#define BMOPEN(b,p) (((b) < 0) ? (((p)->outlines.current_depth > (p)->opt.outline_open_depth) ? 0 : 1) : (b)) - -#if 0 - item->dict = pdf_link_obj(dict); -#endif - item->dict = dict; - item->first = NULL; - item->is_open = BMOPEN(is_open, p); - - item->next = next = NEW(1, pdf_olitem); - next->dict = NULL; - next->parent = item->parent; - next->first = NULL; - next->is_open = -1; - next->next = NULL; - - p->outlines.current = item; - - pdf_doc_add_goto(dict); - - return; -} - -static void -pdf_doc_close_bookmarks (pdf_doc *p) -{ - pdf_obj *catalog = p->root.dict; - pdf_olitem *item; - int count; - pdf_obj *bm_root, *bm_root_ref; - - item = p->outlines.first; - if (item->dict) { - bm_root = pdf_new_dict(); - bm_root_ref = pdf_ref_obj(bm_root); - count = flush_bookmarks(item, bm_root_ref, bm_root); - pdf_add_dict(bm_root, - pdf_new_name("Count"), - pdf_new_number(count)); - pdf_add_dict(catalog, - pdf_new_name("Outlines"), - bm_root_ref); - pdf_release_obj(bm_root); - } - clean_bookmarks(item); - - p->outlines.first = NULL; - p->outlines.current = NULL; - p->outlines.current_depth = 0; - - return; -} - - -static const char *name_dict_categories[] = { - "Dests", "AP", "JavaScript", "Pages", - "Templates", "IDS", "URLS", "EmbeddedFiles", - "AlternatePresentations", "Renditions" -}; -#define NUM_NAME_CATEGORY (sizeof(name_dict_categories)/sizeof(name_dict_categories[0])) - -static void -pdf_doc_init_names (pdf_doc *p, int check_gotos) -{ - int i; - - p->root.names = NULL; - - p->names = NEW(NUM_NAME_CATEGORY + 1, struct name_dict); - for (i = 0; i < NUM_NAME_CATEGORY; i++) { - p->names[i].category = name_dict_categories[i]; - p->names[i].data = strcmp(name_dict_categories[i], "Dests") ? - NULL : pdf_new_name_tree(); - /* - * We need a non-null entry for PDF destinations in order to find - * broken links even if no destination is defined in the DVI file. - */ - } - p->names[NUM_NAME_CATEGORY].category = NULL; - p->names[NUM_NAME_CATEGORY].data = NULL; - - p->check_gotos = check_gotos; - ht_init_table(&p->gotos, (void (*) (void *)) pdf_release_obj); - - return; -} - -int -pdf_doc_add_names (const char *category, - const void *key, int keylen, pdf_obj *value) -{ - pdf_doc *p = &pdoc; - int i; - - for (i = 0; p->names[i].category != NULL; i++) { - if (!strcmp(p->names[i].category, category)) { - break; - } - } - if (p->names[i].category == NULL) { - WARN("Unknown name dictionary category \"%s\".", category); - return -1; - } - if (!p->names[i].data) { - p->names[i].data = pdf_new_name_tree(); - } - - return pdf_names_add_object(p->names[i].data, key, keylen, value); -} - -static void -pdf_doc_add_goto (pdf_obj *annot_dict) -{ - pdf_obj *subtype = NULL, *A = NULL, *S = NULL, *D = NULL, *D_new, *dict; - const char *dest, *key; - - if (!pdoc.check_gotos) - return; - - /* - * An annotation dictionary coming from an annotation special - * must have a "Subtype". An annotation dictionary coming from - * an outline special has none. - */ - subtype = pdf_deref_obj(pdf_lookup_dict(annot_dict, "Subtype")); - if (subtype) { - if (PDF_OBJ_UNDEFINED(subtype)) - goto undefined; - else if (!PDF_OBJ_NAMETYPE(subtype)) - goto error; - else if (strcmp(pdf_name_value(subtype), "Link")) - goto cleanup; - } - - dict = annot_dict; - key = "Dest"; - D = pdf_deref_obj(pdf_lookup_dict(annot_dict, key)); - if (PDF_OBJ_UNDEFINED(D)) - goto undefined; - - A = pdf_deref_obj(pdf_lookup_dict(annot_dict, "A")); - if (A) { - if (PDF_OBJ_UNDEFINED(A)) - goto undefined; - else if (D || !PDF_OBJ_DICTTYPE(A)) - goto error; - else { - S = pdf_deref_obj(pdf_lookup_dict(A, "S")); - if (PDF_OBJ_UNDEFINED(S)) - goto undefined; - else if (!PDF_OBJ_NAMETYPE(S)) - goto error; - else if (strcmp(pdf_name_value(S), "GoTo")) - goto cleanup; - - dict = A; - key = "D"; - D = pdf_deref_obj(pdf_lookup_dict(A, key)); - } - } - - if (PDF_OBJ_STRINGTYPE(D)) - dest = (char *) pdf_string_value(D); -#if 0 - /* Names as destinations are not supported by dvipdfmx */ - else if (PDF_OBJ_NAMETYPE(D)) - dest = pdf_name_value(D); -#endif - else if (PDF_OBJ_ARRAYTYPE(D)) - goto cleanup; - else if (PDF_OBJ_UNDEFINED(D)) - goto undefined; - else - goto error; - - D_new = ht_lookup_table(&pdoc.gotos, dest, strlen(dest)); - if (!D_new) { - char buf[10]; - - /* We use hexadecimal notation for our numeric destinations. - * Other bases (e.g., 10+26 or 10+2*26) would be more efficient. - */ - sprintf(buf, "%lx", ht_table_size(&pdoc.gotos)); - D_new = pdf_new_string(buf, strlen(buf)); - ht_append_table(&pdoc.gotos, dest, strlen(dest), D_new); - } - - { - pdf_obj *key_obj = pdf_new_name(key); - if (!pdf_add_dict(dict, key_obj, pdf_link_obj(D_new))) - pdf_release_obj(key_obj); - } - - cleanup: - if (subtype) - pdf_release_obj(subtype); - if (A) - pdf_release_obj(A); - if (S) - pdf_release_obj(S); - if (D) - pdf_release_obj(D); - - return; - - error: - WARN("Unknown PDF annotation format. Output file may be broken."); - goto cleanup; - - undefined: - WARN("Cannot optimize PDF annotations. Output file may be broken." - " Please restart with option \"-C 0x10\"\n"); - goto cleanup; -} - -#ifndef XETEX -static void -warn_undef_dests (struct ht_table *dests, struct ht_table *gotos) -{ - struct ht_iter iter; - - if (ht_set_iter(gotos, &iter) < 0) - return; - - do { - int keylen; - char *key = ht_iter_getkey(&iter, &keylen); - if (!ht_lookup_table(dests, key, keylen)) { - char *dest = NEW(keylen+1, char); - memcpy(dest, key, keylen); - dest[keylen] = 0; - WARN("PDF destination \"%s\" not defined.", dest); - RELEASE(dest); - } - } while (ht_iter_next(&iter) >= 0); - - ht_clear_iter(&iter); -} -#endif - -static void -pdf_doc_close_names (pdf_doc *p) -{ - pdf_obj *tmp; - int i; - - for (i = 0; p->names[i].category != NULL; i++) { - if (p->names[i].data) { - struct ht_table *data = p->names[i].data; - pdf_obj *name_tree; - long count; - - if (!pdoc.check_gotos || strcmp(p->names[i].category, "Dests")) - name_tree = pdf_names_create_tree(data, &count, NULL); - else { - name_tree = pdf_names_create_tree(data, &count, &pdoc.gotos); - - if (verbose && count < data->count) - MESG("\nRemoved %ld unused PDF destinations\n", data->count-count); - - if (count < pdoc.gotos.count) - warn_undef_dests(data, &pdoc.gotos); - } - - if (name_tree) { - if (!p->root.names) - p->root.names = pdf_new_dict(); - pdf_add_dict(p->root.names, - pdf_new_name(p->names[i].category), - pdf_ref_obj(name_tree)); - pdf_release_obj(name_tree); - } - pdf_delete_name_tree(&p->names[i].data); - } - } - - if (p->root.names) { - tmp = pdf_lookup_dict(p->root.dict, "Names"); - if (!tmp) { - pdf_add_dict(p->root.dict, - pdf_new_name("Names"), - pdf_ref_obj (p->root.names)); - } else if (PDF_OBJ_DICTTYPE(tmp)) { - pdf_merge_dict(p->root.names, tmp); - pdf_add_dict(p->root.dict, - pdf_new_name("Names"), - pdf_ref_obj (p->root.names)); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify Names dictionary."); - } - pdf_release_obj(p->root.names); - p->root.names = NULL; - } - - RELEASE(p->names); - p->names = NULL; - - ht_clear_table(&p->gotos); - - return; -} - - -void -pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, - pdf_obj *annot_dict, int new_annot) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - pdf_obj *rect_array; - double annot_grow = p->opt.annot_grow; - double xpos, ypos; - pdf_rect annbox; - - page = doc_get_page_entry(p, page_no); - if (!page->annots) - page->annots = pdf_new_array(); - - { - pdf_rect mediabox; - - pdf_doc_get_mediabox(page_no, &mediabox); - pdf_dev_get_coord(&xpos, &ypos); - annbox.llx = rect->llx - xpos; annbox.lly = rect->lly - ypos; - annbox.urx = rect->urx - xpos; annbox.ury = rect->ury - ypos; - - if (annbox.llx < mediabox.llx || annbox.urx > mediabox.urx || - annbox.lly < mediabox.lly || annbox.ury > mediabox.ury) { - WARN("Annotation out of page boundary."); - WARN("Current page's MediaBox: [%g %g %g %g]", - mediabox.llx, mediabox.lly, mediabox.urx, mediabox.ury); - WARN("Annotation: [%g %g %g %g]", - annbox.llx, annbox.lly, annbox.urx, annbox.ury); - WARN("Maybe incorrect paper size specified."); - } - if (annbox.llx > annbox.urx || annbox.lly > annbox.ury) { - WARN("Rectangle with negative width/height: [%g %g %g %g]", - annbox.llx, annbox.lly, annbox.urx, annbox.ury); - } - } - - rect_array = pdf_new_array(); - pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.llx - annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.lly - annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.urx + annot_grow, 0.001))); - pdf_add_array(rect_array, pdf_new_number(ROUND(annbox.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)); - - if (new_annot) - pdf_doc_add_goto(annot_dict); - - return; -} - - -/* - * PDF Article Thread - */ -static void -pdf_doc_init_articles (pdf_doc *p) -{ - p->root.threads = NULL; - - p->articles.num_entries = 0; - p->articles.max_entries = 0; - p->articles.entries = NULL; - - return; -} - -void -pdf_doc_begin_article (const char *article_id, pdf_obj *article_info) -{ - pdf_doc *p = &pdoc; - pdf_article *article; - - if (article_id == NULL || strlen(article_id) == 0) - ERROR("Article thread without internal identifier."); - - if (p->articles.num_entries >= p->articles.max_entries) { - p->articles.max_entries += PDFDOC_ARTICLE_ALLOC_SIZE; - p->articles.entries = RENEW(p->articles.entries, - p->articles.max_entries, struct pdf_article); - } - article = &(p->articles.entries[p->articles.num_entries]); - - article->id = NEW(strlen(article_id)+1, char); - strcpy(article->id, article_id); - article->info = article_info; - article->num_beads = 0; - article->max_beads = 0; - article->beads = NULL; - - p->articles.num_entries++; - - return; -} - -#if 0 -void -pdf_doc_end_article (const char *article_id) -{ - return; /* no-op */ -} -#endif - -static pdf_bead * -find_bead (pdf_article *article, const char *bead_id) -{ - pdf_bead *bead; - long i; - - bead = NULL; - for (i = 0; i < article->num_beads; i++) { - if (!strcmp(article->beads[i].id, bead_id)) { - bead = &(article->beads[i]); - break; - } - } - - return bead; -} - -void -pdf_doc_add_bead (const char *article_id, - const char *bead_id, long page_no, const pdf_rect *rect) -{ - pdf_doc *p = &pdoc; - pdf_article *article; - pdf_bead *bead; - long i; - - if (!article_id) { - ERROR("No article identifier specified."); - } - - article = NULL; - for (i = 0; i < p->articles.num_entries; i++) { - if (!strcmp(p->articles.entries[i].id, article_id)) { - article = &(p->articles.entries[i]); - break; - } - } - if (!article) { - ERROR("Specified article thread that doesn't exist."); - return; - } - - bead = bead_id ? find_bead(article, bead_id) : NULL; - if (!bead) { - if (article->num_beads >= article->max_beads) { - article->max_beads += PDFDOC_BEAD_ALLOC_SIZE; - article->beads = RENEW(article->beads, - article->max_beads, struct pdf_bead); - for (i = article->num_beads; i < article->max_beads; i++) { - article->beads[i].id = NULL; - article->beads[i].page_no = -1; - } - } - bead = &(article->beads[article->num_beads]); - if (bead_id) { - bead->id = NEW(strlen(bead_id)+1, char); - strcpy(bead->id, bead_id); - } else { - bead->id = NULL; - } - article->num_beads++; - } - bead->rect.llx = rect->llx; - bead->rect.lly = rect->lly; - bead->rect.urx = rect->urx; - bead->rect.ury = rect->ury; - bead->page_no = page_no; - - return; -} - -static pdf_obj * -make_article (pdf_doc *p, - pdf_article *article, - const char **bead_ids, int num_beads, - pdf_obj *article_info) -{ - pdf_obj *art_dict; - pdf_obj *first, *prev, *last; - long i, n; - - if (!article) - return NULL; - - art_dict = pdf_new_dict(); - first = prev = last = NULL; - /* - * The bead_ids represents logical order of beads in an article thread. - * If bead_ids is not given, we create an article thread in the order of - * beads appeared. - */ - n = bead_ids ? num_beads : article->num_beads; - for (i = 0; i < n; i++) { - pdf_bead *bead; - - bead = bead_ids ? find_bead(article, bead_ids[i]) : &(article->beads[i]); - if (!bead || bead->page_no < 0) { - continue; - } - last = pdf_new_dict(); - if (prev == NULL) { - first = last; - pdf_add_dict(first, - pdf_new_name("T"), pdf_ref_obj(art_dict)); - } else { - pdf_add_dict(prev, - pdf_new_name("N"), pdf_ref_obj(last)); - pdf_add_dict(last, - pdf_new_name("V"), pdf_ref_obj(prev)); - /* We must link first to last. */ - if (prev != first) - pdf_release_obj(prev); - } - - /* Realize bead now. */ - { - pdf_page *page; - pdf_obj *rect; - - page = doc_get_page_entry(p, bead->page_no); - if (!page->beads) { - page->beads = pdf_new_array(); - } - pdf_add_dict(last, pdf_new_name("P"), pdf_link_obj(page->page_ref)); - rect = pdf_new_array(); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.llx, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.lly, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.urx, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.ury, 0.01))); - pdf_add_dict (last, pdf_new_name("R"), rect); - pdf_add_array(page->beads, pdf_ref_obj(last)); - } - - prev = last; - } - - if (first && last) { - pdf_add_dict(last, - pdf_new_name("N"), pdf_ref_obj(first)); - pdf_add_dict(first, - pdf_new_name("V"), pdf_ref_obj(last)); - if (first != last) { - pdf_release_obj(last); - } - pdf_add_dict(art_dict, - pdf_new_name("F"), pdf_ref_obj(first)); - /* If article_info is supplied, we override article->info. */ - if (article_info) { - pdf_add_dict(art_dict, - pdf_new_name("I"), article_info); - } else if (article->info) { - pdf_add_dict(art_dict, - pdf_new_name("I"), pdf_ref_obj(article->info)); - pdf_release_obj(article->info); - article->info = NULL; /* We do not write as object reference. */ - } - pdf_release_obj(first); - } else { - pdf_release_obj(art_dict); - art_dict = NULL; - } - - return art_dict; -} - -static void -clean_article (pdf_article *article) -{ - if (!article) - return; - - if (article->beads) { - long i; - - for (i = 0; i < article->num_beads; i++) { - if (article->beads[i].id) - RELEASE(article->beads[i].id); - } - RELEASE(article->beads); - article->beads = NULL; - } - - if (article->id) - RELEASE(article->id); - article->id = NULL; - article->num_beads = 0; - article->max_beads = 0; - - return; -} - -static void -pdf_doc_close_articles (pdf_doc *p) -{ - int i; - - for (i = 0; i < p->articles.num_entries; i++) { - pdf_article *article; - - article = &(p->articles.entries[i]); - if (article->beads) { - pdf_obj *art_dict; - - art_dict = make_article(p, article, NULL, 0, NULL); - if (!p->root.threads) { - p->root.threads = pdf_new_array(); - } - pdf_add_array(p->root.threads, pdf_ref_obj(art_dict)); - pdf_release_obj(art_dict); - } - clean_article(article); - } - RELEASE(p->articles.entries); - p->articles.entries = NULL; - p->articles.num_entries = 0; - p->articles.max_entries = 0; - - if (p->root.threads) { - pdf_add_dict(p->root.dict, - pdf_new_name("Threads"), - pdf_ref_obj (p->root.threads)); - pdf_release_obj(p->root.threads); - p->root.threads = NULL; - } - - return; -} - -/* page_no = 0 for root page tree node. */ -void -pdf_doc_set_mediabox (unsigned page_no, const pdf_rect *mediabox) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - if (page_no == 0) { - p->pages.mediabox.llx = mediabox->llx; - p->pages.mediabox.lly = mediabox->lly; - p->pages.mediabox.urx = mediabox->urx; - p->pages.mediabox.ury = mediabox->ury; - } else { - page = doc_get_page_entry(p, page_no); - page->cropbox.llx = mediabox->llx; - page->cropbox.lly = mediabox->lly; - page->cropbox.urx = mediabox->urx; - page->cropbox.ury = mediabox->ury; - page->flags |= USE_MY_MEDIABOX; - } - - return; -} - -void -pdf_doc_get_mediabox (unsigned page_no, pdf_rect *mediabox) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - if (page_no == 0) { - mediabox->llx = p->pages.mediabox.llx; - mediabox->lly = p->pages.mediabox.lly; - mediabox->urx = p->pages.mediabox.urx; - mediabox->ury = p->pages.mediabox.ury; - } else { - page = doc_get_page_entry(p, page_no); - if (page->flags & USE_MY_MEDIABOX) { - mediabox->llx = page->cropbox.llx; - mediabox->lly = page->cropbox.lly; - mediabox->urx = page->cropbox.urx; - mediabox->ury = page->cropbox.ury; - } else { - mediabox->llx = p->pages.mediabox.llx; - mediabox->lly = p->pages.mediabox.lly; - mediabox->urx = p->pages.mediabox.urx; - mediabox->ury = p->pages.mediabox.ury; - } - } - - return; -} - -pdf_obj * -pdf_doc_current_page_resources (void) -{ - pdf_obj *resources; - pdf_doc *p = &pdoc; - pdf_page *currentpage; - - if (p->pending_forms) { - if (p->pending_forms->form.resources) { - resources = p->pending_forms->form.resources; - } else { - resources = p->pending_forms->form.resources = pdf_new_dict(); - } - } else { - currentpage = LASTPAGE(p); - if (currentpage->resources) { - resources = currentpage->resources; - } else { - resources = currentpage->resources = pdf_new_dict(); - } - } - - return resources; -} - -pdf_obj * -pdf_doc_get_dictionary (const char *category) -{ - pdf_doc *p = &pdoc; - pdf_obj *dict = NULL; - - ASSERT(category); - - if (!strcmp(category, "Names")) { - if (!p->root.names) - p->root.names = pdf_new_dict(); - dict = p->root.names; - } else if (!strcmp(category, "Pages")) { - if (!p->root.pages) - p->root.pages = pdf_new_dict(); - dict = p->root.pages; - } else if (!strcmp(category, "Catalog")) { - if (!p->root.dict) - p->root.dict = pdf_new_dict(); - dict = p->root.dict; - } else if (!strcmp(category, "Info")) { - if (!p->info) - p->info = pdf_new_dict(); - dict = p->info; - } else if (!strcmp(category, "@THISPAGE")) { - /* Sorry for this... */ - pdf_page *currentpage; - - currentpage = LASTPAGE(p); - dict = currentpage->page_obj; - } - - if (!dict) { - ERROR("Document dict. \"%s\" not exist. ", category); - } - - return dict; -} - -long -pdf_doc_current_page_number (void) -{ - pdf_doc *p = &pdoc; - - return (long) (PAGECOUNT(p) + 1); -} - -pdf_obj * -pdf_doc_ref_page (unsigned long page_no) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - page = doc_get_page_entry(p, page_no); - if (!page->page_obj) { - page->page_obj = pdf_new_dict(); - page->page_ref = pdf_ref_obj(page->page_obj); - } - - return pdf_link_obj(page->page_ref); -} - -pdf_obj * -pdf_doc_get_reference (const char *category) -{ - pdf_obj *ref = NULL; - long page_no; - - ASSERT(category); - - page_no = pdf_doc_current_page_number(); - if (!strcmp(category, "@THISPAGE")) { - ref = pdf_doc_ref_page(page_no); - } else if (!strcmp(category, "@PREVPAGE")) { - if (page_no <= 1) { - ERROR("Reference to previous page, but no pages have been completed yet."); - } - ref = pdf_doc_ref_page(page_no - 1); - } else if (!strcmp(category, "@NEXTPAGE")) { - ref = pdf_doc_ref_page(page_no + 1); - } - - if (!ref) { - ERROR("Reference to \"%s\" not exist. ", category); - } - - return ref; -} - -static void -pdf_doc_new_page (pdf_doc *p) -{ - pdf_page *currentpage; - - if (PAGECOUNT(p) >= MAXPAGES(p)) { - doc_resize_page_entries(p, MAXPAGES(p) + PDFDOC_PAGES_ALLOC_SIZE); - } - - /* - * This is confusing. pdf_doc_finish_page() have increased page count! - */ - currentpage = LASTPAGE(p); - /* Was this page already instantiated by a forward reference to it? */ - if (!currentpage->page_ref) { - currentpage->page_obj = pdf_new_dict(); - currentpage->page_ref = pdf_ref_obj(currentpage->page_obj); - } - - currentpage->background = NULL; - currentpage->contents = pdf_new_stream(STREAM_COMPRESS); - currentpage->resources = pdf_new_dict(); - - currentpage->annots = NULL; - currentpage->beads = NULL; - - return; -} - -/* This only closes contents and resources. */ -static void -pdf_doc_finish_page (pdf_doc *p) -{ - pdf_page *currentpage; - - if (p->pending_forms) { - ERROR("A pending form XObject at the end of page."); - } - - currentpage = LASTPAGE(p); - if (!currentpage->page_obj) - currentpage->page_obj = pdf_new_dict(); - - /* - * Make Contents array. - */ - - /* - * Global BOP content stream. - * pdf_ref_obj() returns reference itself when the object is - * indirect reference, not reference to the indirect reference. - * We keep bop itself but not reference to it since it is - * expected to be small. - */ - if (p->pages.bop && - pdf_stream_length(p->pages.bop) > 0) { - currentpage->content_refs[0] = pdf_ref_obj(p->pages.bop); - } else { - currentpage->content_refs[0] = NULL; - } - /* - * Current page background content stream. - */ - if (currentpage->background) { - if (pdf_stream_length(currentpage->background) > 0) { - currentpage->content_refs[1] = pdf_ref_obj(currentpage->background); - pdf_add_stream (currentpage->background, "\n", 1); - } - pdf_release_obj(currentpage->background); - currentpage->background = NULL; - } else { - currentpage->content_refs[1] = NULL; - } - - /* Content body of current page */ - currentpage->content_refs[2] = pdf_ref_obj(currentpage->contents); - pdf_add_stream (currentpage->contents, "\n", 1); - pdf_release_obj(currentpage->contents); - currentpage->contents = NULL; - - /* - * Global EOP content stream. - */ - if (p->pages.eop && - pdf_stream_length(p->pages.eop) > 0) { - currentpage->content_refs[3] = pdf_ref_obj(p->pages.eop); - } else { - currentpage->content_refs[3] = NULL; - } - - /* - * Page resources. - */ - if (currentpage->resources) { - pdf_obj *procset; - /* - * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. - */ - - procset = pdf_new_array (); - pdf_add_array(procset, pdf_new_name("PDF")); - pdf_add_array(procset, pdf_new_name("Text")); - pdf_add_array(procset, pdf_new_name("ImageC")); - pdf_add_array(procset, pdf_new_name("ImageB")); - pdf_add_array(procset, pdf_new_name("ImageI")); - pdf_add_dict(currentpage->resources, pdf_new_name("ProcSet"), procset); - - pdf_add_dict(currentpage->page_obj, - pdf_new_name("Resources"), - pdf_ref_obj(currentpage->resources)); - pdf_release_obj(currentpage->resources); - currentpage->resources = NULL; - } - - if (manual_thumb_enabled) { - char *thumb_filename; - pdf_obj *thumb_ref; - - thumb_filename = NEW(strlen(thumb_basename)+7, char); - sprintf(thumb_filename, "%s.%ld", - thumb_basename, (p->pages.num_entries % 99999) + 1L); - thumb_ref = read_thumbnail(thumb_filename); - RELEASE(thumb_filename); - if (thumb_ref) - pdf_add_dict(currentpage->page_obj, pdf_new_name("Thumb"), thumb_ref); - } - - p->pages.num_entries++; - - return; -} - - -static pdf_color bgcolor; - -void -pdf_doc_set_bgcolor (const pdf_color *color) -{ - if (color) - pdf_color_copycolor(&bgcolor, color); - else { /* as clear... */ - pdf_color_white(&bgcolor); - } -} - -static void -doc_fill_page_background (pdf_doc *p) -{ - pdf_page *currentpage; - pdf_rect r; - int cm; - pdf_obj *saved_content; - - cm = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - if (!cm || pdf_color_is_white(&bgcolor)) { - return; - } - - pdf_doc_get_mediabox(pdf_doc_current_page_number(), &r); - - currentpage = LASTPAGE(p); - ASSERT(currentpage); - - if (!currentpage->background) - currentpage->background = pdf_new_stream(STREAM_COMPRESS); - - saved_content = currentpage->contents; - currentpage->contents = currentpage->background; - - pdf_dev_gsave(); - pdf_dev_set_nonstrokingcolor(&bgcolor); - pdf_dev_rectfill(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); - pdf_dev_grestore(); - - currentpage->contents = saved_content; - - return; -} - -void -pdf_doc_begin_page (double scale, double x_origin, double y_origin) -{ - pdf_doc *p = &pdoc; - pdf_tmatrix M; - - M.a = scale; M.b = 0.0; - M.c = 0.0 ; M.d = scale; - M.e = x_origin; - M.f = y_origin; - - /* pdf_doc_new_page() allocates page content stream. */ - pdf_doc_new_page(p); - pdf_dev_bop(&M); - - return; -} - -void -pdf_doc_end_page (void) -{ - pdf_doc *p = &pdoc; - - pdf_dev_eop(); - doc_fill_page_background(p); - - pdf_doc_finish_page(p); - - return; -} - -void -pdf_doc_add_page_content (const char *buffer, unsigned length) -{ - pdf_doc *p = &pdoc; - pdf_page *currentpage; - - if (p->pending_forms) { - pdf_add_stream(p->pending_forms->form.contents, buffer, length); - } else { - currentpage = LASTPAGE(p); - pdf_add_stream(currentpage->contents, buffer, length); - } - - return; -} - -static char *doccreator = NULL; /* Ugh */ - -void -pdf_open_document (const char *filename, - int do_encryption, - double media_width, double media_height, - double annot_grow_amount, int bookmark_open_depth, - int check_gotos) -{ - pdf_doc *p = &pdoc; - - pdf_out_init(filename, do_encryption); - - pdf_doc_init_catalog(p); - - p->opt.annot_grow = annot_grow_amount; - p->opt.outline_open_depth = bookmark_open_depth; - - pdf_init_resources(); - pdf_init_colors(); - pdf_init_fonts(); - /* Thumbnail want this to be initialized... */ - pdf_init_images(); - - pdf_doc_init_docinfo(p); - if (doccreator) { - pdf_add_dict(p->info, - pdf_new_name("Creator"), - pdf_new_string(doccreator, strlen(doccreator))); - RELEASE(doccreator); doccreator = NULL; - } - - pdf_doc_init_bookmarks(p, bookmark_open_depth); - pdf_doc_init_articles (p); - pdf_doc_init_names (p, check_gotos); - pdf_doc_init_page_tree(p, media_width, media_height); - - pdf_doc_set_bgcolor(NULL); - - if (do_encryption) { - pdf_obj *encrypt = pdf_encrypt_obj(); - pdf_set_encrypt(encrypt); - pdf_release_obj(encrypt); - } - pdf_set_id(pdf_enc_id_array()); - - /* Create a default name for thumbnail image files */ - if (manual_thumb_enabled) { - if (strlen(filename) > 4 && - !strncmp(".pdf", filename + strlen(filename) - 4, 4)) { - thumb_basename = NEW(strlen(filename)-4+1, char); - strncpy(thumb_basename, filename, strlen(filename)-4); - thumb_basename[strlen(filename)-4] = 0; - } else { - thumb_basename = NEW(strlen(filename)+1, char); - strcpy(thumb_basename, filename); - } - } - - p->pending_forms = NULL; - - return; -} - -void -pdf_doc_set_creator (const char *creator) -{ - if (!creator || - creator[0] == '\0') - return; - - doccreator = NEW(strlen(creator)+1, char); - strcpy(doccreator, creator); /* Ugh */ -} - - -void -pdf_close_document (void) -{ - pdf_doc *p = &pdoc; - - /* - * Following things were kept around so user can add dictionary items. - */ - pdf_doc_close_articles (p); - pdf_doc_close_names (p); - pdf_doc_close_bookmarks(p); - pdf_doc_close_page_tree(p); - pdf_doc_close_docinfo (p); - - pdf_doc_close_catalog (p); - - pdf_close_images(); - pdf_close_fonts (); - pdf_close_colors(); - - pdf_close_resources(); /* Should be at last. */ - - pdf_out_flush(); - - if (thumb_basename) - RELEASE(thumb_basename); - - return; -} - -/* - * All this routine does is give the form a name and add a unity scaling matrix. - * It fills in required fields. The caller must initialize the stream. - */ -static void -pdf_doc_make_xform (pdf_obj *xform, - pdf_rect *bbox, - pdf_tmatrix *matrix, - pdf_obj *resources, - pdf_obj *attrib) -{ - pdf_obj *xform_dict; - pdf_obj *tmp; - - xform_dict = pdf_stream_dict(xform); - pdf_add_dict(xform_dict, - pdf_new_name("Type"), pdf_new_name("XObject")); - pdf_add_dict(xform_dict, - pdf_new_name("Subtype"), pdf_new_name("Form")); - pdf_add_dict(xform_dict, - pdf_new_name("FormType"), pdf_new_number(1.0)); - - if (!bbox) - ERROR("No BoundingBox supplied."); - - tmp = pdf_new_array(); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->llx, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->lly, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->urx, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->ury, .001))); - pdf_add_dict(xform_dict, pdf_new_name("BBox"), tmp); - - if (matrix) { - tmp = pdf_new_array(); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->a, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->b, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->c, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->d, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->e, .001 ))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->f, .001 ))); - pdf_add_dict(xform_dict, pdf_new_name("Matrix"), tmp); - } - - if (attrib) { - pdf_merge_dict(xform_dict, attrib); - } - - pdf_add_dict(xform_dict, pdf_new_name("Resources"), resources); - - return; -} - -/* - * begin_form_xobj creates an xobject with its "origin" at - * xpos and ypos that is clipped to the specified bbox. Note - * that the origin is not the lower left corner of the bbox. - */ -int -pdf_doc_begin_grabbing (const char *ident, - double ref_x, double ref_y, const pdf_rect *cropbox) -{ - int xobj_id = -1; - pdf_doc *p = &pdoc; - pdf_form *form; - struct form_list_node *fnode; - xform_info info; - - pdf_dev_push_gstate(); - - fnode = NEW(1, struct form_list_node); - - fnode->prev = p->pending_forms; - fnode->q_depth = pdf_dev_current_depth(); - form = &fnode->form; - - /* - * The reference point of an Xobject is at the lower left corner - * of the bounding box. Since we would like to have an arbitrary - * reference point, we use a transformation matrix, translating - * the reference point to (0,0). - */ - - form->matrix.a = 1.0; form->matrix.b = 0.0; - form->matrix.c = 0.0; form->matrix.d = 1.0; - form->matrix.e = -ref_x; - form->matrix.f = -ref_y; - - form->cropbox.llx = ref_x + cropbox->llx; - form->cropbox.lly = ref_y + cropbox->lly; - form->cropbox.urx = ref_x + cropbox->urx; - form->cropbox.ury = ref_y + cropbox->ury; - - form->contents = pdf_new_stream(STREAM_COMPRESS); - form->resources = pdf_new_dict(); - - pdf_ximage_init_form_info(&info); - - info.matrix.a = 1.0; info.matrix.b = 0.0; - info.matrix.c = 0.0; info.matrix.d = 1.0; - info.matrix.e = -ref_x; - info.matrix.f = -ref_y; - - info.bbox.llx = cropbox->llx; - info.bbox.lly = cropbox->lly; - info.bbox.urx = cropbox->urx; - info.bbox.ury = cropbox->ury; - - /* Use reference since content itself isn't available yet. */ - xobj_id = pdf_ximage_defineresource(ident, - PDF_XOBJECT_TYPE_FORM, - &info, pdf_ref_obj(form->contents)); - - p->pending_forms = fnode; - - /* - * Make sure the object is self-contained by adding the - * current font and color to the object stream. - */ - pdf_dev_reset_fonts(); - pdf_dev_reset_color(1); /* force color operators to be added to stream */ - - return xobj_id; -} - -void -pdf_doc_end_grabbing (pdf_obj *attrib) -{ - pdf_form *form; - pdf_obj *procset; - pdf_doc *p = &pdoc; - struct form_list_node *fnode; - - if (!p->pending_forms) { - WARN("Tried to close a nonexistent form XOject."); - return; - } - - fnode = p->pending_forms; - form = &fnode->form; - - pdf_dev_grestore_to(fnode->q_depth); - - /* - * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. - */ - procset = pdf_new_array(); - pdf_add_array(procset, pdf_new_name("PDF")); - pdf_add_array(procset, pdf_new_name("Text")); - pdf_add_array(procset, pdf_new_name("ImageC")); - pdf_add_array(procset, pdf_new_name("ImageB")); - pdf_add_array(procset, pdf_new_name("ImageI")); - pdf_add_dict (form->resources, pdf_new_name("ProcSet"), procset); - - pdf_doc_make_xform(form->contents, - &form->cropbox, &form->matrix, - pdf_ref_obj(form->resources), attrib); - pdf_release_obj(form->resources); - pdf_release_obj(form->contents); - if (attrib) pdf_release_obj(attrib); - - p->pending_forms = fnode->prev; - - pdf_dev_pop_gstate(); - - pdf_dev_reset_fonts(); - pdf_dev_reset_color(0); - - RELEASE(fnode); - - return; -} - -static struct -{ - int dirty; - int broken; - pdf_obj *annot_dict; - pdf_rect rect; -} breaking_state = {0, 0, NULL, {0.0, 0.0, 0.0, 0.0}}; - -static void -reset_box (void) -{ - breaking_state.rect.llx = breaking_state.rect.lly = HUGE_VAL; - breaking_state.rect.urx = breaking_state.rect.ury = -HUGE_VAL; - breaking_state.dirty = 0; -} - -void -pdf_doc_begin_annot (pdf_obj *dict) -{ - breaking_state.annot_dict = dict; - breaking_state.broken = 0; - reset_box(); -} - -void -pdf_doc_end_annot (void) -{ - pdf_doc_break_annot(); - breaking_state.annot_dict = NULL; -} - -void -pdf_doc_break_annot (void) -{ - if (breaking_state.dirty) { - pdf_obj *annot_dict; - - /* Copy dict */ - annot_dict = pdf_new_dict(); - pdf_merge_dict(annot_dict, breaking_state.annot_dict); - pdf_doc_add_annot(pdf_doc_current_page_number(), &(breaking_state.rect), - annot_dict, !breaking_state.broken); - pdf_release_obj(annot_dict); - - breaking_state.broken = 1; - } - reset_box(); -} - -void -pdf_doc_expand_box (const pdf_rect *rect) -{ - breaking_state.rect.llx = MIN(breaking_state.rect.llx, rect->llx); - breaking_state.rect.lly = MIN(breaking_state.rect.lly, rect->lly); - breaking_state.rect.urx = MAX(breaking_state.rect.urx, rect->urx); - breaking_state.rect.ury = MAX(breaking_state.rect.ury, rect->ury); - breaking_state.dirty = 1; -} - -#if 0 -/* This should be number tree */ -void -pdf_doc_set_pagelabel (long pg_start, - const char *type, - const void *prefix, int prfx_len, long start) -{ - pdf_doc *p = &pdoc; - pdf_obj *label_dict; - - if (!p->root.pagelabels) - p->root.pagelabels = pdf_new_array(); - - label_dict = pdf_new_dict(); - if (!type || type[0] == '\0') /* Set back to default. */ - pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name("D")); - else { - if (type) - pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name(type)); - if (prefix && prfx_len > 0) - pdf_add_dict(label_dict, - pdf_new_name("P"), - pdf_new_string(prefix, prfx_len)); - if (start != 1) - pdf_add_dict(label_dict, - pdf_new_name("St"), pdf_new_number(start)); - } - - pdf_add_array(p->root.pagelabels, pdf_new_number(pg_start)); - pdf_add_array(p->root.pagelabels, label_dict); - - return; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/src/pdfdraw.c b/Build/source/texk/dvipdfm-x/src/pdfdraw.c deleted file mode 100644 index 6ef0a2d8dc2..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfdraw.c +++ /dev/null @@ -1,1884 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "error.h" -#include "mem.h" -#include "mfileio.h" -#include "dpxutil.h" -#include "numbers.h" - -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfcolor.h" - -#include "pdfdraw.h" - -#if 1 -typedef void pdf_dev; -#endif - - -/* - * Numbers are rounding to 0-5 fractional digits - * in output routine. - */ -#define detM(M) ((M).a * (M).d - (M).b * (M).c) -#define detP(M) ((M)->a * (M)->d - (M)->b * (M)->c) - - -static /* __inline__ */ int -inversematrix (pdf_tmatrix *W, const pdf_tmatrix *M) -{ - double det; - - det = detP(M); - if (fabs(det) < 1.e-8) { -#if 1 - WARN("Inverting matrix with zero determinant..."); -#endif - return -1; /* result is undefined. */ - } - - W->a = (M->d) / det; W->b = -(M->b) / det; - 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); - - return 0; -} - -/* pdf_coord as vector */ -#define vecprd(v,w) ((v).x * (w).x + (v).y * (w).y) -#define vecrot(v,w) ((v).x * (w).y - (v).y * (w).x) -#define dsign(v) (((v) >= 0.0) ? 1.0 : -1.0) -/* acos => [0, pi] */ -#define vecang(v,w) ( \ - dsign(vecrot((v),(w))) * \ - acos(vecprd((v),(w)) / sqrt(vecprd((v),(v)) * vecprd((w),(w)))) \ -) - -static /* __inline__ */ int -pdf_coord__equal (const pdf_coord *p1, const pdf_coord *p2) -{ - if (fabs(p1->x - p2->x) < 1.e-7 && - fabs(p1->y - p2->y) < 1.e-7) - return 1; - return 0; -} -#define COORD_EQUAL(p,q) pdf_coord__equal((p),(q)) - -#if 0 -static int -pdf_coord__sort_compar_X (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->x - p2->x); - - return 1; -} - -static int -pdf_coord__sort_compar_Y (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->y - p2->y); - - return 1; -} -#endif - - -static /* __inline__ */ int -pdf_coord__transform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c + M->e; - p->y = x * M->b + y * M->d + M->f; - - return 0; -} - -#if 0 -static /* __inline__ */ int -pdf_coord__itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c + W.e; - p->y = x * W.b + y * W.d + W.f; - - return 0; -} -#endif - -static /* __inline__ */ int -pdf_coord__dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c; - p->y = x * M->b + y * M->d; - - return 0; -} - -static /* __inline__ */ int -pdf_coord__idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c; - p->y = x * W.b + y * W.d; - - return 0; -} - - -/* Modify M itself */ -void -pdf_invertmatrix (pdf_tmatrix *M) -{ - pdf_tmatrix W; - double det; - - ASSERT(M); - - det = detP(M); - if (fabs(det) < 1.e-8) { - WARN("Inverting matrix with zero determinant..."); - W.a = 1.0; W.c = 0.0; - W.b = 0.0; W.d = 1.0; - W.e = 0.0; W.f = 0.0; - } else { - W.a = (M->d) / det; W.b = -(M->b) / det; - 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); - } - - pdf_copymatrix(M, &W); - - return; -} - - -typedef struct pa_elem_ -{ - int type; - pdf_coord p[3]; -} pa_elem; - -/* each subpath delimitted by moveto */ -struct pdf_path_ -{ - int num_paths; - int max_paths; - pa_elem *path; -}; - -static const struct { - char opchr; /* PDF operator char */ - int n_pts; /* number of *points* */ - const char *strkey; -} petypes[] = { -#define PE_TYPE__INVALID -1 -#define PE_TYPE__MOVETO 0 - {'m', 1, "moveto" }, -#define PE_TYPE__LINETO 1 - {'l', 1, "lineto" }, -#define PE_TYPE__CURVETO 2 - {'c', 3, "curveto" }, - /* no PS correspondence for v and y */ -#define PE_TYPE__CURVETO_V 3 - {'v', 2, "vcurveto"}, /* current point replicated */ -#define PE_TYPE__CURVETO_Y 4 - {'y', 2, "ycurveto"}, /* last point replicated */ -#define PE_TYPE__CLOSEPATH 5 - {'h', 0, "closepath"}, -#define PE_TYPE__TERMINATE 6 - {' ', 0, NULL} -}; - -#define PE_VALID(p) ((p) && \ - (p)->type > PE_TYPE__INVALID && (p)->type < PE_TYPE__TERMINATE) -#define PE_N_PTS(p) (PE_VALID((p)) ? petypes[(p)->type].n_pts : 0) -#define PE_OPCHR(p) (PE_VALID((p)) ? petypes[(p)->type].opchr : ' ') - -#define PA_LENGTH(pa) ((pa)->num_paths) - -#define GS_FLAG_CURRENTPOINT_SET (1 << 0) - - -static char fmt_buf[1024]; /* FIXME */ -#define FORMAT_BUFF_PTR(p) fmt_buf -#define FORMAT_BUFF_LEN(p) 1024 - -static void -init_a_path (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - p->max_paths = 0; - p->path = NULL; - - return; -} - -static void -pdf_path__clearpath (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - - return; -} - -static int -pdf_path__growpath (pdf_path *p, int max_pe) -{ - if (max_pe < p->max_paths) - return 0; - - p->max_paths = MAX(p->max_paths + 8, max_pe); - p->path = RENEW(p->path, p->max_paths, pa_elem); - - return 0; -} - -static void -clear_a_path (pdf_path *p) -{ - ASSERT(p); - - if (p->path) - RELEASE(p->path); - p->path = NULL; - p->num_paths = 0; - p->max_paths = 0; - - return; -} - -static int -pdf_path__copypath (pdf_path *p1, const pdf_path *p0) -{ - pa_elem *pe0, *pe1; - int i; - - pdf_path__growpath(p1, PA_LENGTH(p0)); - for (i = 0; i < PA_LENGTH(p0); i++) { - pe1 = &(p1->path[i]); - pe0 = &(p0->path[i]); - /* FIXME */ - pe1->type = pe0->type; - pe1->p[0].x = pe0->p[0].x; - pe1->p[0].y = pe0->p[0].y; - pe1->p[1].x = pe0->p[1].x; - pe1->p[1].y = pe0->p[1].y; - pe1->p[2].x = pe0->p[2].x; - pe1->p[2].y = pe0->p[2].y; - } - p1->num_paths = PA_LENGTH(p0); - - return 0; -} - - -/* start new subpath */ -static int -pdf_path__moveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - if (PA_LENGTH(pa) > 0) { - pe = &pa->path[pa->num_paths-1]; - if (pe->type == PE_TYPE__MOVETO) { - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - return 0; - } - } - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -/* Do 'compression' of path while adding new path elements. - * Sequantial moveto command will be replaced with a - * single moveto. If cp is not equal to the last point in pa, - * then moveto is inserted (starting new subpath). - * FIXME: - * 'moveto' must be used to enforce starting new path. - * This affects how 'closepath' is treated. - */ -static pa_elem * -pdf_path__next_pe (pdf_path *pa, const pdf_coord *cp) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 2); - if (PA_LENGTH(pa) == 0) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - - return &pa->path[pa->num_paths++]; - } - - pe = &pa->path[pa->num_paths-1]; - switch (pe->type) { - case PE_TYPE__MOVETO: - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - case PE_TYPE__LINETO: - if (!COORD_EQUAL(&pe->p[0], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO: - if (!COORD_EQUAL(&pe->p[2], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO_Y: - case PE_TYPE__CURVETO_V: - if (!COORD_EQUAL(&pe->p[1], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CLOSEPATH: - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - } - - return &pa->path[pa->num_paths++]; -} - -static int -pdf_path__transform (pdf_path *pa, const pdf_tmatrix *M) -{ - pa_elem *pe; - int n = 0, i; - - ASSERT(pa && M); - - for (i = 0; i < PA_LENGTH(pa); i++) { - pe = &(pa->path[i]); - n = PE_N_PTS(pe); - while (n-- > 0) - pdf_coord__transform(&(pe->p[n]), M); - } - - return 0; -} - - -/* Path Construction */ -static int -pdf_path__lineto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - pe->type = PE_TYPE__LINETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -static int -pdf_path__curveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1, - const pdf_coord *p2 - ) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - if (COORD_EQUAL(cp, p0)) { - pe->type = PE_TYPE__CURVETO_V; - pe->p[0].x = p1->x; - pe->p[0].y = p1->y; - pe->p[1].x = cp->x = p2->x; - pe->p[1].y = cp->y = p2->y; - } else if (COORD_EQUAL(p1, p2)) { - pe->type = PE_TYPE__CURVETO_Y; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = cp->x = p1->x; - pe->p[1].y = cp->y = p1->y; - } else { - pe->type = PE_TYPE__CURVETO; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = p1->x; - pe->p[1].y = p1->y; - pe->p[2].x = cp->x = p2->x; - pe->p[2].y = cp->y = p2->y; - } - - return 0; -} - -#if 0 -#define QB_TWO_THIRD (2.0/3.0) -#define QB_ONE_THIRD (1.0/3.0) - -static int -pdf_path__curveto_QB (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1 - ) -{ - pdf_coord q0, q1; - - q0.x = cp->x + QB_TWO_THIRD * (p0->x - cp->x); - q0.y = cp->y + QB_TWO_THIRD * (p0->y - cp->y); - q1.x = p0->x + QB_ONE_THIRD * (p1->x - p0->x); - q1.y = p0->y + QB_ONE_THIRD * (p1->y - p0->y); - /* q2 == p1 */ - - return pdf_path__curveto(pa, cp, &q0, &q1, p1); -} -#endif - - -/* This isn't specified as cp to somewhere. */ -static int -pdf_path__elliptarc (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *ca, /* ellipsis center */ - double r_x, /* x radius */ - double r_y, /* y radius */ - double xar, /* x-axis-rotation (deg!) */ - double a_0, /* start angle */ - double a_1, /* stop angle */ - int a_d /* arc orientation */ - ) -{ - double b, b_x, b_y; - double d_a, q; - pdf_coord p0, p1, p2, p3; - pdf_coord e0, e1; - pdf_tmatrix T; - int n_c; /* number of segments */ - int i, error = 0; - - if (fabs(r_x) < 1.e-8 || - fabs(r_y) < 1.e-8) - return -1; - - if (a_d < 0) { - for ( ; a_1 > a_0; a_1 -= 360.0); - } else { - for ( ; a_1 < a_0; a_0 -= 360.0); - } - - d_a = a_1 - a_0; - for (n_c = 1; fabs(d_a) > 90.0 * n_c; n_c++); - d_a /= n_c; - if (fabs(d_a) < 1.e-8) - return -1; - - a_0 *= M_PI / 180.0; - a_1 *= M_PI / 180.0; - d_a *= M_PI / 180.0; - xar *= M_PI / 180.0; - T.a = cos(xar); T.c = -sin(xar); - T.b = -T.c ; T.d = T.a; - T.e = 0.0 ; T.f = 0.0; - - /* A parameter that controls cb-curve (off-curve) points */ - b = 4.0 * (1.0 - cos(.5 * d_a)) / (3.0 * sin(.5 * d_a)); - b_x = r_x * b; - b_y = r_y * b; - - p0.x = r_x * cos(a_0); - p0.y = r_y * sin(a_0); - pdf_coord__transform(&p0, &T); - p0.x += ca->x; p0.y += ca->y; - if (PA_LENGTH(pa) == 0) { - pdf_path__moveto(pa, cp, &p0); - } else if (!COORD_EQUAL(cp, &p0)) { - pdf_path__lineto(pa, cp, &p0); /* add line seg */ - } - for (i = 0; !error && i < n_c; i++) { - q = a_0 + i * d_a; - e0.x = cos(q); e0.y = sin(q); - e1.x = cos(q + d_a); e1.y = sin(q + d_a); - - /* Condition for tangent vector requirs - * d1 = p1 - p0 = f ( sin a, -cos a) - * d2 = p2 - p3 = g ( sin b, -cos b) - * and from symmetry - * g^2 = f^2 - */ - p0.x = r_x * e0.x; /* s.p. */ - p0.y = r_y * e0.y; - p3.x = r_x * e1.x; /* e.p. */ - p3.y = r_y * e1.y; - - p1.x = -b_x * e0.y; - p1.y = b_y * e0.x; - p2.x = b_x * e1.y; - p2.y = -b_y * e1.x; - - pdf_coord__transform(&p0, &T); - pdf_coord__transform(&p1, &T); - pdf_coord__transform(&p2, &T); - pdf_coord__transform(&p3, &T); - p0.x += ca->x; p0.y += ca->y; - p3.x += ca->x; p3.y += ca->y; - p1.x += p0.x ; p1.y += p0.y ; - p2.x += p3.x ; p2.y += p3.y ; - - error = pdf_path__curveto(pa, &p0, &p1, &p2, &p3); - cp->x = p3.x; cp->y = p3.y; - } - - return error; -} - -static int -pdf_path__closepath (pdf_path *pa, pdf_coord *cp /* no arg */) -{ - pa_elem *pe = NULL; - int i; - - /* search for start point of the last subpath */ - for (i = PA_LENGTH(pa) - 1; i >= 0; i--) { - pe = &pa->path[i]; - if (pe->type == PE_TYPE__MOVETO) - break; - } - - if (!pe || i < 0) - return -1; /* No path or no start point(!) */ - - cp->x = pe->p[0].x; - cp->y = pe->p[0].y; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - - /* NOTE: - * Manually closed path without closepath is not - * affected by linejoin. A path with coincidental - * starting and ending point is not the same as - * 'closed' path. - */ - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__CLOSEPATH; - - return 0; -} - -/* - * x y width height re - * - * is equivalent to - * - * x y m - * (x + width) y l - * (x + width) (y + height) l - * x (y + height) l - * h - */ -/* Just for quick test */ -static /* __inline__ */ int -pdf_path__isarect (pdf_path *pa, - int f_ir /* fill-rule is ignorable */ - ) -{ - pa_elem *pe0, *pe1, *pe2, *pe3, *pe4; - - if (PA_LENGTH(pa) == 5) { - pe0 = &(pa->path[0]); - pe1 = &(pa->path[1]); - pe2 = &(pa->path[2]); - pe3 = &(pa->path[3]); - pe4 = &(pa->path[4]); - if (pe0->type == PE_TYPE__MOVETO && - pe1->type == PE_TYPE__LINETO && - pe2->type == PE_TYPE__LINETO && - pe3->type == PE_TYPE__LINETO && - pe4->type == PE_TYPE__CLOSEPATH) { - if (pe1->p[0].y - pe0->p[0].y == 0 && - pe2->p[0].x - pe1->p[0].x == 0 && - pe3->p[0].y - pe2->p[0].y == 0) { - if (pe1->p[0].x - pe0->p[0].x - == pe2->p[0].x - pe3->p[0].x) { - return 1; - } - /* Winding number is different but ignore it here. */ - } else if (f_ir && - pe1->p[0].x - pe0->p[0].x == 0 && - pe2->p[0].y - pe1->p[0].y == 0 && - pe3->p[0].x - pe2->p[0].x == 0) { - if (pe1->p[0].y - pe0->p[0].y - == pe2->p[0].y - pe3->p[0].y) { - return 1; - } - } - } - } - - return 0; -} - -/* Path Painting */ -/* F is obsoleted */ -#define PT_OP_VALID(c) ( \ - (c) == 'f' || (c) == 'F' || \ - (c) == 's' || (c) == 'S' || \ - (c) == 'b' || (c) == 'B' || \ - (c) == 'W' \ -) - -static /* __inline__ */ int -INVERTIBLE_MATRIX (const pdf_tmatrix *M) -{ - if (fabs(detP(M)) < 1.e-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; - } - return 0; -} - -/* rectfill, rectstroke, rectclip, recteoclip - * - * Draw isolated rectangle without actually doing - * gsave/grestore operation. - * - * TODO: - * linestyle, fill-opacity, stroke-opacity,.... - * As this routine draw a single graphics object - * each time, there should be options for specifying - * various drawing styles, which might inherite - * current graphcs state parameter. - */ -static int -pdf_dev__rectshape (pdf_dev *P, - const pdf_rect *r, - const pdf_tmatrix *M, - char opchr - ) -{ - char *buf = FORMAT_BUFF_PTR(P); - int len = 0; - int isclip = 0; - pdf_coord p; - double wd, ht; - - ASSERT(r && PT_OP_VALID(opchr)); - - isclip = (opchr == 'W') ? 1 : 0; - - /* disallow matrix for clipping. - * q ... clip Q does nothing and - * n M cm ... clip n alter CTM. - */ - if (M && (isclip || - !INVERTIBLE_MATRIX(M))) - return -1; - - graphics_mode(); - - buf[len++] = ' '; - if (!isclip) { - buf[len++] = 'q'; - if (M) { - buf[len++] = ' '; - len += pdf_sprint_matrix(buf + len, M); - buf[len++] = ' '; - buf[len++] = 'c'; buf[len++] = 'm'; - } - buf[len++] = ' '; - } - buf[len++] = 'n'; - - p.x = r->llx; p.y = r->lly; - wd = r->urx - r->llx; - ht = r->ury - r->lly; - buf[len++] = ' '; - len += pdf_sprint_coord (buf + len, &p); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, wd); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, ht); - buf[len++] = ' '; - buf[len++] = 'r'; buf[len++] = 'e'; - - { - buf[len++] = ' '; - buf[len++] = opchr; - - buf[len++] = ' '; - buf[len++] = isclip ? 'n' : 'Q'; - } - - pdf_doc_add_page_content(buf, len); /* op: q cm n re Q */ - - return 0; -} - -/* FIXME */ -static int -pdf_dev__flushpath (pdf_dev *P, - pdf_path *pa, - char opchr, - int rule, - int ignore_rule) -{ - pa_elem *pe, *pe1; - char *b = FORMAT_BUFF_PTR(P); - long b_len = FORMAT_BUFF_LEN(P); - pdf_rect r; /* FIXME */ - pdf_coord *pt; - int n_pts, n_seg; - int len = 0; - int isrect, i, j; - - ASSERT(pa && PT_OP_VALID(opchr)); - - if (PA_LENGTH(pa) <= 0) - return 0; - - graphics_mode(); - isrect = pdf_path__isarect(pa, ignore_rule); - if (isrect) { - pe = &(pa->path[0]); - pe1 = &(pa->path[2]); - - r.llx = pe->p[0].x; - r.lly = pe->p[0].y; - r.urx = pe1->p[0].x - pe->p[0].x; /* width... */ - r.ury = pe1->p[0].y - pe->p[0].y; /* height... */ - - b[len++] = ' '; - len += pdf_sprint_rect(b + len, &r); - b[len++] = ' '; - b[len++] = 'r'; - b[len++] = 'e'; - pdf_doc_add_page_content(b, len); /* op: re */ - len = 0; - } else { - n_seg = PA_LENGTH(pa); - for (i = 0, len = 0, pe = &pa->path[0]; - i < n_seg; pe++, i++) { - n_pts = PE_N_PTS(pe); - for (j = 0, pt = &pe->p[0]; - j < n_pts; j++, pt++) { - b[len++] = ' '; - len += pdf_sprint_coord(b + len, pt); - } - b[len++] = ' '; - b[len++] = PE_OPCHR(pe); - if (len + 128 > b_len) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - if (len > 0) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - - b[len++] = ' '; - b[len++] = opchr; - if (rule == PDF_FILL_RULE_EVENODD) - b[len++] = '*'; - - pdf_doc_add_page_content(b, len); /* op: f F s S b B W f* F* s* S* b* B* W* */ - - return 0; -} - - -/* Graphics State */ -typedef struct pdf_gstate_ -{ - pdf_coord cp; - - pdf_tmatrix matrix; /* cm, - */ - - pdf_color strokecolor; - pdf_color fillcolor; - /* colorspace here */ - - struct { - int num_dash; - double pattern[PDF_DASH_SIZE_MAX]; - double offset; - } linedash; /* d, D */ - - double linewidth; /* w, LW */ - - int linecap; /* J, LC */ - int linejoin; /* j, LJ */ - double miterlimit; /* M, ML */ - - int flatness; /* i, FL, 0 to 100 (0 for use device-default) */ - - /* internal */ - pdf_path path; - long flags; -} pdf_gstate; - - -typedef struct m_stack_elem -{ - void *data; - struct m_stack_elem *prev; -} m_stack_elem; - -typedef struct m_stack -{ - int size; - m_stack_elem *top; - m_stack_elem *bottom; -} m_stack; - -static void -m_stack_init (m_stack *stack) -{ - ASSERT(stack); - - stack->size = 0; - stack->top = NULL; - stack->bottom = NULL; - - return; -} - -static void -m_stack_push (m_stack *stack, void *data) -{ - m_stack_elem *elem; - - ASSERT(stack); - - elem = NEW(1, m_stack_elem); - elem->prev = stack->top; - elem->data = data; - - stack->top = elem; - if (stack->size == 0) - stack->bottom = elem; - - stack->size++; - - return; -} - -static void * -m_stack_pop (m_stack *stack) -{ - m_stack_elem *elem; - void *data; - - ASSERT(stack); - - if (stack->size == 0) - return NULL; - - data = stack->top->data; - elem = stack->top; - stack->top = elem->prev; - if (stack->size == 1) - stack->bottom = NULL; - RELEASE(elem); - - stack->size--; - - return data; -} - -static void * -m_stack_top (m_stack *stack) -{ - void *data; - - ASSERT(stack); - - if (stack->size == 0) - return NULL; - - data = stack->top->data; - - return data; -} - -#define m_stack_depth(s) ((s)->size) - -static m_stack gs_stack; - -static void -init_a_gstate (pdf_gstate *gs) -{ - gs->cp.x = 0.0; - gs->cp.y = 0.0; - - pdf_setmatrix(&gs->matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - - pdf_color_black(&gs->strokecolor); - pdf_color_black(&gs->fillcolor); - - gs->linedash.num_dash = 0; - gs->linedash.offset = 0; - gs->linecap = 0; - gs->linejoin = 0; - gs->linewidth = 1.0; - gs->miterlimit = 10.0; - - gs->flatness = 1; /* default to 1 in PDF */ - - /* Internal variables */ - gs->flags = 0; - init_a_path(&gs->path); - - return; -} - -static void -clear_a_gstate (pdf_gstate *gs) -{ - clear_a_path(&gs->path); - memset(gs, 0, sizeof(pdf_gstate)); - - return; -} - -static void -copy_a_gstate (pdf_gstate *gs1, pdf_gstate *gs2) -{ - int i; - - ASSERT(gs1 && gs2); - - gs1->cp.x = gs2->cp.x; - gs1->cp.y = gs2->cp.y; - - pdf_copymatrix(&gs1->matrix, &gs2->matrix); - - /* TODO: - * Path should be linked list and gsave only - * record starting point within path rather than - * copying whole path. - */ - pdf_path__copypath(&gs1->path, &gs2->path); - - gs1->linedash.num_dash = gs2->linedash.num_dash; - for (i = 0; i < gs2->linedash.num_dash; i++) { - gs1->linedash.pattern[i] = gs2->linedash.pattern[i]; - } - gs1->linedash.offset = gs2->linedash.offset; - - gs1->linecap = gs2->linecap; - gs1->linejoin = gs2->linejoin; - gs1->linewidth = gs2->linewidth; - gs1->miterlimit = gs2->miterlimit; - gs1->flatness = gs2->flatness; - - pdf_color_copycolor(&gs1->fillcolor , &gs2->fillcolor); - pdf_color_copycolor(&gs1->strokecolor, &gs2->strokecolor); - - return; -} - -void -pdf_dev_init_gstates (void) -{ - pdf_gstate *gs; - - m_stack_init(&gs_stack); - - gs = NEW(1, pdf_gstate); - init_a_gstate(gs); - - m_stack_push(&gs_stack, gs); /* Initial state */ - - return; -} - -void -pdf_dev_clear_gstates (void) -{ - pdf_gstate *gs; - - 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(&gs_stack)) != NULL) { - clear_a_gstate(gs); - RELEASE(gs); - } - return; -} - -int -pdf_dev_gsave (void) -{ - pdf_gstate *gs0, *gs1; - - gs0 = m_stack_top(&gs_stack); - gs1 = NEW(1, pdf_gstate); - init_a_gstate(gs1); - copy_a_gstate(gs1, gs0); - m_stack_push(&gs_stack, gs1); - - pdf_doc_add_page_content(" q", 2); /* op: q */ - - return 0; -} - -int -pdf_dev_grestore (void) -{ - pdf_gstate *gs; - - if (m_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = m_stack_pop(&gs_stack); - clear_a_gstate(gs); - RELEASE(gs); - - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - - pdf_dev_reset_fonts(); - - return 0; -} - - -int -pdf_dev_push_gstate (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs0; - - gs0 = NEW(1, pdf_gstate); - - init_a_gstate(gs0); - - m_stack_push(gss, gs0); - - return 0; -} - - -int -pdf_dev_pop_gstate (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs; - - if (m_stack_depth(gss) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = m_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - - return 0; -} - - -int -pdf_dev_current_depth (void) -{ - return (m_stack_depth(&gs_stack) - 1); /* 0 means initial state */ -} - -void -pdf_dev_grestore_to (int depth) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs; - - ASSERT(depth >= 0); - - if (m_stack_depth(gss) > depth + 1) { - WARN("Closing pending transformations at end of page/XObject."); - } - - while (m_stack_depth(gss) > depth + 1) { - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - gs = m_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - } - pdf_dev_reset_fonts(); - - return; -} - -int -pdf_dev_currentpoint (pdf_coord *p) -{ - m_stack *gss = &gs_stack; - 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 = &gs_stack; - 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) -{ - 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 */ - -#ifndef XETEX -/* - * mask == 0 means stroking color, mask == 0x20 nonstroking color - * - * force == 1 means that operators will be generated even if - * the color is the same as the current graphics state color - */ -void -pdf_dev_set_color (const pdf_color *color, char mask, int force) -{ - int len; - - pdf_gstate *gs = m_stack_top(&gs_stack); - pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; - - ASSERT(pdf_color_is_valid(color)); - - if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && - (force || pdf_color_compare(color, current)))) - /* If "color" is already the current color, then do nothing - * unless a color operator is forced - */ - return; - - graphics_mode(); - len = pdf_color_to_string(color, fmt_buf); - fmt_buf[len++] = ' '; - switch (pdf_color_type(color)) { - case PDF_COLORSPACE_TYPE_RGB: - fmt_buf[len++] = 'R' | mask; - fmt_buf[len++] = 'G' | mask; - break; - case PDF_COLORSPACE_TYPE_CMYK: - fmt_buf[len++] = 'K' | mask; - break; - case PDF_COLORSPACE_TYPE_GRAY: - fmt_buf[len++] = 'G' | mask; - break; - default: /* already verified the given color */ - break; - } - pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g */ - - pdf_color_copycolor(current, color); -} - -void -pdf_dev_reset_color (int force) -{ - pdf_color *sc, *fc; - - pdf_color_get_current(&sc, &fc); - pdf_dev_set_color(sc, 0, force); - pdf_dev_set_color(fc, 0x20, force); -} -#endif - -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 = {0, 0, 0, 0, 0, 0}; /* Init to avoid compiler warning */ - 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; - } - - { - buf[len++] = ' '; - len += pdf_sprint_matrix(buf + len, M); - buf[len++] = ' '; - buf[len++] = 'c'; - buf[len++] = 'm'; - pdf_doc_add_page_content(buf, len); /* op: cm */ - - pdf_concatmatrix(CTM, M); - } - inversematrix(&W, M); - - pdf_path__transform (cpa, &W); - pdf_coord__transform(cpt, &W); - - return 0; -} - -/* - * num w LW linewidth (g.t. 0) - * int J LC linecap - * int j LJ linejoin - * num M ML miter limit (g.t. 0) - * array num d D line dash - * int ri RI renderint intnet - * int i FL flatness tolerance (0-100) - * name gs -- name: res. name of ExtGState dict. - */ -int -pdf_dev_setmiterlimit (double mlimit) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->miterlimit != mlimit) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, mlimit); - buf[len++] = ' '; - buf[len++] = 'M'; - pdf_doc_add_page_content(buf, len); /* op: M */ - gs->miterlimit = mlimit; - } - - return 0; -} - -int -pdf_dev_setlinecap (int capstyle) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linecap != capstyle) { - len = sprintf(buf, " %d J", capstyle); - pdf_doc_add_page_content(buf, len); /* op: J */ - gs->linecap = capstyle; - } - - return 0; -} - -int -pdf_dev_setlinejoin (int joinstyle) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linejoin != joinstyle) { - len = sprintf(buf, " %d j", joinstyle); - pdf_doc_add_page_content(buf, len); /* op: j */ - gs->linejoin = joinstyle; - } - - return 0; -} - -int -pdf_dev_setlinewidth (double width) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linewidth != width) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, width); - buf[len++] = ' '; - buf[len++] = 'w'; - pdf_doc_add_page_content(buf, len); /* op: w */ - gs->linewidth = width; - } - - return 0; -} - -int -pdf_dev_setdash (int count, double *pattern, double offset) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - int i; - - gs->linedash.num_dash = count; - gs->linedash.offset = offset; - pdf_doc_add_page_content(" [", 2); /* op: */ - for (i = 0; i < count; i++) { - buf[0] = ' '; - len = pdf_sprint_length (buf + 1, pattern[i]); - pdf_doc_add_page_content(buf, len + 1); /* op: */ - gs->linedash.pattern[i] = pattern[i]; - } - pdf_doc_add_page_content("] ", 2); /* op: */ - len = pdf_sprint_length (buf, offset); - pdf_doc_add_page_content(buf, len); /* op: */ - pdf_doc_add_page_content(" d", 2); /* op: d */ - - return 0; -} - -#if 0 -int -pdf_dev_setflat (int flatness) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (flatness < 0 || flatness > 100) - return -1; - - if (gs->flatness != flatness) { - gs->flatness = flatness; - len = sprintf(buf, " %d i", flatness); - pdf_doc_add_page_content(buf, len); /* op: i */ - } - - return 0; -} -#endif - -/* ZSYUEDVEDEOF */ -int -pdf_dev_clip (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_NONZERO, 0); -} - -int -pdf_dev_eoclip (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_EVENODD, 0); -} - -int -pdf_dev_flushpath (char p_op, int fill_rule) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - int error = 0; - - /* last arg 'ignore_rule' is only for single object - * that can be converted to a rect where fill rule - * is inessential. - */ - error = pdf_dev__flushpath(NULL, cpa, p_op, fill_rule, 1); - pdf_path__clearpath(cpa); - - gs->flags &= ~GS_FLAG_CURRENTPOINT_SET; - - return error; -} - -int -pdf_dev_newpath (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *p = &gs->path; - - if (PA_LENGTH(p) > 0) { - pdf_path__clearpath (p); - } - /* The following is required for "newpath" operator in mpost.c. */ - pdf_doc_add_page_content(" n", 2); /* op: n */ - - return 0; -} - -int -pdf_dev_moveto (double x, double y) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = x; p.y = y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_rmoveto (double x, double y) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = cpt->x + x; - p.y = cpt->y + y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_lineto (double x, double y) -{ - 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; - - p0.x = x; p0.y = y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_rlineto (double x, double y) -{ - 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; - - p0.x = x + cpt->x; p0.y = y + cpt->y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_curveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - 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, p2; - - p0.x = x0; p0.y = y0; - p1.x = x1; p1.y = y1; - p2.x = x2; p2.y = y2; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - -#ifdef XETEX -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); -} -#endif - -int -pdf_dev_rcurveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - 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, p2; - - p0.x = x0 + cpt->x; p0.y = y0 + cpt->y; - p1.x = x1 + cpt->x; p1.y = y1 + cpt->y; - p2.x = x2 + cpt->x; p2.y = y2 + cpt->y; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - - -int -pdf_dev_closepath (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_coord *cpt = &gs->cp; - pdf_path *cpa = &gs->path; - - return pdf_path__closepath(cpa, cpt); -} - - -void -pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__dtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__idtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__transform(p, (M ? M : CTM)); - - return; -} - -#if 0 -void -pdf_dev_itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__itransform(p, (M ? M : CTM)); - - return; -} -#endif - -int -pdf_dev_arc (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, +1); -} - -/* *negative* arc */ -int -pdf_dev_arcn (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, -1); -} - -int -pdf_dev_arcx (double c_x , double c_y, - double r_x , double r_y, - double a_0 , double a_1, - int a_d , - double xar) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r_x, r_y, xar, a_0, a_1, a_d); -} - -/* Required by Tpic */ -int -pdf_dev_bspline (double x0, double y0, - double x1, double y1, double x2, double y2) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p1, p2, p3; - - p1.x = x0 + 2.0 * (x1 - x0) / 3.0; - p1.y = y0 + 2.0 * (y1 - y0) / 3.0; - p2.x = x1 + (x2 - x1) / 3.0; - p2.y = y1 + (y2 - y1) / 3.0; - p3.x = x2; - p3.y = y2; - - return pdf_path__curveto(cpa, cpt, &p1, &p2, &p3); -} - -#if 0 -int -pdf_dev_rectstroke (double x, double y, - double w, double h, - const pdf_tmatrix *M /* optional */ - ) -{ - pdf_rect r; - - r.llx = x; - r.lly = y; - r.urx = x + w; - r.ury = y + h; - - return pdf_dev__rectshape(NULL, &r, M, 'S'); -} -#endif - -int -pdf_dev_rectfill (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; - - return pdf_dev__rectshape(NULL, &r, NULL, 'f'); -} - -int -pdf_dev_rectclip (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; - - return pdf_dev__rectshape(NULL, &r, NULL, 'W'); -} - -#ifdef XETEX -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; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/src/pdfnames.c b/Build/source/texk/dvipdfm-x/src/pdfnames.c deleted file mode 100644 index 4f587d283bc..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfnames.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "numbers.h" - -/* Hash */ -#include "dpxutil.h" - -#include "pdfobj.h" - -#include "pdfnames.h" - -struct obj_data -{ - pdf_obj *object; - int closed; /* 1 if object is closed */ -}; - -char * -printable_key (const char *key, int keylen) -{ -#define MAX_KEY 32 - static char pkey[MAX_KEY+4]; - int i, len; - unsigned char hi, lo; - - for (i = 0, len = 0; - i < keylen && len < MAX_KEY; i++) { - if (isprint(key[i])) { - pkey[len++] = key[i]; - } else { - hi = (key[i] >> 4) & 0xff; - lo = key[i] & 0xff; - pkey[len++] = '#'; - pkey[len++] = (hi < 10) ? hi + '0' : (hi - 10) + 'A'; - pkey[len++] = (lo < 10) ? lo + '0' : (lo - 10) + 'A'; - } - } - pkey[len] = '\0'; - - return (char *) pkey; -} - -#ifdef XETEX -static void -flush_objects (struct ht_table *ht_tab) -{ - struct ht_iter iter; - - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - if (value->reserve) { - WARN("Unresolved object reference \"%s\" found!!!", - printable_key(key, keylen)); - } - if (value->object) { - pdf_release_obj(value->object); - } - if (value->object_ref) { - pdf_release_obj(value->object_ref); - } - value->object = NULL; - value->object_ref = NULL; - value->reserve = 0; - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } -} -#endif - -static void CDECL -hval_free (void *hval) -{ - struct obj_data *value; - - value = (struct obj_data *) hval; - - if (value->object) { - pdf_release_obj(value->object); - value->object = NULL; - } - - RELEASE(value); - - return; -} - -struct ht_table * -pdf_new_name_tree (void) -{ - struct ht_table *names; - - names = NEW(1, struct ht_table); - ht_init_table(names, hval_free); - - return names; -} - -#ifndef XETEX -static void -check_objects_defined (struct ht_table *ht_tab) -{ - struct ht_iter iter; - - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - ASSERT(value->object); - if (PDF_OBJ_UNDEFINED(value->object)) { - pdf_names_add_object(ht_tab, key, keylen, pdf_new_null()); - WARN("Object @%s used, but not defined. Replaced by null.", - printable_key(key, keylen)); - } - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } -} -#endif - -void -pdf_delete_name_tree (struct ht_table **names) -{ - ASSERT(names && *names); - - check_objects_defined(*names); - - ht_clear_table(*names); - RELEASE(*names); - *names = NULL; -} - -int -pdf_names_add_object (struct ht_table *names, - const void *key, int keylen, pdf_obj *object) -{ - struct obj_data *value; - - ASSERT(names && object); - - if (!key || keylen < 1) { - WARN("Null string used for name tree key."); - return -1; - } - - value = ht_lookup_table(names, key, keylen); - if (!value) { - value = NEW(1, struct obj_data); - value->object = object; - value->closed = 0; - ht_append_table(names, key, keylen, value); - } else { - ASSERT(value->object); - if (PDF_OBJ_UNDEFINED(value->object)) { - pdf_transfer_label(object, value->object); - pdf_release_obj(value->object); - value->object = object; - } else { - WARN("Object @%s already defined.", printable_key(key, keylen)); - pdf_release_obj(object); - return -1; - } - } - - return 0; -} - -#ifdef XETEX -int -pdf_names_add_reference (struct ht_table *names, - const void *key, int keylen, pdf_obj *object_ref) -{ - struct obj_data *value; - - ASSERT(names); - - if (!PDF_OBJ_INDIRECTTYPE(object_ref)) { - WARN("Invalid type: @%s is not reference...", - printable_key(key, keylen)); - return -1; - } - - value = ht_lookup_table(names, key, keylen); - if (!value) { - value = NEW(1, struct obj_data); - value->object = NULL; - value->object_ref = object_ref; - value->reserve = 0; - ht_append_table(names, key, keylen, value); - } else { - if (value->object || value->object_ref) { - WARN("Object reference \"%s\" is in use.", - printable_key(key, keylen)); - WARN("Please close it before redefining."); - return -1; - } else { - value->object = NULL; - value->object_ref = object_ref; - } - value->reserve = 0; - } - - return 0; -} -#endif - -/* - * The following routine returns copies, not the original object. - */ -pdf_obj * -pdf_names_lookup_reference (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - pdf_obj *object; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - if (value) { - object = value->object; - } else { - /* A null object as dummy would create problems because as value - * of a dictionary entry, a null object is be equivalent to no entry - * at all. This matters for optimization of PDF destinations. - */ - object = pdf_new_undefined(); - pdf_names_add_object(names, key, keylen, object); - } - ASSERT(object); - - return pdf_ref_obj(object); -} - -pdf_obj * -pdf_names_lookup_object (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - if (!value || PDF_OBJ_UNDEFINED(value->object)) - return NULL; - ASSERT(value->object); - - return value->object; -} - -int -pdf_names_close_object (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - if (!value ||PDF_OBJ_UNDEFINED(value->object) ) { - WARN("Cannot close undefined object @%s.", printable_key(key, keylen)); - return -1; - } - ASSERT(value->object); - - if (value->closed) { - WARN("Object @%s already closed.", printable_key(key, keylen)); - return -1; - } - - value->closed = 1; - - return 0; -} - -struct named_object -{ - char *key; - int keylen; - pdf_obj *value; -}; - -static int CDECL -cmp_key (const void *d1, const void *d2) -{ - const struct named_object *sd1, *sd2; - int keylen, cmp; - - sd1 = (const struct named_object *) d1; - sd2 = (const struct named_object *) d2; - - if (!sd1->key) - cmp = -1; - else if (!sd2->key) - cmp = 1; - else { - keylen = MIN(sd1->keylen, sd2->keylen); - cmp = memcmp(sd1->key, sd2->key, keylen); - if (!cmp) { - cmp = sd1->keylen - sd2->keylen; - } - } - - return cmp; -} - -#define NAME_CLUSTER 4 -static pdf_obj * -build_name_tree (struct named_object *first, long num_leaves, int is_root) -{ - pdf_obj *result; - int i; - - result = pdf_new_dict(); - /* - * According to PDF Refrence, Third Edition (p.101-102), a name tree - * always has exactly one root node, which contains a SINGLE entry: - * either Kids or Names but not both. If the root node has a Names - * entry, it is the only node in the tree. If it has a Kids entry, - * then each of the remaining nodes is either an intermediate node, - * containing a Limits entry and a Kids entry, or a leaf node, - * containing a Limits entry and a Names entry. - */ - if (!is_root) { - struct named_object *last; - pdf_obj *limits; - - limits = pdf_new_array(); - last = &first[num_leaves - 1]; - pdf_add_array(limits, pdf_new_string(first->key, first->keylen)); - pdf_add_array(limits, pdf_new_string(last->key , last->keylen )); - pdf_add_dict (result, pdf_new_name("Limits"), limits); - } - - if (num_leaves > 0 && - num_leaves <= 2 * NAME_CLUSTER) { - pdf_obj *names; - - /* Create leaf nodes. */ - names = pdf_new_array(); - for (i = 0; i < num_leaves; i++) { - struct named_object *cur; - - cur = &first[i]; - pdf_add_array(names, pdf_new_string(cur->key, cur->keylen)); - switch (PDF_OBJ_TYPEOF(cur->value)) { - case PDF_ARRAY: - case PDF_DICT: - case PDF_STREAM: - case PDF_STRING: - pdf_add_array(names, pdf_ref_obj(cur->value)); - break; - case PDF_OBJ_INVALID: - ERROR("Invalid object...: %s", printable_key(cur->key, cur->keylen)); - break; - default: - pdf_add_array(names, pdf_link_obj(cur->value)); - break; - } - pdf_release_obj(cur->value); - cur->value = NULL; - } - pdf_add_dict(result, pdf_new_name("Names"), names); - } else if (num_leaves > 0) { - pdf_obj *kids; - - /* Intermediate node */ - kids = pdf_new_array(); - for (i = 0; i < NAME_CLUSTER; i++) { - pdf_obj *subtree; - long start, end; - - start = (i*num_leaves) / NAME_CLUSTER; - end = ((i+1)*num_leaves) / NAME_CLUSTER; - subtree = build_name_tree(&first[start], (end - start), 0); - pdf_add_array (kids, pdf_ref_obj(subtree)); - pdf_release_obj(subtree); - } - pdf_add_dict(result, pdf_new_name("Kids"), kids); - } - - return result; -} - -static struct named_object * -flat_table (struct ht_table *ht_tab, long *num_entries, - struct ht_table *filter) -{ - struct named_object *objects; - struct ht_iter iter; - long count; - - ASSERT(ht_tab); - - objects = NEW(ht_tab->count, struct named_object); - count = 0; - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - - if (filter) { - pdf_obj *new_obj = ht_lookup_table(filter, key, keylen); - - if (!new_obj) - continue; - - key = pdf_string_value(new_obj); - keylen = pdf_string_length(new_obj); - } - - value = ht_iter_getval(&iter); - ASSERT(value->object); - if (PDF_OBJ_UNDEFINED(value->object)) { - WARN("Object @%s\" not defined. Replaced by null.", - printable_key(key, keylen)); - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_new_null(); - } else if (value->object) { - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_link_obj(value->object); - } - - count++; - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } - - *num_entries = count; - objects = RENEW(objects, count, struct named_object); - - return objects; -} - -pdf_obj * -pdf_names_create_tree (struct ht_table *names, long *count, - struct ht_table *filter) -{ - pdf_obj *name_tree; - struct named_object *flat; - - flat = flat_table(names, count, filter); - if (!flat) - name_tree = NULL; - else { - qsort(flat, *count, sizeof(struct named_object), cmp_key); - name_tree = build_name_tree(flat, *count, 1); - RELEASE(flat); - } - - return name_tree; -} diff --git a/Build/source/texk/dvipdfm-x/src/pdfobj.c b/Build/source/texk/dvipdfm-x/src/pdfobj.c deleted file mode 100644 index a5ec7c3bd03..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfobj.c +++ /dev/null @@ -1,3264 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "dpxutil.h" -#include "pdflimits.h" -#include "pdfencrypt.h" -#include "pdfparse.h" - -#ifdef HAVE_ZLIB -#include -#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 -{ - int type; - - unsigned long label; /* Only used for indirect objects - 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; -}; - -struct pdf_boolean -{ - char value; -}; - -struct pdf_number -{ - double value; -}; - -struct pdf_string -{ - unsigned char *string; - unsigned short length; -}; - -struct pdf_name -{ - char *name; -}; - -struct pdf_array -{ - unsigned long max; - unsigned long size; - struct pdf_obj **values; -}; - -struct pdf_dict -{ - struct pdf_obj *key; - struct pdf_obj *value; - struct pdf_dict *next; -}; - -struct pdf_stream -{ - struct pdf_obj *dict; - unsigned char *stream; - long *objstm_data; /* used for object streams */ - unsigned long stream_length; - unsigned long max_length; - unsigned char _flags; -}; - -struct pdf_indirect -{ - pdf_file *pf; - unsigned long label; - unsigned short generation; -}; - -typedef void pdf_null; -typedef struct pdf_boolean pdf_boolean; -typedef struct pdf_number pdf_number; -typedef struct pdf_string pdf_string; -typedef struct pdf_name pdf_name; -typedef struct pdf_array pdf_array; -typedef struct pdf_dict pdf_dict; -typedef struct pdf_stream pdf_stream; -typedef struct pdf_indirect pdf_indirect; - -static FILE *pdf_output_file = NULL; - -static long pdf_output_file_position = 0; -static long pdf_output_line_position = 0; -static long compression_saved = 0; - -#define FORMAT_BUF_SIZE 4096 -static char format_buffer[FORMAT_BUF_SIZE]; - -typedef struct xref_entry -{ - unsigned char type; /* object storage type */ - unsigned long field2; /* offset in file or object stream */ - unsigned short field3; /* generation or index */ - pdf_obj *direct; /* used for imported objects */ - pdf_obj *indirect; /* used for imported objects */ -} xref_entry; - -static xref_entry *output_xref; - -static unsigned long pdf_max_ind_objects; -static unsigned long next_label; - -static unsigned long startxref; - -struct pdf_file -{ - FILE *file; - pdf_obj *trailer; - xref_entry *xref_table; - pdf_obj *catalog; - long num_obj; - long file_size; - int version; -}; - -static pdf_obj *output_stream; - -#define OBJSTM_MAX_OBJS 200 -/* the limit is only 100 for linearized PDF */ - -static int enc_mode; -static int doc_enc_mode; - -static pdf_obj *trailer_dict; -static pdf_obj *xref_stream; - -/* Internal static routines */ - -static int check_for_pdf_version (FILE *file); - -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 set_objstm_data (pdf_obj *objstm, long *data); -static long *get_objstm_data (pdf_obj *objstm); -static void release_objstm (pdf_obj *objstm); - -static void pdf_out_char (FILE *file, char c); -static void pdf_out (FILE *file, const void *buffer, long length); - -static void release_indirect (pdf_indirect *data); -static void write_indirect (pdf_indirect *indirect, FILE *file); - -static void release_boolean (pdf_obj *data); -static void write_boolean (pdf_boolean *data, FILE *file); - -static void release_null (pdf_null *data); -static void write_null (pdf_null *data, FILE *file); - -static void release_number (pdf_number *number); -static void write_number (pdf_number *number, FILE *file); - -static void write_string (pdf_string *str, FILE *file); -static void release_string (pdf_string *str); - -static void write_name (pdf_name *name, FILE *file); -static void release_name (pdf_name *name); - -static void write_array (pdf_array *array, FILE *file); -static void release_array (pdf_array *array); - -static void write_dict (pdf_dict *dict, FILE *file); -static void release_dict (pdf_dict *dict); - -static void write_stream (pdf_stream *stream, FILE *file); -static void release_stream (pdf_stream *stream); - -static int verbose = 0; -static char compression_level = 9; - -void -pdf_set_compression (int level) -{ -#ifndef HAVE_ZLIB - ERROR("You don't have compression compiled in. Possibly libz wasn't found by configure."); -#else -#ifndef HAVE_ZLIB_COMPRESS2 - if (level != 0) - WARN("Unable to set compression level -- your zlib doesn't have compress2()."); -#endif - if (level >= 0 && level <= 9) - compression_level = level; - else { - ERROR("set_compression: invalid compression level: %d", level); - } -#endif /* !HAVE_ZLIB */ - - return; -} - -static unsigned pdf_version = PDF_VERSION_DEFAULT; - -void -pdf_set_version (unsigned version) -{ - /* Don't forget to update CIDFont_stdcc_def[] in cid.c too! */ - if (version >= PDF_VERSION_MIN && version <= PDF_VERSION_MAX) { - pdf_version = version; - } -} - -unsigned -pdf_get_version (void) -{ - return pdf_version; -} - -int -pdf_obj_get_verbose(void) -{ - return verbose; -} - -void -pdf_obj_set_verbose(void) -{ - verbose++; -} - -static pdf_obj *current_objstm = NULL; -static int do_objstm; - -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, xref_entry); - } - - output_xref[label].type = type; - output_xref[label].field2 = field2; - output_xref[label].field3 = field3; - output_xref[label].direct = NULL; - output_xref[label].indirect = NULL; -} - -#define BINARY_MARKER "%\344\360\355\370\n" -void -pdf_out_init (const char *filename, int do_encryption) -{ - char v; - - 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")); - do_objstm = 1; - } else { - xref_stream = NULL; - trailer_dict = pdf_new_dict(); - do_objstm = 0; - } - - output_stream = NULL; - - pdf_output_file = MFOPEN(filename, FOPEN_WBIN_MODE); - if (!pdf_output_file) { - if (strlen(filename) < 128) - ERROR("Unable to open \"%s\".", filename); - else - ERROR("Unable to open file."); - } - pdf_out(pdf_output_file, "%PDF-1.", strlen("%PDF-1.")); - v = '0' + pdf_version; - 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_table (void) -{ - long length; - unsigned long i; - - 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); - - /* - * 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. - */ - 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); - } -} - -static void -dump_trailer_dict (void) -{ - pdf_out(pdf_output_file, "trailer\n", 8); - enc_mode = 0; - write_dict(trailer_dict->data, pdf_output_file); - pdf_release_obj(trailer_dict); - pdf_out_char(pdf_output_file, '\n'); -} - -/* - * 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; - - /* 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; - unsigned short f3; - buf[0] = output_xref[i].type; - pos = output_xref[i].field2; - for (j = poslen; j--; ) { - buf[1+j] = (unsigned char) pos; - pos >>= 8; - } - 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_release_obj(xref_stream); -} - -void -pdf_out_flush (void) -{ - if (pdf_output_file) { - long length; - - /* Flush current object stream */ - if (current_objstm) { - release_objstm(current_objstm); - current_objstm =NULL; - } - - /* - * Label xref stream - we need the number of correct objects - * for the xref stream dictionary (= trailer). - * Labelling it in pdf_out_init (with 1) does not work (why?). - */ - if (xref_stream) - pdf_label_obj(xref_stream); - - /* 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 (xref_stream) - 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 saved %ld bytes%s\n", compression_saved, - pdf_version < 5 ? ". Try \"-V 5\" for better compression" : ""); - } - } - MESG("%ld bytes written", pdf_output_file_position); - - MFCLOSE(pdf_output_file); - } -} - -void -pdf_error_cleanup (void) -{ - /* - * This routine is the cleanup required for an abnormal exit. - * For now, simply close the file. - */ - if (pdf_output_file) - MFCLOSE(pdf_output_file); -} - - -void -pdf_set_root (pdf_obj *object) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) { - ERROR("Root object already set!"); - } - /* 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_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) { - ERROR ("Info object already set!"); - } -} - -void -pdf_set_id (pdf_obj *id) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("ID"), id)) { - ERROR ("ID already set!"); - } -} - -void -pdf_set_encrypt (pdf_obj *encrypt) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) { - ERROR("Encrypt object already set!"); - } - encrypt->flags |= OBJ_NO_ENCRYPT; -} - -static -void pdf_out_char (FILE *file, char c) -{ - 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; - } - } -} - -static char xchar[] = "0123456789abcdef"; - -#define pdf_out_xchar(f,c) do {\ - pdf_out_char((f), xchar[((c) >> 4) & 0x0f]);\ - pdf_out_char((f), xchar[(c) & 0x0f]);\ -} while (0) - -static -void pdf_out (FILE *file, const void *buffer, long length) -{ - 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 && - ((const char *)buffer)[length-1] == '\n') - 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) -{ - if (file == pdf_output_file && pdf_output_line_position >= 80) { - pdf_out_char(file, '\n'); - } else { - pdf_out_char(file, ' '); - } -} - -#define TYPECHECK(o,t) if (!(o) || (o)->type != (t)) {\ - ERROR("typecheck: Invalid object type: %d %d (line %d)", (o) ? (o)->type : -1, (t), __LINE__);\ -} - -#define INVALIDOBJ(o) ((o) == NULL || (o)->type <= 0 || (o)->type > PDF_UNDEFINED) - -static pdf_obj * -pdf_new_obj(int type) -{ - pdf_obj *result; - - if (type >= PDF_UNDEFINED || type < 0) - ERROR("Invalid object type: %d", type); - - result = NEW(1, pdf_obj); - result->type = type; - result->data = NULL; - result->label = 0; - result->generation = 0; - result->refcount = 1; - result->flags = 0; - - return result; -} - -int -pdf_obj_typeof (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - return PDF_OBJ_INVALID; - - return object->type; -} - -static void -pdf_label_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_label_obj(): passed invalid object."); - - /* - * Don't change label on an already labeled object. Ignore such calls. - */ - if (object->label == 0) { - object->label = next_label++; - object->generation = 0; - } -} - -#ifndef XETEX -/* - * Transfer the label assigned to the object src to the object dst. - * The object dst must not yet have been labeled. - */ -void -pdf_transfer_label (pdf_obj *dst, pdf_obj *src) -{ - ASSERT(dst && !dst->label && src); - - dst->label = src->label; - dst->generation = src->generation; - src->label = 0; - src->generation = 0; -} -#endif - -/* - * This doesn't really copy the object, but allows it to be used without - * fear that somebody else will free it. - */ -pdf_obj * -pdf_link_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_link_obj(): passed invalid object."); - - object->refcount += 1; - - return object; -} - - -pdf_obj * -pdf_ref_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_ref_obj(): passed invalid object."); - - if (object->refcount == 0) { - MESG("\nTrying to refer already released object!!!\n"); - pdf_write_obj(object, stderr); - ERROR("Cannot continue..."); - } - - if (PDF_OBJ_INDIRECTTYPE(object)) { - return pdf_link_obj(object); - } else { - if (object->label == 0) { - pdf_label_obj(object); - } - return pdf_new_indirect(NULL, object->label, object->generation); - } -} - -static void -release_indirect (pdf_indirect *data) -{ - RELEASE(data); -} - -static void -write_indirect (pdf_indirect *indirect, FILE *file) -{ - long length; - - ASSERT(!indirect->pf); - - length = sprintf(format_buffer, "%lu %hu R", indirect->label, indirect->generation); - pdf_out(file, format_buffer, length); -} - -#ifndef XETEX -/* The undefined object is used as a placeholder in pdfnames.c - * for objects which are referenced before they are defined. - */ -pdf_obj * -pdf_new_undefined (void) -{ - pdf_obj *result; - - result = pdf_new_obj(PDF_UNDEFINED); - result->data = NULL; - - return result; -} -#endif - -pdf_obj * -pdf_new_null (void) -{ - pdf_obj *result; - - result = pdf_new_obj(PDF_NULL); - result->data = NULL; - - return result; -} - -static void -release_null (pdf_null *obj) -{ - return; -} - -static void -write_null (pdf_null *obj, FILE *file) -{ - pdf_out(file, "null", 4); -} - -pdf_obj * -pdf_new_boolean (char value) -{ - pdf_obj *result; - pdf_boolean *data; - - result = pdf_new_obj(PDF_BOOLEAN); - data = NEW(1, pdf_boolean); - data->value = value; - result->data = data; - - return result; -} - -static void -release_boolean (pdf_obj *data) -{ - RELEASE (data); -} - -static void -write_boolean (pdf_boolean *data, FILE *file) -{ - if (data->value) { - pdf_out(file, "true", 4); - } else { - pdf_out(file, "false", 5); - } -} - -#ifdef XETEX -void -pdf_set_boolean (pdf_obj *object, char value) -{ - pdf_boolean *data; - - TYPECHECK(object, PDF_BOOLEAN); - - data = object->data; - data->value = value; -} -#endif - -char -pdf_boolean_value (pdf_obj *object) -{ - pdf_boolean *data; - - TYPECHECK(object, PDF_BOOLEAN); - - data = object->data; - - return data->value; -} - -pdf_obj * -pdf_new_number (double value) -{ - pdf_obj *result; - pdf_number *data; - - result = pdf_new_obj(PDF_NUMBER); - data = NEW(1, pdf_number); - data->value = value; - result->data = data; - - return result; -} - -static void -release_number (pdf_number *data) -{ - RELEASE (data); -} - -static void -write_number (pdf_number *number, FILE *file) -{ - int count; - - count = pdf_sprint_number(format_buffer, number->value); - - pdf_out(file, format_buffer, count); -} - - -void -pdf_set_number (pdf_obj *object, double value) -{ - pdf_number *data; - - TYPECHECK(object, PDF_NUMBER); - - data = object->data; - data->value = value; -} - -double -pdf_number_value (pdf_obj *object) -{ - pdf_number *data; - - TYPECHECK(object, PDF_NUMBER); - - data = object->data; - - return data->value; -} - -pdf_obj * -pdf_new_string (const void *str, unsigned length) -{ - pdf_obj *result; - pdf_string *data; - - ASSERT(str); - - result = pdf_new_obj(PDF_STRING); - data = NEW(1, pdf_string); - result->data = data; - - data->length = length; - data->string = NEW(length+1, unsigned char); - memcpy(data->string, str, length); - /* Shouldn't assume NULL terminated. */ - data->string[length] = '\0'; - - return result; -} - -void * -pdf_string_value (pdf_obj *object) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - - return data->string; -} - -unsigned -pdf_string_length (pdf_obj *object) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - - return (unsigned) (data->length); -} - -/* - * This routine escapes non printable characters and control - * characters in an output string. - */ -int -pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len) -{ - int result = 0; - int i; - - for (i = 0; i < len; i++) { - unsigned char ch; - - ch = s[i]; - if (result > bufsize - 4) - ERROR("pdfobj_escape_str: Buffer overflow"); - - /* - * We always write three octal digits. Optimization only gives few Kb - * smaller size for most documents when zlib compressed. - */ - if (ch < 32 || ch > 126) { - buffer[result++] = '\\'; -#if 0 - if (i < len - 1 && !isdigit(s[i+1])) - result += sprintf(buffer+result, "%o", ch); - else - result += sprintf(buffer+result, "%03o", ch); -#endif - result += sprintf(buffer+result, "%03o", ch); - } else { - switch (ch) { - case '(': - buffer[result++] = '\\'; - buffer[result++] = '('; - break; - case ')': - buffer[result++] = '\\'; - buffer[result++] = ')'; - break; - case '\\': - buffer[result++] = '\\'; - buffer[result++] = '\\'; - break; - default: - buffer[result++] = ch; - break; - } - } - } - - return result; -} - -static void -write_string (pdf_string *str, FILE *file) -{ - unsigned char *s; - char wbuf[FORMAT_BUF_SIZE]; /* Shouldn't use format_buffer[]. */ - int nescc = 0, i, count; - - s = str->string; - - if (enc_mode) - pdf_encrypt_data(s, str->length); - - /* - * Count all ASCII non-printable characters. - */ - for (i = 0; i < str->length; i++) { - if (!isprint(s[i])) - nescc++; - } - /* - * If the string contains much escaped chars, then we write it as - * ASCII hex string. - */ - if (nescc > str->length / 3) { - pdf_out_char(file, '<'); - for (i = 0; i < str->length; i++) { - pdf_out_xchar(file, s[i]); - } - pdf_out_char(file, '>'); - } else { - pdf_out_char(file, '('); - /* - * This section of code probably isn't speed critical. Escaping the - * characters in the string one at a time may seem slow, but it's - * safe if the formatted string length exceeds FORMAT_BUF_SIZE. - * Occasionally you see some long strings in PDF. pdfobj_escape_str - * is also used for strings of text with no kerning. These must be - * handled as quickly as possible since there are so many of them. - */ - for (i = 0; i < str->length; i++) { - count = pdfobj_escape_str(wbuf, FORMAT_BUF_SIZE, &(s[i]), 1); - pdf_out(file, wbuf, count); - } - pdf_out_char(file, ')'); - } -} - -static void -release_string (pdf_string *data) -{ - if (data->string != NULL) { - RELEASE(data->string); - data->string = NULL; - } - RELEASE(data); -} - -void -pdf_set_string (pdf_obj *object, unsigned char *str, unsigned length) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - if (data->string != 0) { - RELEASE(data->string); - } - if (length != 0) { - data->length = length; - data->string = NEW(length + 1, unsigned char); - memcpy(data->string, str, length); - data->string[length] = '\0'; - } else { - data->length = 0; - data->string = NULL; - } -} - -/* Name does *not* include the /. */ -pdf_obj * -pdf_new_name (const char *name) -{ - pdf_obj *result; - unsigned length; - pdf_name *data; - - result = pdf_new_obj(PDF_NAME); - data = NEW (1, pdf_name); - result->data = data; - length = strlen(name); - if (length != 0) { - data->name = NEW(length+1, char); - memcpy(data->name, name, length); - data->name[length] = '\0'; - } else { - data->name = NULL; - } - - return result; -} - -static void -write_name (pdf_name *name, FILE *file) -{ - char *s; - int i, length; - - s = name->name; - length = name->name ? strlen(name->name) : 0; - /* - * From PDF Reference, 3rd ed., p.33: - * - * Beginning with PDF 1.2, any character except null (character code 0) - * may be included in a name by writing its 2-digit hexadecimal code, - * preceded bythe number sign character (#); see implementation notes 3 - * and 4 in Appendix H. This syntax is required in order to represent - * any of the delimiter or white-space characters or the number sign - * character itself; it is recommended but not required for characters - * whose codes are outside the range 33 (!) to 126 (~). - */ -#ifndef is_delim - /* Avoid '{' and '}' for PostScript compatibility? */ -#define is_delim(c) ((c) == '(' || (c) == '/' || \ - (c) == '<' || (c) == '>' || \ - (c) == '[' || (c) == ']' || \ - (c) == '{' || (c) == '}' || \ - (c) == '%') -#endif - pdf_out_char(file, '/'); - for (i = 0; i < length; i++) { - if (s[i] < '!' || s[i] > '~' || s[i] == '#' || is_delim(s[i])) { - /* ^ "space" is here. */ - pdf_out_char (file, '#'); - pdf_out_xchar(file, s[i]); - } else { - pdf_out_char (file, s[i]); - } - } -} - -static void -release_name (pdf_name *data) -{ - if (data->name != NULL) { - RELEASE(data->name); - data->name = NULL; - } - RELEASE(data); -} - -#ifdef XETEX -void -pdf_set_name (pdf_obj *object, const char *name) -{ - pdf_name *data; - unsigned length; - - TYPECHECK(object, PDF_NAME); - - length = strlen(name); - data = object->data; - if (data->name != NULL) { - RELEASE(data->name); - } - if (length != 0) { - data->name = NEW(length+1, char); - memcpy(data->name, name, length); - data->name[length] = 0; - } else { - data->name = NULL; - } -} -#endif - -char * -pdf_name_value (pdf_obj *object) -{ - pdf_name *data; - - TYPECHECK(object, PDF_NAME); - - data = object->data; - - return data->name; -} - -/* - * We do not have pdf_name_length() since '\0' is not allowed - * in PDF name object. - */ - -pdf_obj * -pdf_new_array (void) -{ - pdf_obj *result; - pdf_array *data; - - result = pdf_new_obj(PDF_ARRAY); - data = NEW(1, pdf_array); - data->values = NULL; - data->max = 0; - data->size = 0; - result->data = data; - - return result; -} - -static void -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 (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_out_char(file, ']'); -} - -pdf_obj * -pdf_get_array (pdf_obj *array, long idx) -{ - pdf_obj *result = NULL; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (idx < 0) - result = data->values[idx + data->size]; - else if (idx < data->size) { - result = data->values[idx]; - } - - return result; -} - -unsigned int -pdf_array_length (pdf_obj *array) -{ - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = (pdf_array *) array->data; - - return (unsigned int) data->size; -} - -static void -release_array (pdf_array *data) -{ - unsigned long i; - - if (data->values) { - for (i = 0; i < data->size; i++) { - pdf_release_obj(data->values[i]); - data->values[i] = NULL; - } - RELEASE(data->values); - data->values = NULL; - } - RELEASE(data); -} - -/* - * The name pdf_add_array is misleading. It behaves differently than - * pdf_add_dict(). This should be pdf_push_array(). - */ -void -pdf_add_array (pdf_obj *array, pdf_obj *object) -{ - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size >= data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - data->values[data->size] = object; - data->size++; - - return; -} - -#if 0 -void -pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object) -{ - pdf_array *data; - long i; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (idx + 1 > data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - /* - * Rangecheck error in PostScript interpreters if - * idx > data->size - 1. But pdf_new_array() doesn't set - * array size, pdf_add_array() dynamically increases size - * of array. This might confusing... - */ - if (idx + 1 > data->size) { - for (i = data->size; i < idx; i++) - data->values[i] = pdf_new_null(); /* release_array() won't work without this */ - data->values[idx] = object; - data->size = idx + 1; - } else { - if (data->values[idx]) - pdf_release_obj(data->values[idx]); - data->values[idx] = object; - } -} - -/* Easily leaks memory... */ -pdf_obj * -pdf_shift_array (pdf_obj *array) -{ - pdf_obj *result = NULL; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size > 0) { - int i; - - result = data->values[0]; - for (i = 1; i < data->size; i++) - data->values[i-1] = data->values[i]; - data->size--; - } - - return result; -} -#endif - -/* Prepend an object to an array */ -void -pdf_unshift_array (pdf_obj *array, pdf_obj *object) -{ - pdf_array *data; - int i; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size >= data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - for (i = 0; i < data->size; i++) - data->values[i+1] = data->values[i]; - data->values[0] = object; - data->size++; -} - -#if 0 -pdf_obj * -pdf_pop_array (pdf_obj *array) -{ - pdf_obj *result; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size > 0) { - result = data->values[data->size - 1]; - data->size--; - } else { - result = NULL; - } - - return result; -} -#endif - -static void -write_dict (pdf_dict *dict, FILE *file) -{ -#ifdef XETEX - pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */ -#else - pdf_out (file, "<<", 2); -#endif - while (dict->key != NULL) { - pdf_write_obj(dict->key, file); - if (pdf_need_white(PDF_NAME, (dict->value)->type)) { - pdf_out_white(file); - } - pdf_write_obj(dict->value, file); -#ifdef XETEX - pdf_out_char (file, '\n'); /* removing this saves few kb. */ -#endif - dict = dict->next; - } - pdf_out(file, ">>", 2); -} - -pdf_obj * -pdf_new_dict (void) -{ - pdf_obj *result; - pdf_dict *data; - - result = pdf_new_obj(PDF_DICT); - data = NEW(1, pdf_dict); - data->key = NULL; - data->value = NULL; - data->next = NULL; - result->data = data; - - return result; -} - -static void -release_dict (pdf_dict *data) -{ - pdf_dict *next; - - while (data != NULL && data->key != NULL) { - pdf_release_obj(data->key); - pdf_release_obj(data->value); - data->key = NULL; - data->value = NULL; - next = data->next; - RELEASE(data); - data = next; - } - RELEASE(data); -} - -/* Array is ended by a node with NULL this pointer */ -/* 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, *new_node; - - TYPECHECK(dict, PDF_DICT); - TYPECHECK(key, PDF_NAME); - - /* It seems that NULL is sometimes used for null object... */ - if (value != NULL && INVALIDOBJ(value)) - ERROR("pdf_add_dict(): Passed invalid value"); - - /* If this key already exists, simply replace the value */ - 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; - return 1; - } - } - /* - * We didn't find the key. We build a new "end" node and add - * the new key just before the end - */ - 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; -} - -#if 0 -void -pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value) -{ - pdf_dict *data; - - TYPECHECK(dict, PDF_DICT); - - if (!key) { - ERROR("pdf_put_dict(): Passed invalid key."); - } - /* It seems that NULL is sometimes used for null object... */ - if (value != NULL && INVALIDOBJ(value)) { - ERROR("pdf_add_dict(): Passed invalid value."); - } - - data = dict->data; - - while (data->key != NULL) { - if (!strcmp(key, pdf_name_value(data->key))) { - pdf_release_obj(data->value); - data->value = value; - break; - } - data = data->next; - } - - /* - * If we didn't find the key, 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 = pdf_new_name(key); - data->value = value; - } -} -#endif - -/* pdf_merge_dict makes a link for each item in dict2 before stealing it */ -void -pdf_merge_dict (pdf_obj *dict1, pdf_obj *dict2) -{ - pdf_dict *data; - - TYPECHECK(dict1, PDF_DICT); - TYPECHECK(dict2, PDF_DICT); - - data = dict2->data; - while (data->key != NULL) { - pdf_add_dict(dict1, pdf_link_obj(data->key), pdf_link_obj(data->value)); - data = data->next; - } -} - -int -pdf_foreach_dict (pdf_obj *dict, - int (*proc) (pdf_obj *, pdf_obj *, void *), void *pdata) -{ - int error = 0; - pdf_dict *data; - - ASSERT(proc); - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - while (!error && - data->key != NULL) { - error = proc(data->key, data->value, pdata); - data = data->next; - } - - return error; -} - -#define pdf_match_name(o,s) ((o) && (s) && !strcmp(((pdf_name *)(o)->data)->name, (s))) -pdf_obj * -pdf_lookup_dict (pdf_obj *dict, const char *name) -{ - pdf_dict *data; - - ASSERT(name); - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - while (data->key != NULL) { - if (!strcmp(name, pdf_name_value(data->key))) { - return data->value; - } - data = data->next; - } - - return NULL; -} - -/* Returns array of dictionary keys */ -pdf_obj * -pdf_dict_keys (pdf_obj *dict) -{ - pdf_obj *keys; - pdf_dict *data; - - TYPECHECK(dict, PDF_DICT); - - keys = pdf_new_array(); - for (data = dict->data; (data && - data->key != NULL); data = data->next) { - /* We duplicate name object rather than linking keys. - * If we forget to free keys, broken PDF is generated. - */ - pdf_add_array(keys, pdf_new_name(pdf_name_value(data->key))); - } - - return keys; -} - -void -pdf_remove_dict (pdf_obj *dict, const char *name) -{ - pdf_dict *data, **data_p; - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - data_p = (pdf_dict **) (void *) &(dict->data); - while (data->key != NULL) { - if (pdf_match_name(data->key, name)) { - pdf_release_obj(data->key); - pdf_release_obj(data->value); - *data_p = data->next; - RELEASE(data); - break; - } - data_p = &(data->next); - data = data->next; - } -} - -pdf_obj * -pdf_new_stream (int flags) -{ - pdf_obj *result; - pdf_stream *data; - - result = pdf_new_obj(PDF_STREAM); - data = NEW(1, pdf_stream); - /* - * Although we are using an arbitrary pdf_object here, it must have - * type=PDF_DICT and cannot be an indirect reference. This will be - * checked by the output routine. - */ - data->dict = pdf_new_dict(); - data->_flags = flags; - data->stream = NULL; - data->stream_length = 0; - data->max_length = 0; - data->objstm_data = NULL; - - result->data = data; - result->flags |= OBJ_NO_OBJSTM; - - return result; -} - -static void -write_stream (pdf_stream *stream, FILE *file) -{ - unsigned char *filtered; - unsigned long filtered_length; - unsigned long buffer_length; - unsigned char *buffer; - - /* - * Always work from a copy of the stream. All filters read from - * "filtered" and leave their result in "filtered". - */ -#if 0 - filtered = NEW(stream->stream_length + 1, unsigned char); -#endif - filtered = NEW(stream->stream_length, unsigned char); - memcpy(filtered, stream->stream, stream->stream_length); - filtered_length = stream->stream_length; - -#if 0 - if (stream->stream_length < 10) - stream->_flags &= ^STREAM_COMPRESS; -#endif - -#ifdef HAVE_ZLIB - /* Apply compression filter if requested */ - if (stream->stream_length > 0 && - (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 *filter_name = pdf_new_name("FlateDecode"); - - 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, - filtered_length, compression_level)) { - ERROR("Zlib error"); - } -#else - if (compress(buffer, &buffer_length, filtered, - filtered_length)) { - ERROR ("Zlib error"); - } -#endif /* HAVE_ZLIB_COMPRESS2 */ - RELEASE(filtered); - compression_saved += filtered_length - buffer_length - - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n")); - - filtered = buffer; - filtered_length = buffer_length; - } -#endif /* HAVE_ZLIB */ - -#if 0 - /* - * An optional end-of-line marker preceding the "endstream" is - * not part of stream data. See, PDF Reference 4th ed., p. 38. - */ - /* Add a '\n' if the last character wasn't one */ - if (filtered_length > 0 && - filtered[filtered_length-1] != '\n') { - filtered[filtered_length] = '\n'; - filtered_length++; - } -#endif - pdf_add_dict(stream->dict, - pdf_new_name("Length"), pdf_new_number(filtered_length)); - - pdf_write_obj(stream->dict, file); - - pdf_out(file, "\nstream\n", 8); - - if (enc_mode) - pdf_encrypt_data(filtered, filtered_length); - - if (filtered_length > 0) { - pdf_out(file, filtered, filtered_length); - } - RELEASE(filtered); - - /* - * This stream length "object" gets reset every time write_stream is - * called for the stream object. - * If this stream gets written more than once with different - * filters, this could be a problem. - */ - - pdf_out(file, "\n", 1); - pdf_out(file, "endstream", 9); -} - -static void -release_stream (pdf_stream *stream) -{ - pdf_release_obj(stream->dict); - stream->dict = NULL; - - if (stream->stream) { - RELEASE(stream->stream); - stream->stream = NULL; - } - - if (stream->objstm_data) { - RELEASE(stream->objstm_data); - stream->objstm_data = NULL; - } - - RELEASE(stream); -} - -pdf_obj * -pdf_stream_dict (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return data->dict; -} - -const void * -pdf_stream_dataptr (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return (const void *) data->stream; -} - -long -pdf_stream_length (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return (long) data->stream_length; -} - -static void -set_objstm_data (pdf_obj *objstm, long *data) { - TYPECHECK(objstm, PDF_STREAM); - - ((pdf_stream *) objstm->data)->objstm_data = data; -} - -static long * -get_objstm_data (pdf_obj *objstm) { - TYPECHECK(objstm, PDF_STREAM); - - return ((pdf_stream *) objstm->data)->objstm_data; -} - -void -pdf_add_stream (pdf_obj *stream, const void *stream_data, long length) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - if (length < 1) - return; - data = stream->data; - if (data->stream_length + length > data->max_length) { - data->max_length += length + STREAM_ALLOC_SIZE; - data->stream = RENEW(data->stream, data->max_length, unsigned char); - } - memcpy(data->stream + data->stream_length, stream_data, length); - data->stream_length += length; -} - -#if HAVE_ZLIB -#define WBUF_SIZE 4096 -int -pdf_add_stream_flate (pdf_obj *dst, const void *data, long len) -{ - z_stream z; - Bytef wbuf[WBUF_SIZE]; - - z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - z.next_in = (Bytef *) data; z.avail_in = len; - z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; - - if (inflateInit(&z) != Z_OK) { - WARN("inflateInit() failed."); - return -1; - } - - for (;;) { - int status; - status = inflate(&z, Z_NO_FLUSH); - if (status == Z_STREAM_END) - break; - else if (status != Z_OK) { - WARN("inflate() failed. Broken PDF file?"); - inflateEnd(&z); - return -1; - } - - if (z.avail_out == 0) { - pdf_add_stream(dst, wbuf, WBUF_SIZE); - z.next_out = wbuf; - z.avail_out = WBUF_SIZE; - } - } - - if (WBUF_SIZE - z.avail_out > 0) - pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); - - return (inflateEnd(&z) == Z_OK ? 0 : -1); -} -#endif - - -int -pdf_concat_stream (pdf_obj *dst, pdf_obj *src) -{ - const char *stream_data; - long stream_length; - pdf_obj *stream_dict; - pdf_obj *filter; - - if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) - ERROR("Invalid type."); - - stream_data = pdf_stream_dataptr(src); - stream_length = pdf_stream_length (src); - stream_dict = pdf_stream_dict (src); - - if (pdf_lookup_dict(stream_dict, "DecodeParms")) { - WARN("Streams with DecodeParams not supported."); - return -1; - } - - filter = pdf_lookup_dict(stream_dict, "Filter"); - if (!filter) { - pdf_add_stream(dst, stream_data, stream_length); - return 0; -#if HAVE_ZLIB - } else { - char *filter_name; - if (PDF_OBJ_NAMETYPE(filter)) { - filter_name = pdf_name_value(filter); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return pdf_add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } else if (PDF_OBJ_ARRAYTYPE(filter)) { - if (pdf_array_length(filter) > 1) { - WARN("Multiple DecodeFilter not supported."); - return -1; - } else { - filter_name = pdf_name_value(pdf_get_array(filter, 0)); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return pdf_add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } - } else - ERROR("Broken PDF file?"); -#endif /* HAVE_ZLIB */ - } - - return -1; -} - -static pdf_obj * -pdf_stream_uncompress (pdf_obj *src) { - pdf_obj *dst = pdf_new_stream(0); - - TYPECHECK(src, PDF_STREAM); - - pdf_merge_dict(pdf_stream_dict(dst), pdf_stream_dict(src)); - pdf_remove_dict(pdf_stream_dict(dst), "Length"); - pdf_concat_stream(dst, src); - - return dst; -} - -#if 0 -void -pdf_stream_set_flags (pdf_obj *stream, int flags) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - data->_flags = flags; -} - -int -pdf_stream_get_flags (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return data->_flags; -} -#endif - -static void -pdf_write_obj (pdf_obj *object, FILE *file) -{ - if (object == NULL) { - write_null(NULL, file); - return; - } - - if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object)) - ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type); - - if (file == stderr) - fprintf(stderr, "{%d}", object->refcount); - - switch (object->type) { - case PDF_BOOLEAN: - write_boolean(object->data, file); - break; - case PDF_NUMBER: - write_number (object->data, file); - break; - case PDF_STRING: - write_string (object->data, file); - break; - case PDF_NAME: - write_name(object->data, file); - break; - case PDF_ARRAY: - write_array(object->data, file); - break; - case PDF_DICT: - write_dict (object->data, file); - break; - case PDF_STREAM: - write_stream(object->data, file); - break; - case PDF_NULL: - write_null(NULL, file); - break; - case PDF_INDIRECT: - write_indirect(object->data, file); - break; - } -} - -/* Write the object to the file */ -static void -pdf_flush_obj (pdf_obj *object, FILE *file) -{ - long length; - - /* - * Record file position - */ - 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); - pdf_write_obj(object, file); - pdf_out(file, "\nendobj\n", 8); -} - -static long -pdf_add_objstm (pdf_obj *objstm, pdf_obj *object) -{ - long *data, pos; - - TYPECHECK(objstm, PDF_STREAM); - - data = get_objstm_data(objstm); - pos = ++data[0]; - - data[2*pos] = object->label; - data[2*pos+1] = pdf_stream_length(objstm); - - add_xref_entry(object->label, 2, objstm->label, pos-1); - - /* redirect output into objstm */ - output_stream = objstm; - enc_mode = 0; - pdf_write_obj(object, pdf_output_file); - pdf_out_char(pdf_output_file, '\n'); - output_stream = NULL; - - return pos; -} - -static void -release_objstm (pdf_obj *objstm) -{ - long *data = get_objstm_data(objstm); - long pos = data[0]; - pdf_obj *dict; - pdf_stream *stream; - unsigned char *old_buf; - unsigned long old_length; - stream = (pdf_stream *) objstm->data; - - /* Precede stream data by offset table */ - old_buf = stream->stream; - 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; - - { - long i = 2*pos, *val = data+2; - while (i--) { - long length = sprintf(format_buffer, "%ld ", *(val++)); - pdf_add_stream(objstm, format_buffer, length); - } - } - - dict = pdf_stream_dict(objstm); - 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(objstm, old_buf, old_length); - RELEASE(old_buf); - pdf_release_obj(objstm); -} - -void -pdf_release_obj (pdf_obj *object) -{ - if (object == NULL) - return; - if (INVALIDOBJ(object) || object->refcount <= 0) { - MESG("\npdf_release_obj: object=%p, type=%d, refcount=%d\n", - object, object->type, object->refcount); - pdf_write_obj(object, stderr); - ERROR("pdf_release_obj: Called with invalid object."); - } - object->refcount -= 1; - if (object->refcount == 0) { - /* - * 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) { - if (!do_objstm || object->flags & OBJ_NO_OBJSTM - || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT) - || object->generation) - pdf_flush_obj(object, pdf_output_file); - else { - if (!current_objstm) { - long *data = NEW(2*OBJSTM_MAX_OBJS+2, long); - data[0] = data[1] = 0; - current_objstm = pdf_new_stream(STREAM_COMPRESS); - set_objstm_data(current_objstm, data); - pdf_label_obj(current_objstm); - } - if (pdf_add_objstm(current_objstm, object) == OBJSTM_MAX_OBJS) { - release_objstm(current_objstm); - current_objstm = NULL; - } - } - } - switch (object->type) { - case PDF_BOOLEAN: - release_boolean(object->data); - break; - case PDF_NULL: - release_null(object->data); - break; - case PDF_NUMBER: - release_number(object->data); - break; - case PDF_STRING: - release_string(object->data); - break; - case PDF_NAME: - release_name(object->data); - break; - case PDF_ARRAY: - release_array(object->data); - break; - case PDF_DICT: - release_dict(object->data); - break; - case PDF_STREAM: - release_stream(object->data); - break; - case PDF_INDIRECT: - release_indirect(object->data); - break; - } - /* This might help detect freeing already freed objects */ - object->type = -1; - object->data = NULL; - RELEASE(object); - } -} - -#ifdef XETEX -/* Copy object data without changing object label. */ -void -pdf_copy_object (pdf_obj *dst, pdf_obj *src) -{ - if (!dst || !src) - return; - - switch (dst->type) { - case PDF_BOOLEAN: release_boolean(dst->data); break; - case PDF_NULL: release_null(dst->data); break; - case PDF_NUMBER: release_number(dst->data); break; - case PDF_STRING: release_string(dst->data); break; - case PDF_NAME: release_name(dst->data); break; - case PDF_ARRAY: release_array(dst->data); break; - case PDF_DICT: release_dict(dst->data); break; - case PDF_STREAM: release_stream(dst->data); break; - case PDF_INDIRECT: release_indirect(dst->data); break; - } - - dst->type = src->type; - switch (src->type) { - case PDF_BOOLEAN: - dst->data = NEW(1, pdf_boolean); - pdf_set_boolean(dst, pdf_boolean_value(src)); - break; - case PDF_NULL: - dst->data = NULL; - break; - case PDF_NUMBER: - dst->data = NEW(1, pdf_number); - pdf_set_number(dst, pdf_number_value(src)); - break; - case PDF_STRING: - dst->data = NEW(1, pdf_string); - pdf_set_string(dst, - pdf_string_value(src), - pdf_string_length(src)); - break; - case PDF_NAME: - dst->data = NEW(1, pdf_name); - pdf_set_name(dst, pdf_name_value(src)); - break; - case PDF_ARRAY: - { - pdf_array *data; - unsigned long i; - - dst->data = data = NEW(1, pdf_array); - data->size = 0; - data->max = 0; - data->values = NULL; - for (i = 0; i < pdf_array_length(src); i++) { - pdf_add_array(dst, pdf_link_obj(pdf_get_array(src, i))); - } - } - break; - case PDF_DICT: - { - pdf_dict *data; - - dst->data = data = NEW(1, pdf_dict); - data->key = NULL; - data->value = NULL; - data->next = NULL; - pdf_merge_dict(dst, src); - } - break; - case PDF_STREAM: - { - pdf_stream *data; - - dst->data = data = NEW(1, pdf_stream); - data->dict = pdf_new_dict(); - data->_flags = ((pdf_stream *)src->data)->_flags; - data->stream_length = 0; - data->max_length = 0; - - pdf_add_stream(dst, pdf_stream_dataptr(src), pdf_stream_length(src)); - pdf_merge_dict(data->dict, pdf_stream_dict(src)); - } - break; - case PDF_INDIRECT: - { - pdf_indirect *data; - - dst->data = data = NEW(1, pdf_indirect); - data->pf = ((pdf_indirect *) (src->data))->pf; - data->label = ((pdf_indirect *) (src->data))->label; - data->generation = ((pdf_indirect *) (src->data))->generation; - } - break; - } - - return; -} -#endif - -static int -backup_line (FILE *pdf_input_file) -{ - int ch = -1; - - /* - * Note: this code should work even if \r\n is eol. It could fail on a - * machine where \n is eol and there is a \r in the stream --- Highly - * unlikely in the last few bytes where this is likely to be used. - */ - if (tell_position(pdf_input_file) > 1) - do { - seek_relative (pdf_input_file, -2); - } while (tell_position(pdf_input_file) > 0 && - (ch = fgetc(pdf_input_file)) >= 0 && - (ch != '\n' && ch != '\r' )); - if (ch < 0) { - return 0; - } - - return 1; -} - -static long -find_xref (FILE *pdf_input_file) -{ - long xref_pos; - int tries = 10; - - do { - long currentpos; - - if (!backup_line(pdf_input_file)) { - tries = 0; - break; - } - currentpos = tell_position(pdf_input_file); - fread(work_buffer, sizeof(char), strlen("startxref"), pdf_input_file); - seek_absolute(pdf_input_file, currentpos); - tries--; - } while (tries > 0 && - strncmp(work_buffer, "startxref", strlen("startxref"))); - if (tries <= 0) - return 0; - - /* Skip rest of this line */ - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - /* Next line of input file should contain actual xref location */ - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - - { - const char *start, *end; - char *number; - - start = work_buffer; - end = start + strlen(work_buffer); - skip_white(&start, end); - number = parse_number(&start, end); - xref_pos = (long) atof(number); - RELEASE(number); - } - - return xref_pos; -} - -/* - * This routine must be called with the file pointer located - * at the start of the trailer. - */ -static pdf_obj * -parse_trailer (pdf_file *pf) -{ - pdf_obj *result; - /* - * Fill work_buffer and hope trailer fits. This should - * be made a bit more robust sometime. - */ - if (fread(work_buffer, sizeof(char), - WORK_BUFFER_SIZE, pf->file) == 0 || - strncmp(work_buffer, "trailer", strlen("trailer"))) { - WARN("No trailer. Are you sure this is a PDF file?"); - WARN("buffer:\n->%s<-\n", work_buffer); - result = NULL; - } else { - const char *p = work_buffer + strlen("trailer"); - skip_white(&p, work_buffer + WORK_BUFFER_SIZE); - result = parse_pdf_dict(&p, work_buffer + WORK_BUFFER_SIZE, pf); - } - - return result; -} - -/* - * This routine tries to estimate an upper bound for character position - * of the end of the object, so it knows how big the buffer must be. - * The parsing routines require that the entire object be read into - * memory. It would be a major pain to rewrite them. The worst case - * is that an object before an xref table will grab the whole table - * :-( - */ -static long -next_object_offset (pdf_file *pf, unsigned long obj_num) -{ - long next = pf->file_size; /* Worst case */ - long i, curr; - - curr = pf->xref_table[obj_num].field2; - /* Check all other type 1 objects to find next one */ - for (i = 0; i < pf->num_obj; i++) { - if (pf->xref_table[i].type == 1 && - pf->xref_table[i].field2 > curr && - pf->xref_table[i].field2 < next) - next = pf->xref_table[i].field2; - } - - return next; -} - -#define checklabel(pf, n, g) ((n) > 0 && (n) < (pf)->num_obj && ( \ - ((pf)->xref_table[(n)].type == 1 && (pf)->xref_table[(n)].field3 == (g)) || \ - ((pf)->xref_table[(n)].type == 2 && !(g)))) - -pdf_obj * -pdf_new_indirect (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) -{ - pdf_obj *result; - pdf_indirect *indirect; - - indirect = NEW(1, pdf_indirect); - indirect->pf = pf; - indirect->label = obj_num; - indirect->generation = obj_gen; - - result = pdf_new_obj(PDF_INDIRECT); - result->data = indirect; - - return result; -} - -static pdf_obj * -pdf_read_object (unsigned long obj_num, unsigned short obj_gen, - pdf_file *pf, long offset, long limit) -{ - long length; - char *buffer; - const char *p, *endptr; - pdf_obj *result; - - length = limit - offset; - - if (length <= 0) - return NULL; - - buffer = NEW(length + 1, char); - - seek_absolute(pf->file, offset); - fread(buffer, sizeof(char), length, pf->file); - - p = buffer; - endptr = p + length; - - /* Check for obj_num and obj_gen */ - { - const char *q = p; /* <== p */ - char *sp; - unsigned long n, g; - - skip_white(&q, endptr); - sp = parse_unsigned(&q, endptr); - if (!sp) { - RELEASE(buffer); - return NULL; - } - n = strtoul(sp, NULL, 10); - RELEASE(sp); - - skip_white(&q, endptr); - sp = parse_unsigned(&q, endptr); - if (!sp) { - RELEASE(buffer); - return NULL; - } - g = strtoul(sp, NULL, 10); - RELEASE(sp); - - if (obj_num && (n != obj_num || g != obj_gen)) { - RELEASE(buffer); - return NULL; - } - - p = q; /* ==> p */ - } - - - skip_white(&p, endptr); - if (memcmp(p, "obj", strlen("obj"))) { - WARN("Didn't find \"obj\"."); - RELEASE(buffer); - return NULL; - } - p += strlen("obj"); - - result = parse_pdf_object(&p, endptr, pf); - - skip_white(&p, endptr); - if (memcmp(p, "endobj", strlen("endobj"))) { - WARN("Didn't find \"endobj\"."); - if (result) - pdf_release_obj(result); - result = NULL; - } - RELEASE(buffer); - - return result; -} - -static pdf_obj * -read_objstm (pdf_file *pf, unsigned long num) -{ - unsigned long offset = pf->xref_table[num].field2; - unsigned short gen = pf->xref_table[num].field3; - long limit = next_object_offset(pf, num), n, first, *header = NULL; - char *data = NULL, *q; - const char *p, *endptr; - int i; - - pdf_obj *objstm, *dict, *type, *n_obj, *first_obj; - - objstm = pdf_read_object(num, gen, pf, offset, limit); - - if (!PDF_OBJ_STREAMTYPE(objstm)) - goto error; - - { - pdf_obj *tmp = pdf_stream_uncompress(objstm); - if (!tmp) - goto error; - pdf_release_obj(objstm); - objstm = tmp; - } - - dict = pdf_stream_dict(objstm); - - type = pdf_lookup_dict(dict, "Type"); - if (!PDF_OBJ_NAMETYPE(type) || - strcmp(pdf_name_value(type), "ObjStm")) - goto error; - - n_obj = pdf_lookup_dict(dict, "N"); - if (!PDF_OBJ_NUMBERTYPE(n_obj)) - goto error; - n = (long) pdf_number_value(n_obj); - - first_obj = pdf_lookup_dict(dict, "First"); - if (!PDF_OBJ_NUMBERTYPE(first_obj)) - goto error; - first = (long) pdf_number_value(first_obj); - /* reject object streams without object data */ - if (first >= pdf_stream_length(objstm)) - goto error; - - header = NEW(2*(n+1), long); - set_objstm_data(objstm, header); - *(header++) = n; - *(header++) = first; - - /* avoid parsing beyond offset table */ - data = NEW(first + 1, char); - memcpy(data, pdf_stream_dataptr(objstm), first); - data[first] = 0; - - p = data; - endptr = p + first; - i = 2*n; - while (i--) { - *(header++) = strtoul(p, &q, 10); - if (q == p) - goto error; - p = q; - } - - /* Any garbage after last entry? */ - skip_white(&p, endptr); - if (p != endptr) - goto error; - RELEASE(data); - - return pf->xref_table[num].direct = objstm; - - error: - WARN("Cannot parse object stream."); - if (data) - RELEASE(data); - if (objstm) - pdf_release_obj(objstm); - return NULL; -} - -/* Label without corresponding object definition are replaced by the - * null object, as required by the PDF spec. This is important to parse - * several cross-reference sections. - */ -static pdf_obj * -pdf_get_object (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) -{ - pdf_obj *result; - - if (!checklabel(pf, obj_num, obj_gen)) { - WARN("Trying to read nonexistent or deleted object: %lu %u", - obj_num, obj_gen); - return pdf_new_null(); - } - - if ((result = pf->xref_table[obj_num].direct)) { - return pdf_link_obj(result); - } - - if (pf->xref_table[obj_num].type == 1) { - /* type == 1 */ - unsigned long offset; - long limit; - offset = pf->xref_table[obj_num].field2; - limit = next_object_offset(pf, obj_num); - result = pdf_read_object(obj_num, obj_gen, pf, offset, limit); - } else { - /* type == 2 */ - unsigned long objstm_num = pf->xref_table[obj_num].field2; - unsigned short index = pf->xref_table[obj_num].field3; - pdf_obj *objstm; - long *data, n, first, length; - const char *p, *q; - - if (objstm_num >= pf->num_obj || - pf->xref_table[objstm_num].type != 1 || - !((objstm = pf->xref_table[objstm_num].direct) || - (objstm = read_objstm(pf, objstm_num)))) - goto error; - - data = get_objstm_data(objstm); - n = *(data++); - first = *(data++); - - if (index >= n || data[2*index] != obj_num) - goto error; - - length = pdf_stream_length(objstm); - p = (const char *) pdf_stream_dataptr(objstm) + first + data[2*index+1]; - q = p + (index == n-1 ? length : first+data[2*index+3]); - result = parse_pdf_object(&p, q, pf); - if (!result) - goto error; - } - - /* Make sure the caller doesn't free this object */ - pf->xref_table[obj_num].direct = pdf_link_obj(result); - - return result; - - error: - WARN("Could not read object from object stream."); - return pdf_new_null(); -} - -#define OBJ_FILE(o) (((pdf_indirect *)((o)->data))->pf) -#define OBJ_NUM(o) (((pdf_indirect *)((o)->data))->label) -#define OBJ_GEN(o) (((pdf_indirect *)((o)->data))->generation) - -/* pdf_deref_obj always returns a link instead of the original */ -/* It never return the null object, but the NULL pointer instead */ -pdf_obj * -pdf_deref_obj (pdf_obj *obj) -{ - int count = PDF_OBJ_MAX_DEPTH; - - if (obj) - obj = pdf_link_obj(obj); - - while (PDF_OBJ_INDIRECTTYPE(obj) && --count) { - pdf_file *pf = OBJ_FILE(obj); - unsigned long obj_num = OBJ_NUM(obj); - unsigned short obj_gen = OBJ_GEN(obj); - ASSERT(pf); - pdf_release_obj(obj); - obj = pdf_get_object(pf, obj_num, obj_gen); - } - - if (!count) - ERROR("Loop in object hierarchy detected. Broken PDF file?"); - - if (PDF_OBJ_NULLTYPE(obj)) { - pdf_release_obj(obj); - return NULL; - } else - return obj; -} - -static void -extend_xref (pdf_file *pf, long new_size) -{ - unsigned long i; - - pf->xref_table = RENEW(pf->xref_table, new_size, xref_entry); - for (i = pf->num_obj; i < new_size; i++) { - pf->xref_table[i].direct = NULL; - pf->xref_table[i].indirect = NULL; - pf->xref_table[i].type = 0; - pf->xref_table[i].field3 = 0; - pf->xref_table[i].field2 = 0L; - } - pf->num_obj = new_size; -} - -static int -parse_xref_table (pdf_file *pf, long xref_pos) -{ - FILE *pdf_input_file = pf->file; - unsigned long first, size; - unsigned long i, offset; - unsigned int obj_gen; - char flag; - int r; - - /* - * This routine reads one xref segment. It may be called multiple times - * on the same file. xref tables sometimes come in pieces. - */ - - seek_absolute(pf->file, xref_pos); - - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - if (memcmp(work_buffer, "xref", strlen("xref"))) { - /* Might be an xref stream and not an xref table */ - return 0; - } - /* Next line in file has first item and size of table */ - for (;;) { - unsigned long current_pos; - - current_pos = tell_position(pdf_input_file); - if (mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file) == NULL) { - WARN("Premature end of PDF file while parsing xref table."); - return -1; - } - if (!strncmp(work_buffer, "trailer", strlen ("trailer"))) { - /* - * Backup... This is ugly, but it seems like the safest thing to - * do. It is possible the trailer dictionary starts on the same - * logical line as the word trailer. In that case, the mfgets - * call might have started to read the trailer dictionary and - * parse_trailer would fail. - */ - seek_absolute(pdf_input_file, current_pos); - break; - } - sscanf(work_buffer, "%lu %lu", &first, &size); - if (pf->num_obj < first + size) { - extend_xref(pf, first + size); - } - - for (i = first; i < first + size; i++) { - fread(work_buffer, sizeof(char), 20, pdf_input_file); - /* - * Don't overwrite positions that have already been set by a - * modified xref table. We are working our way backwards - * through the reference table, so we only set "position" - * if it hasn't been set yet. - */ - work_buffer[19] = 0; - offset = 0UL; obj_gen = 0; flag = 0; - r = sscanf(work_buffer, "%010lu %05u %c", &offset, &obj_gen, &flag); - if ( r != 3 || - ((flag != 'n' && flag != 'f') || - (flag == 'n' && - (offset >= pf->file_size || (offset > 0 && offset < 4))))) { - WARN("Invalid xref table entry [%lu]. PDF file is corrupt...", i); - return -1; - } - if (!pf->xref_table[i].field2) { - pf->xref_table[i].type = (flag == 'n'); - pf->xref_table[i].field2 = offset; - pf->xref_table[i].field3 = obj_gen; - } - } - } - - return 1; -} - -static unsigned long -parse_xrefstm_field (const char **p, int length, unsigned long def) -{ - unsigned long val = 0; - - if (!length) - return def; - - while (length--) { - val <<= 8; - val |= (unsigned char) *((*p)++); - } - - return val; -} - -static int -parse_xrefstm_subsec (pdf_file *pf, - const char **p, long *length, - int *W, int wsum, - long first, long size) { - xref_entry *e; - - if ((*length -= wsum*size) < 0) - return -1; - - if (pf->num_obj < first+size) - extend_xref(pf, first+size); /* TODO: change! why? */ - - e = pf->xref_table + first; - while (size--) { - unsigned char type; - unsigned long field2; - unsigned short field3; - - type = (unsigned char) parse_xrefstm_field(p, W[0], 1); - if (type > 2) - WARN("Unknown cross-reference stream entry type."); - else if (!W[1] || (type != 1 && !W[2])) - return -1; - - field2 = (unsigned long) parse_xrefstm_field(p, W[1], 0); - field3 = (unsigned short) parse_xrefstm_field(p, W[2], 0); - - if (!e->field2) { - e->type = type; - e->field2 = field2; - e->field3 = field3; - } - e++; - } - - return 0; -} - -static int -parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) -{ - pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj; - unsigned long size; - long length; - int W[3], i, wsum = 0; - const char *p; - - xrefstm = pdf_read_object(0, 0, pf, xref_pos, pf->file_size); - if (!PDF_OBJ_STREAMTYPE(xrefstm)) - goto error; - - { - pdf_obj *tmp = pdf_stream_uncompress(xrefstm); - if (!tmp) - goto error; - pdf_release_obj(xrefstm); - xrefstm = tmp; - } - - *trailer = pdf_link_obj(pdf_stream_dict(xrefstm)); - - size_obj = pdf_lookup_dict(*trailer, "Size"); - if (!PDF_OBJ_NUMBERTYPE(size_obj)) - goto error; - size = (unsigned long) pdf_number_value(size_obj); - - length = pdf_stream_length(xrefstm); - - W_obj = pdf_lookup_dict(*trailer, "W"); - if (!PDF_OBJ_ARRAYTYPE(W_obj) || pdf_array_length(W_obj) != 3) - goto error; - - for (i = 0; i < 3; i++) { - pdf_obj *tmp = pdf_get_array(W_obj, i); - if (!PDF_OBJ_NUMBERTYPE(tmp)) - goto error; - wsum += (W[i] = (int) pdf_number_value(tmp)); - } - - p = pdf_stream_dataptr(xrefstm); - - index_obj = pdf_lookup_dict(*trailer, "Index"); - if (index_obj) { - unsigned int index_len; - if (!PDF_OBJ_ARRAYTYPE(index_obj) || - ((index_len = pdf_array_length(index_obj)) % 2 )) - goto error; - - i = 0; - while (i < index_len) { - pdf_obj *first = pdf_get_array(index_obj, i++); - size_obj = pdf_get_array(index_obj, i++); - if (!PDF_OBJ_NUMBERTYPE(first) || - !PDF_OBJ_NUMBERTYPE(size_obj) || - parse_xrefstm_subsec(pf, &p, &length, W, wsum, - (long) pdf_number_value(first), - (long) pdf_number_value(size_obj))) - goto error; - } - } else if (parse_xrefstm_subsec(pf, &p, &length, W, wsum, 0, size)) - goto error; - - if (length) - WARN("Garbage in xref stream."); - - pdf_release_obj(xrefstm); - - return 1; - - error: - WARN("Cannot parse cross-reference stream."); - if (xrefstm) - pdf_release_obj(xrefstm); - if (*trailer) { - pdf_release_obj(*trailer); - *trailer = NULL; - } - return 0; -} - -/* TODO: parse Version entry */ -static pdf_obj * -read_xref (pdf_file *pf) -{ - pdf_obj *trailer = NULL, *main_trailer = NULL; - long xref_pos; - - if (!(xref_pos = find_xref(pf->file))) - goto error; - - while (xref_pos) { - pdf_obj *prev; - - int res = parse_xref_table(pf, xref_pos); - if (res > 0) { - /* cross-reference table */ - pdf_obj *xrefstm; - - if (!(trailer = parse_trailer(pf))) - goto error; - - if (!main_trailer) - main_trailer = pdf_link_obj(trailer); - - if ((xrefstm = pdf_lookup_dict(trailer, "XRefStm"))) { - pdf_obj *new_trailer = NULL; - if (PDF_OBJ_NUMBERTYPE(xrefstm) && - parse_xref_stream(pf, (long) pdf_number_value(xrefstm), - &new_trailer)) - pdf_release_obj(new_trailer); - else - WARN("Skipping hybrid reference section."); - /* Many PDF 1.5 xref streams use DecodeParms, which we cannot - parse. This way we can use at least xref tables in hybrid - documents. Or should we better stop parsing the file? - */ - } - - } else if (!res && parse_xref_stream(pf, xref_pos, &trailer)) { - /* cross-reference stream */ - if (!main_trailer) - main_trailer = pdf_link_obj(trailer); - } else - goto error; - - if ((prev = pdf_lookup_dict(trailer, "Prev"))) { - if (PDF_OBJ_NUMBERTYPE(prev)) - xref_pos = (long) pdf_number_value(prev); - else - goto error; - } else - xref_pos = 0; - - pdf_release_obj(trailer); - } - -#if 0 - if (!pdf_lookup_dict(main_trailer, "Root")) { - WARN("Trailer doesn't have catalog. Is this a correct PDF file?"); - goto error; - } -#endif - - return main_trailer; - - error: - WARN("Error while parsing PDF file."); - if (trailer) - pdf_release_obj(trailer); - if (main_trailer) - pdf_release_obj(main_trailer); - return NULL; -} - -static struct ht_table *pdf_files = NULL; - -static pdf_file * -pdf_file_new (FILE *file) -{ - pdf_file *pf; - ASSERT(file); - pf = NEW(1, pdf_file); - pf->file = file; - pf->trailer = NULL; - pf->xref_table = NULL; - pf->catalog = NULL; - pf->num_obj = 0; - pf->version = 0; - - seek_end(file); - pf->file_size = tell_position(file); - - return pf; -} - -static void -pdf_file_free (pdf_file *pf) -{ - unsigned long i; - - if (!pf) { - return; - } - - for (i = 0; i < pf->num_obj; i++) { - if (pf->xref_table[i].direct) - pdf_release_obj(pf->xref_table[i].direct); - if (pf->xref_table[i].indirect) - pdf_release_obj(pf->xref_table[i].indirect); - } - - RELEASE(pf->xref_table); - if (pf->trailer) { - pdf_release_obj(pf->trailer); - pf->trailer = NULL; - } - if (pf->catalog) { - pdf_release_obj(pf->catalog); - pf->catalog = NULL; - } - - RELEASE(pf); -} - -void -pdf_files_init (void) -{ - pdf_files = NEW(1, struct ht_table); - ht_init_table(pdf_files, (void (*)(void *)) pdf_file_free); -} - -int -pdf_file_get_version (pdf_file *pf) -{ - ASSERT(pf); - return pf->version; -} - -#ifdef XETEX -pdf_obj * -pdf_file_get_trailer (pdf_file *pf) -{ - ASSERT(pf); - return pf->trailer; -} -#endif - -pdf_obj * -pdf_file_get_catalog (pdf_file *pf) -{ - ASSERT(pf); - return pf->catalog; -} - -pdf_file * -pdf_open (const char *ident, FILE *file) -{ - pdf_file *pf; - - ASSERT(pdf_files); - - pf = (pdf_file *) ht_lookup_table(pdf_files, ident, strlen(ident)); - - if (pf) { - pf->file = file; - } else { - pdf_obj *new_version; - int version = check_for_pdf_version(file); - - if (version < 0) { - WARN("Not a PDF file."); - return NULL; - } - - pf = pdf_file_new(file); - pf->version = version; - - if (!(pf->trailer = read_xref(pf))) - goto error; - - if (pdf_lookup_dict(pf->trailer, "Encrypt")) { - WARN("PDF document is encrypted."); - goto error; - } - - pf->catalog = pdf_deref_obj(pdf_lookup_dict(pf->trailer, "Root")); - if (!PDF_OBJ_DICTTYPE(pf->catalog)) { - WARN("Cannot read PDF document catalog. Broken PDF file?"); - goto error; - } - - new_version = pdf_deref_obj(pdf_lookup_dict(pf->catalog, "Version")); - if (new_version) { - unsigned int minor; - - if (!PDF_OBJ_NAMETYPE(new_version) || - sscanf(pdf_name_value(new_version), "1.%u", &minor) != 1) { - pdf_release_obj(new_version); - WARN("Illegal Version entry in document catalog. Broken PDF file?"); - goto error; - } - - if (pf->version < minor) - pf->version = minor; - - pdf_release_obj(new_version); - } - - ht_append_table(pdf_files, ident, strlen(ident), pf); - } - - return pf; - - error: - pdf_file_free(pf); - return NULL; -} - -void -pdf_close (pdf_file *pf) -{ - if (pf) - pf->file = NULL; -} - -void -pdf_files_close (void) -{ - ASSERT(pdf_files); - ht_clear_table(pdf_files); - RELEASE(pdf_files); -} - -static int -check_for_pdf_version (FILE *file) -{ - unsigned int minor; - - rewind(file); - - return (ungetc(fgetc(file), file) == '%' && - fscanf(file, "%%PDF-1.%u", &minor) == 1) ? minor : -1; -} - -int -check_for_pdf (FILE *file) -{ - return (check_for_pdf_version(file) >= 0); -} - -static int CDECL -import_dict (pdf_obj *key, pdf_obj *value, void *pdata) -{ - pdf_obj *copy; - pdf_obj *tmp; - - copy = (pdf_obj *) pdata; - - tmp = pdf_import_object(value); - if (!tmp) { - return -1; - } - pdf_add_dict(copy, pdf_link_obj(key), tmp); - - return 0; -} - -static pdf_obj loop_marker = { PDF_OBJ_INVALID, 0, 0, 0, 0, NULL }; - -static pdf_obj * -pdf_import_indirect (pdf_obj *object) -{ - pdf_file *pf = OBJ_FILE(object); - unsigned long obj_num = OBJ_NUM(object); - unsigned short obj_gen = OBJ_GEN(object); - - pdf_obj *ref; - - ASSERT(pf); - - if (!checklabel(pf, obj_num, obj_gen)) { - WARN("Can't resolve object: %lu %u", obj_num, obj_gen); - return pdf_new_null(); - } - - if ((ref = pf->xref_table[obj_num].indirect)) { - if (ref == &loop_marker) - ERROR("Loop in object hierarchy detected. Broken PDF file?"); - return pdf_link_obj(ref); - } else { - pdf_obj *obj, *tmp; - - obj = pdf_get_object(pf, obj_num, obj_gen); - - /* We mark the reference to be able to detect loops */ - pf->xref_table[obj_num].indirect = &loop_marker; - - tmp = pdf_import_object(obj); - - pf->xref_table[obj_num].indirect = ref = pdf_ref_obj(tmp); - - pdf_release_obj(tmp); - pdf_release_obj(obj); - - return pdf_link_obj(ref); - } -} - -/* - * pdf_import_object recursively copies the object and those - * referenced by it and changes the indirect references so that - * they refer to the current output file. New indirect references - * are remembered, which avoids duplicating objects when they - * are imported several times. - */ -pdf_obj * -pdf_import_object (pdf_obj *object) -{ - pdf_obj *imported; - pdf_obj *tmp; - int i; - - switch (pdf_obj_typeof(object)) { - - case PDF_INDIRECT: - if (OBJ_FILE(object)) { - imported = pdf_import_indirect(object); - } else { - imported = pdf_link_obj(object); - } - break; - - case PDF_STREAM: - { - pdf_obj *stream_dict; - - tmp = pdf_import_object(pdf_stream_dict(object)); - if (!tmp) - return NULL; - - imported = pdf_new_stream(0); - stream_dict = pdf_stream_dict(imported); - pdf_merge_dict(stream_dict, tmp); - pdf_release_obj(tmp); - pdf_add_stream(imported, - pdf_stream_dataptr(object), - pdf_stream_length(object)); - } - break; - - case PDF_DICT: - - imported = pdf_new_dict(); - if (pdf_foreach_dict(object, import_dict, imported) < 0) { - pdf_release_obj(imported); - return NULL; - } - - break; - - case PDF_ARRAY: - - imported = pdf_new_array(); - for (i = 0; i < pdf_array_length(object); i++) { - tmp = pdf_import_object(pdf_get_array(object, i)); - if (!tmp) { - pdf_release_obj(imported); - return NULL; - } - pdf_add_array(imported, tmp); - } - break; - - default: - imported = pdf_link_obj(object); - } - - return imported; -} - - -/* returns 0 if indirect references point to the same object */ -int -pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2) -{ - pdf_indirect *data1, *data2; - - ASSERT(PDF_OBJ_INDIRECTTYPE(ref1) && PDF_OBJ_INDIRECTTYPE(ref2)); - - data1 = (pdf_indirect *) ref1->data; - data2 = (pdf_indirect *) ref2->data; - - return data1->pf != data2->pf || data1->label != data2->label - || data1->generation != data2->generation; -} diff --git a/Build/source/texk/dvipdfm-x/src/pdfximage.c b/Build/source/texk/dvipdfm-x/src/pdfximage.c deleted file mode 100644 index 7e44720d936..00000000000 --- a/Build/source/texk/dvipdfm-x/src/pdfximage.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "error.h" -#include "mem.h" - -#include "dpxfile.h" - -#include "pdfobj.h" - -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfdraw.h" - -#include "epdf.h" -#include "mpost.h" -#include "pngimage.h" -#include "jpegimage.h" -#include "bmpimage.h" - -#include "pdfximage.h" - -/* From psimage.h */ -static int check_for_ps (FILE *fp); -static int ps_include_page (pdf_ximage *ximage, const char *file_name); - - -#define IMAGE_TYPE_UNKNOWN -1 -#define IMAGE_TYPE_PDF 0 -#define IMAGE_TYPE_JPEG 1 -#define IMAGE_TYPE_PNG 2 -#define IMAGE_TYPE_MPS 4 -#define IMAGE_TYPE_EPS 5 -#define IMAGE_TYPE_BMP 6 - - -struct attr_ -{ - long width, height; - double xdensity, ydensity; - pdf_rect bbox; -}; - -struct pdf_ximage_ -{ - char *ident; - char res_name[16]; - long page_no, page_count; - - int subtype; - - struct attr_ attr; - - char *filename; - pdf_obj *reference; - pdf_obj *resource; - pdf_obj *attr_dict; - - char tempfile; -}; - - -/* verbose, verbose, verbose... */ -struct opt_ -{ - int verbose; - char *cmdtmpl; -}; - -static struct opt_ _opts = { - 0, NULL -}; - -void pdf_ximage_set_verbose (void) { _opts.verbose++; } - - -struct ic_ -{ - int count, capacity; - pdf_ximage *ximages; -}; - -static struct ic_ _ic = { - 0, 0, NULL -}; - -static void -pdf_init_ximage_struct (pdf_ximage *I, - const char *ident, const char *filename, - long page_no, pdf_obj *dict) -{ - if (ident) { - I->ident = NEW(strlen(ident)+1, char); - strcpy(I->ident, ident); - } else - I ->ident = NULL; - I->page_no = page_no; - I->page_count = 0; - if (filename) { - I->filename = NEW(strlen(filename)+1, char); - strcpy(I->filename, filename); - } else - I->filename = NULL; - I->subtype = -1; - memset(I->res_name, 0, 16); - I->reference = NULL; - I->resource = NULL; - I->attr_dict = dict; - - 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->tempfile = 0; -} - -static void -pdf_set_ximage_tempfile (pdf_ximage *I, const char *filename) -{ - if (I->filename) - RELEASE(I->filename); - I->filename = NEW(strlen(filename)+1, char); - strcpy(I->filename, filename); - I->tempfile = 1; -} - -static void -pdf_clean_ximage_struct (pdf_ximage *I) -{ - if (I->ident) - RELEASE(I->ident); - if (I->filename) - RELEASE(I->filename); - if (I->reference) - pdf_release_obj(I->reference); - if (I->resource) - pdf_release_obj(I->resource); - if (I->attr_dict) - pdf_release_obj(I->attr_dict); - pdf_init_ximage_struct(I, NULL, NULL, 0, NULL); -} - - -void -pdf_init_images (void) -{ - struct ic_ *ic = &_ic; - ic->count = 0; - ic->capacity = 0; - ic->ximages = NULL; -} - -void -pdf_close_images (void) -{ - struct ic_ *ic = &_ic; - if (ic->ximages) { - int i; - for (i = 0; i < ic->count; i++) { - pdf_ximage *I = ic->ximages+i; - if (I->tempfile) { - /* - * It is important to remove temporary files at the end because - * we cache file names. Since we use mkstemp to create them, we - * might get the same file name again if delete the first file. - * (This happens on NetBSD, reported by Jukka Salmi.) - * We also use this to convert a PS file only once if multiple - * pages are imported from that file. - */ - if (_opts.verbose > 1 && keep_cache != 1) - MESG("pdf_image>> deleting temporary file \"%s\"\n", I->filename); - dpx_delete_temp_file(I->filename, false); /* temporary filename freed here */ - I->filename = NULL; - } - pdf_clean_ximage_struct(I); - } - RELEASE(ic->ximages); - ic->ximages = NULL; - ic->count = ic->capacity = 0; - } - - if (_opts.cmdtmpl) - RELEASE(_opts.cmdtmpl); - _opts.cmdtmpl = NULL; -} - -static int -source_image_type (FILE *fp) -{ - int format = IMAGE_TYPE_UNKNOWN; - - rewind(fp); - /* - * Make sure we check for PS *after* checking for MP since - * MP is a special case of PS. - */ - if (check_for_jpeg(fp)) - { - format = IMAGE_TYPE_JPEG; - } -#ifdef HAVE_LIBPNG - else if (check_for_png(fp)) - { - format = IMAGE_TYPE_PNG; - } -#endif - else if (check_for_bmp(fp)) - { - format = IMAGE_TYPE_BMP; - } else if (check_for_pdf(fp)) { - format = IMAGE_TYPE_PDF; - } else if (check_for_mp(fp)) { - format = IMAGE_TYPE_MPS; - } else if (check_for_ps(fp)) { - format = IMAGE_TYPE_EPS; - } else { - format = IMAGE_TYPE_UNKNOWN; - } - rewind(fp); - - return format; -} - -static int -load_image (const char *ident, const char *fullname, int format, FILE *fp, - long page_no, pdf_obj *dict) -{ - struct ic_ *ic = &_ic; - int id = -1; /* ret */ - pdf_ximage *I; - - id = ic->count; - if (ic->count >= ic->capacity) { - ic->capacity += 16; - ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); - } - - I = &ic->ximages[id]; - pdf_init_ximage_struct(I, ident, fullname, page_no, dict); - - switch (format) { - case IMAGE_TYPE_JPEG: - if (_opts.verbose) - MESG("[JPEG]"); - if (jpeg_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; -#ifdef HAVE_LIBPNG - case IMAGE_TYPE_PNG: - if (_opts.verbose) - MESG("[PNG]"); - if (png_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; -#endif - case IMAGE_TYPE_BMP: - if (_opts.verbose) - MESG("[BMP]"); - if (bmp_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; - case IMAGE_TYPE_PDF: - if (_opts.verbose) - MESG("[PDF]"); - { - int result = pdf_include_page(I, fp, fullname); - if (result > 0) - /* PDF version too recent */ - result = ps_include_page(I, NULL); - if (result < 0) - goto error; - } - if (_opts.verbose) - MESG(",Page:%ld", I->page_no); - I->subtype = PDF_XOBJECT_TYPE_FORM; - break; - // case IMAGE_TYPE_EPS: - default: - if (_opts.verbose) - MESG(format == IMAGE_TYPE_EPS ? "[PS]" : "[UNKNOWN]"); - if (ps_include_page(I, NULL) < 0) - goto error; - if (_opts.verbose) - MESG(",Page:%ld", I->page_no); - I->subtype = PDF_XOBJECT_TYPE_FORM; - } - - switch (I->subtype) { - case PDF_XOBJECT_TYPE_IMAGE: - sprintf(I->res_name, "Im%d", id); - break; - case PDF_XOBJECT_TYPE_FORM: - sprintf(I->res_name, "Fm%d", id); - break; - default: - ERROR("Unknown XObject subtype: %d", I->subtype); - goto error; - } - - ic->count++; - - return id; - - error: - pdf_clean_ximage_struct(I); - return -1; -} - - -#define dpx_find_file(n,d,s) (kpse_find_pict((n))) -#define dpx_fopen(n,m) (MFOPEN((n),(m))) -#define dpx_fclose(f) (MFCLOSE((f))) - -int -pdf_ximage_findresource (const char *ident, long page_no, pdf_obj *dict) -{ - struct ic_ *ic = &_ic; - int id = -1; - pdf_ximage *I; - char *fullname, *f = NULL; - int format; - FILE *fp; - - for (id = 0; id < ic->count; id++) { - I = &ic->ximages[id]; - if (I->ident && !strcmp(ident, I->ident)) { - f = I->filename; - if (I->page_no == page_no && I->attr_dict == dict) { - return id; - } - } - } - - if (f) { - /* we already have converted this file; f is the temporary file name */ - fullname = NEW(strlen(f)+1, char); - strcpy(fullname, f); - } else { - /* try loading image */ - fullname = dpx_find_file(ident, "_pic_", ""); - if (!fullname) { - WARN("Error locating image file \"%s\"", ident); - return -1; - } - } - - fp = dpx_fopen(fullname, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Error opening image file \"%s\"", fullname); - RELEASE(fullname); - return -1; - } - if (_opts.verbose) { - MESG("(Image:%s", ident); - if (_opts.verbose > 1) - MESG("[%s]", fullname); - } - - format = source_image_type(fp); - switch (format) { - case IMAGE_TYPE_MPS: - if (_opts.verbose) - MESG("[MPS]"); - id = mps_include_page(ident, fp); - if (id < 0) { - WARN("Try again with the distiller."); - format = IMAGE_TYPE_EPS; - rewind(fp); - } else - break; - default: - id = load_image(ident, fullname, format, fp, page_no, dict); - break; - } - dpx_fclose(fp); - - RELEASE(fullname); - - if (_opts.verbose) - MESG(")"); - - if (id < 0) - WARN("pdf: image inclusion failed for \"%s\".", ident); - - 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) -{ - info->flags = 0; - info->bbox.llx = 0; - info->bbox.lly = 0; - info->bbox.urx = 0; - info->bbox.ury = 0; - info->matrix.a = 1.0; - info->matrix.b = 0.0; - info->matrix.c = 0.0; - info->matrix.d = 1.0; - info->matrix.e = 0.0; - 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) -{ - info->flags = 0; - info->width = 0; - info->height = 0; - info->bits_per_component = 0; - info->num_components = 0; - info->min_dpi = 0; - info->xdensity = info->ydensity = 1.0; -} - -#ifdef XETEX -char * -pdf_ximage_get_ident (pdf_ximage *I) -{ - return I->ident; -} -#endif - -void -pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) -{ - pdf_obj *dict; - ximage_info *info = image_info; - - if (!PDF_OBJ_STREAMTYPE(resource)) - ERROR("Image XObject must be of stream type."); - - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - - 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); - - dict = pdf_stream_dict(resource); - pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("XObject")); - pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image")); - pdf_add_dict(dict, pdf_new_name("Width"), pdf_new_number(info->width)); - pdf_add_dict(dict, pdf_new_name("Height"), pdf_new_number(info->height)); - pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), - pdf_new_number(info->bits_per_component)); - if (I->attr_dict) - pdf_merge_dict(dict, I->attr_dict); - - pdf_release_obj(resource); /* Caller don't know we are using reference. */ - I->resource = NULL; -} - -void -pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) -{ - 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; -} - -#define CHECK_ID(c,n) do {\ - if ((n) < 0 || (n) >= (c)->count) {\ - ERROR("Invalid XObject ID: %d", (n));\ - }\ -} while (0) -#define GET_IMAGE(c,n) (&((c)->ximages[(n)])) - -pdf_obj * -pdf_ximage_get_reference (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - if (!I->reference) - I->reference = pdf_ref_obj(I->resource); - - 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; - - id = ic->count; - if (ic->count >= ic->capacity) { - ic->capacity += 16; - ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); - } - - I = &ic->ximages[id]; - - pdf_init_ximage_struct(I, ident, NULL, 0, NULL); - - switch (subtype) { - case PDF_XOBJECT_TYPE_IMAGE: - pdf_ximage_set_image(I, info, resource); - sprintf(I->res_name, "Im%d", id); - break; - case PDF_XOBJECT_TYPE_FORM: - pdf_ximage_set_form (I, info, resource); - sprintf(I->res_name, "Fm%d", id); - break; - default: - ERROR("Unknown XObject subtype: %d", subtype); - } - ic->count++; - - return id; -} - - -char * -pdf_ximage_get_resname (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - - return I->res_name; -} - -#ifndef XETEX -int -pdf_ximage_get_subtype (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - - return I->subtype; -} - -void -pdf_ximage_set_attr (int id, long width, long height, double xdensity, double ydensity, double llx, double lly, double urx, double ury) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - I->attr.width = width; - I->attr.height = height; - I->attr.xdensity = xdensity; - I->attr.ydensity = ydensity; - I->attr.bbox.llx = llx; - I->attr.bbox.lly = lly; - I->attr.bbox.urx = urx; - I->attr.bbox.ury = ury; -} -#endif - -/* 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 - -static void -scale_to_fit_I (pdf_tmatrix *T, - transform_info *p, - pdf_ximage *I) -{ - double s_x, s_y, d_x, d_y; - double wd0, ht0, dp, xscale, yscale; - - 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; - } - - if (wd0 == 0.0) { - WARN("Image width=0.0!"); - wd0 = 1.0; - } - if (ht0 == 0.0) { - WARN("Image height=0.0!"); - ht0 = 1.0; - } - - if ( (p->flags & INFO_HAS_WIDTH ) && - (p->flags & INFO_HAS_HEIGHT) ) { - 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) * yscale; - s_x = s_y * ((double)I->attr.width / I->attr.height); - dp = p->depth * yscale; - } else { - 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 = d_x * s_x / xscale; T->f = d_y * s_y / yscale - dp; - - return; -} - - -static void -scale_to_fit_F (pdf_tmatrix *T, - transform_info *p, - pdf_ximage *I) -{ - double s_x, s_y, d_x, d_y; - double wd0, ht0, dp; - - if (p->flags & INFO_HAS_USER_BBOX) { - wd0 = p->bbox.urx - p->bbox.llx; - ht0 = p->bbox.ury - p->bbox.lly; - d_x = -p->bbox.llx; - d_y = -p->bbox.lly; - } else { - wd0 = I->attr.bbox.urx - I->attr.bbox.llx; - ht0 = I->attr.bbox.ury - I->attr.bbox.lly; - d_x = 0.0; - d_y = 0.0; - } - - if (wd0 == 0.0) { - WARN("Image width=0.0!"); - wd0 = 1.0; - } - if (ht0 == 0.0) { - WARN("Image height=0.0!"); - ht0 = 1.0; - } - - if ( (p->flags & INFO_HAS_WIDTH ) && - (p->flags & INFO_HAS_HEIGHT) ) { - s_x = p->width / wd0; - s_y = (p->height + p->depth) / ht0; - dp = p->depth; - } else if ( p->flags & INFO_HAS_WIDTH ) { - s_x = p->width / wd0; - s_y = s_x; - dp = 0.0; - } else if ( p->flags & INFO_HAS_HEIGHT) { - s_y = (p->height + p->depth) / ht0; - s_x = s_y; - dp = p->depth; - } else { - s_x = s_y = 1.0; - dp = 0.0; - } - - T->a = s_x; T->c = 0.0; - T->b = 0.0; T->d = s_y; - T->e = s_x * d_x; T->f = s_y * d_y - dp; - - return; -} - - -/* called from pdfdev.c and spc_html.c */ -int -pdf_ximage_scale_image (int id, - 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; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, 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); - 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) { - r->llx = p->bbox.llx; - r->lly = p->bbox.lly; - r->urx = p->bbox.urx; - r->ury = p->bbox.ury; - } 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; - r->ury = I->attr.bbox.ury; - } - break; - } - - return 0; -} - - -/* Migrated from psimage.c */ - -void set_distiller_template (char *s) -{ - if (_opts.cmdtmpl) - RELEASE(_opts.cmdtmpl); - if (!s || *s == '\0') - _opts.cmdtmpl = NULL; - else { - _opts.cmdtmpl = NEW(strlen(s) + 1, char); - strcpy(_opts.cmdtmpl, s); - } - return; -} - -#ifdef XETEX -char *get_distiller_template (void) -{ - return _opts.cmdtmpl; -} -#endif - -static int -ps_include_page (pdf_ximage *ximage, const char *filename) -{ - char *distiller_template = _opts.cmdtmpl; - char *temp; - FILE *fp; - int error = 0; - struct stat stat_o, stat_t; - - filename = ximage->filename; - - if (!distiller_template) { - WARN("No image converter available for converting file \"%s\" to PDF format.", filename); - WARN(">> Please check if you have 'D' option in config file."); - return -1; - } - - temp = dpx_create_fix_temp_file(filename); - if (!temp) { - WARN("Failed to create temporary file for image conversion: %s", filename); - return -1; - } - - if (keep_cache != -1 && stat(temp, &stat_t)==0 && stat(filename, &stat_o)==0 - && stat_t.st_mtime > stat_o.st_mtime) { - /* cache exist */ - /*printf("\nLast file modification: %s", ctime(&stat_o.st_mtime)); - printf("Last file modification: %s", ctime(&stat_t.st_mtime));*/ - ; - } else { - if (_opts.verbose > 1) { - MESG("\n"); - MESG("pdf_image>> Converting file \"%s\" --> \"%s\" via:\n", filename, temp); - MESG("pdf_image>> %s\n", distiller_template); - MESG("pdf_image>> ..."); - } - error = dpx_file_apply_filter(distiller_template, filename, temp, - (unsigned char) pdf_get_version()); - if (error) { - WARN("Image format conversion for \"%s\" failed...", filename); - dpx_delete_temp_file(temp, true); - return error; - } - } - - fp = MFOPEN(temp, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Could not open conversion result \"%s\" for image \"%s\". Why?", temp, filename); - dpx_delete_temp_file(temp, true); - return -1; - } - pdf_set_ximage_tempfile(ximage, temp); -#if 0 - error = pdf_include_page(ximage, fp, 0, pdfbox_crop); -#endif - error = pdf_include_page(ximage, fp, temp); - MFCLOSE(fp); - - /* See pdf_close_images for why we cannot delete temporary files here. */ - - RELEASE(temp); - - if (error) { - WARN("Failed to include image file \"%s\"", filename); - WARN(">> Please check if"); - WARN(">> %s", distiller_template); - WARN(">> %%o = output filename, %%i = input filename, %%b = input filename without suffix"); - WARN(">> can really convert \"%s\" to PDF format image.", filename); - } - - return error; -} - -static int check_for_ps (FILE *image_file) -{ - rewind (image_file); - mfgets (work_buffer, WORK_BUFFER_SIZE, image_file); - if (!strncmp (work_buffer, "%!", 2)) - return 1; - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/src/spc_pdfm.c b/Build/source/texk/dvipdfm-x/src/spc_pdfm.c deleted file mode 100644 index 4f57cb116c4..00000000000 --- a/Build/source/texk/dvipdfm-x/src/spc_pdfm.c +++ /dev/null @@ -1,2130 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" - -#include "numbers.h" - -#include "fontmap.h" -#include "dpxfile.h" -#include "dpxutil.h" - -#include "pdfobj.h" -#include "pdfparse.h" - -#include "pdfdoc.h" - -#include "pdfximage.h" -#include "pdfdraw.h" -#include "pdfcolor.h" -#include "pdfdev.h" - -#include "specials.h" - -#include "spc_util.h" -#include "spc_pdfm.h" - -#include "dvipdfmx.h" - -#define ENABLE_TOUNICODE 1 - - -/* PLEASE REMOVE THIS */ -struct resource_map { - int type; - int res_id; -}; - -#ifdef ENABLE_TOUNICODE -struct tounicode { - int cmap_id; - int unescape_backslash; - pdf_obj *taintkeys; /* An array of PDF names. */ -}; -#endif /* ENABLE_TOUNICODE */ - -struct spc_pdf_ -{ - pdf_obj *annot_dict; /* pending annotation dict */ - int lowest_level; /* current min level of outlines */ - struct ht_table *resourcemap; /* see remark below (somewhere) */ -#ifdef ENABLE_TOUNICODE - struct tounicode cd; /* For to-UTF16-BE conversion :( */ -#endif /* ENABLE_TOUNICODE */ -}; - -#if 1 -static struct spc_pdf_ _pdf_stat = { - NULL, - 255, - NULL, -#ifdef ENABLE_TOUNICODE - { -1, 0, NULL } -#endif /* ENABLE_TOUNICODE */ -}; -#endif - -/* PLEASE REMOVE THIS */ -static void -hval_free (void *vp) -{ - RELEASE(vp); -} - - -static int -addresource (struct spc_pdf_ *sd, const char *ident, int res_id) -{ - struct resource_map *r; - - if (!ident || res_id < 0) - return -1; - - r = NEW(1, struct resource_map); - r->type = 0; /* unused */ - r->res_id = res_id; - - ht_append_table(sd->resourcemap, ident, strlen(ident), r); - spc_push_object(ident, pdf_ximage_get_reference(res_id)); - - return 0; -} - -static int -findresource (struct spc_pdf_ *sd, const char *ident) -{ - struct resource_map *r; - - if (!ident) - return -1; - - r = ht_lookup_table(sd->resourcemap, ident, strlen(ident)); - - return (r ? r->res_id : -1); -} - - -static int -spc_handler_pdfm__init (struct spc_env *spe, struct spc_arg *ap, void *dp) -{ - struct spc_pdf_ *sd = dp; -#ifdef ENABLE_TOUNICODE - static const char *default_taintkeys[] = { - "Title", "Author", "Subject", "Keywords", - "Creator", "Producer", "Contents", "Subj", - "TU", "T", "TM", NULL /* EOD */ - }; - int i; -#endif /* ENABLE_TOUNICODE */ - - sd->annot_dict = NULL; - sd->lowest_level = 255; - sd->resourcemap = NEW(1, struct ht_table); - ht_init_table(sd->resourcemap, hval_free); - -#ifdef ENABLE_TOUNICODE - sd->cd.taintkeys = pdf_new_array(); - for (i = 0; default_taintkeys[i] != NULL; i++) { - pdf_add_array(sd->cd.taintkeys, - pdf_new_name(default_taintkeys[i])); - } -#endif /* ENABLE_TOUNICODE */ - - return 0; -} - -static int -spc_handler_pdfm__clean (struct spc_env *spe, struct spc_arg *ap, void *dp) -{ - struct spc_pdf_ *sd = dp; - - if (sd->annot_dict) { - WARN("Unbalanced bann and eann found."); - pdf_release_obj(sd->annot_dict); - } - sd->lowest_level = 255; - sd->annot_dict = NULL; - if (sd->resourcemap) { - ht_clear_table(sd->resourcemap); - RELEASE(sd->resourcemap); - } - sd->resourcemap = NULL; - -#ifdef ENABLE_TOUNICODE - if (sd->cd.taintkeys) - pdf_release_obj(sd->cd.taintkeys); - sd->cd.taintkeys = NULL; -#endif /* ENABLE_TOUNICODE */ - - return 0; -} - - -int -spc_pdfm_at_begin_document (void) -{ - struct spc_pdf_ *sd = &_pdf_stat; - return spc_handler_pdfm__init(NULL, NULL, sd); -} - -int -spc_pdfm_at_end_document (void) -{ - struct spc_pdf_ *sd = &_pdf_stat; - return spc_handler_pdfm__clean(NULL, NULL, sd); -} - - -/* Dvipdfm specials */ -static int -spc_handler_pdfm_bop (struct spc_env *spe, struct spc_arg *args) -{ - if (args->curptr < args->endptr) { - pdf_doc_set_bop_content(args->curptr, - (long) (args->endptr - args->curptr)); - } - - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_eop (struct spc_env *spe, struct spc_arg *args) -{ - if (args->curptr < args->endptr) { - pdf_doc_set_eop_content(args->curptr, - (long) (args->endptr - args->curptr)); - } - - args->curptr = args->endptr; - - return 0; -} - -#define streamfiltered(o) \ - (pdf_lookup_dict(pdf_stream_dict((o)), "Filter") ? 1 : 0) - -/* Why should we have this kind of things? */ -static int -safeputresdent (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - char *key; - - ASSERT(kp && vp && dp); - - key = pdf_name_value(kp); - if (pdf_lookup_dict(dp, key)) - WARN("Object \"%s\" already defined in dict! (ignored)", key); - else { - pdf_add_dict(dp, - pdf_link_obj(kp), pdf_link_obj(vp)); - } - return 0; -} - -#ifndef pdf_obj_isaref -#define pdf_obj_isaref(o) (pdf_obj_typeof((o)) == PDF_INDIRECT) -#endif - -static int -safeputresdict (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - char *key; - pdf_obj *dict; - - ASSERT(kp && vp && dp); - - key = pdf_name_value(kp); - dict = pdf_lookup_dict(dp, key); - - if (pdf_obj_isaref(vp)) { - pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); - } else if (pdf_obj_typeof(vp) == PDF_DICT) { - if (dict) - pdf_foreach_dict(vp, safeputresdent, dict); - else { - pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); - } - } else { - WARN("Invalid type (not DICT) for page/form resource dict entry: key=\"%s\"", key); - return -1; - } - - return 0; -} - - -/* Think what happens if you do - * - * pdf:put @resources << /Font << >> >> - * - */ -static int -spc_handler_pdfm_put (struct spc_env *spe, struct spc_arg *ap) -{ - pdf_obj *obj1, *obj2; /* put obj2 into obj1 */ - char *ident; - int error = 0; - - skip_white(&ap->curptr, ap->endptr); - - ident = parse_opt_ident(&ap->curptr, ap->endptr); - if (!ident) { - spc_warn(spe, "Missing object identifier."); - return -1; - } - obj1 = spc_lookup_object(ident); - if (!obj1) { - spc_warn(spe, "Specified object not exist: %s", ident); - RELEASE(ident); - return -1; - } - skip_white(&ap->curptr, ap->endptr); - - obj2 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); - if (!obj2) { - spc_warn(spe, "Missing (an) object(s) to put into \"%s\"!", ident); - RELEASE(ident); - return -1; - } - - switch (pdf_obj_typeof(obj1)) { - case PDF_DICT: - if (pdf_obj_typeof(obj2) != PDF_DICT) { - spc_warn(spe, "Inconsistent object type for \"put\" (expecting DICT): %s", ident); - error = -1; - } else { - if (!strcmp(ident, "resources")) - error = pdf_foreach_dict(obj2, safeputresdict, obj1); - else { - pdf_merge_dict(obj1, obj2); - } - } - break; - - case PDF_STREAM: - if (pdf_obj_typeof(obj2) == PDF_DICT) - pdf_merge_dict(pdf_stream_dict(obj1), obj2); - else if (pdf_obj_typeof(obj2) == PDF_STREAM) -#if 0 - { - pdf_merge_dict(pdf_stream_dict(obj1), pdf_stream_dict(obj2)); - pdf_add_stream(obj1, pdf_stream_dataptr(obj2), pdf_stream_length(obj2)); - } -#else - { - spc_warn(spe, "\"put\" operation not supported for STREAM <- STREAM: %s", ident); - error = -1; - } -#endif - else { - spc_warn(spe, "Invalid type: expecting a DICT or STREAM: %s", ident); - error = -1; - } - break; - - case PDF_ARRAY: - /* dvipdfm */ - pdf_add_array(obj1, pdf_link_obj(obj2)); - while (ap->curptr < ap->endptr) { - pdf_obj *obj3 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); - if (!obj3) - break; - pdf_add_array(obj1, obj3); - skip_white(&ap->curptr, ap->endptr); - } - break; - - default: - spc_warn(spe, "Can't \"put\" object into non-DICT/STREAM/ARRAY type object: %s", ident); - error = -1; - break; - } - pdf_release_obj(obj2); - RELEASE(ident); - - return error; -} - - -#ifdef ENABLE_TOUNICODE - -/* For pdf:tounicode support - * This feature is provided for convenience. TeX can't do - * input encoding conversion. - */ -#include "cmap.h" - -static int -reencodestring (CMap *cmap, pdf_obj *instring) -{ -#define WBUF_SIZE 4096 - unsigned char wbuf[WBUF_SIZE]; - unsigned char *obufcur; - const unsigned char *inbufcur; - long inbufleft, obufleft; - - if (!cmap || !instring) - return 0; - - inbufleft = pdf_string_length(instring); - inbufcur = pdf_string_value (instring); - - wbuf[0] = 0xfe; - wbuf[1] = 0xff; - obufcur = wbuf + 2; - obufleft = WBUF_SIZE - 2; - - CMap_decode(cmap, - &inbufcur, &inbufleft, - &obufcur, &obufleft); - - if (inbufleft > 0) { - return -1; - } - - pdf_set_string(instring, wbuf, WBUF_SIZE - obufleft); - - return 0; -} - -#ifdef XETEX -/* tables/values used in UTF-8 interpretation - - code is based on ConvertUTF.[ch] sample code - published by the Unicode consortium */ -static unsigned long -offsetsFromUTF8[6] = { - 0x00000000UL, - 0x00003080UL, - 0x000E2080UL, - 0x03C82080UL, - 0xFA082080UL, - 0x82082080UL -}; - -static unsigned char -bytesFromUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -static int -maybe_reencode_utf8(pdf_obj *instring) -{ - unsigned char* inbuf; - int inlen; - int non_ascii = 0; - unsigned char* cp; - unsigned char* op; - unsigned char wbuf[WBUF_SIZE]; - - if (!instring) - return 0; - - inlen = pdf_string_length(instring); - inbuf = pdf_string_value(instring); - - /* check if the input string is strictly ASCII */ - for (cp = inbuf; cp < inbuf + inlen; ++cp) { - if (*cp > 127) { - non_ascii = 1; - } - } - if (non_ascii == 0) - return 0; /* no need to reencode ASCII strings */ - - cp = inbuf; - op = wbuf; - *op++ = 0xfe; - *op++ = 0xff; - while (cp < inbuf + inlen) { - unsigned long usv = *cp++; - int extraBytes = bytesFromUTF8[usv]; - if (cp + extraBytes > inbuf + inlen) - return -1; /* ill-formed, so give up reencoding */ - switch (extraBytes) { /* note: code falls through cases! */ - case 5: usv <<= 6; usv += *cp++; - case 4: usv <<= 6; usv += *cp++; - case 3: usv <<= 6; usv += *cp++; - case 2: usv <<= 6; usv += *cp++; - case 1: usv <<= 6; usv += *cp++; - case 0: ; - }; - usv -= offsetsFromUTF8[extraBytes]; - if (usv > 0x10FFFF) - return -1; /* out of valid Unicode range, give up */ - if (usv > 0xFFFF) { - /* supplementary-plane character: generate high surrogate */ - unsigned long hi = 0xdc00 + (usv - 0x10000) % 0x0400; - if (op > wbuf + WBUF_SIZE - 2) - return -1; /* out of space */ - *op++ = hi / 256; - *op++ = hi % 256; - usv = 0xd800 + (usv - 0x10000) / 0x0400; - /* remaining value in usv is the low surrogate */ - } - if (op > wbuf + WBUF_SIZE - 2) - return -1; /* out of space */ - *op++ = usv / 256; - *op++ = usv % 256; - } - - pdf_set_string(instring, wbuf, op - wbuf); - - return 0; -} -#endif - -static int -needreencode (pdf_obj *kp, pdf_obj *vp, struct tounicode *cd) -{ - int r = 0, i; - pdf_obj *tk; - - ASSERT( cd && cd->taintkeys ); - ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); - ASSERT( pdf_obj_typeof(vp) == PDF_STRING ); - - for (i = 0; i < pdf_array_length(cd->taintkeys); i++) { - tk = pdf_get_array(cd->taintkeys, i); - ASSERT( tk && pdf_obj_typeof(tk) == PDF_NAME ); - if (!strcmp(pdf_name_value(kp), pdf_name_value(tk))) { - r = 1; - break; - } - } - if (r) { - /* Check UTF-16BE BOM. */ - if (pdf_string_length(vp) >= 2 && - !memcmp(pdf_string_value(vp), "\xfe\xff", 2)) - r = 0; - } - - return r; -} - -static int modstrings (pdf_obj *key, pdf_obj *value, void *pdata); - -static int -modstrings (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - int r = 0; /* continue */ - struct tounicode *cd = dp; - - ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); - - if (!cd || cd->cmap_id < 0 || !cd->taintkeys) - return -1; - - switch (pdf_obj_typeof(vp)) { - case PDF_STRING: - { - CMap *cmap; - - { - cmap = CMap_cache_get(cd->cmap_id); - if (needreencode(kp, vp, cd)) { - r = reencodestring(cmap, vp); - } - } - if (r < 0) /* error occured... */ - WARN("Failed to convert input string to UTF16..."); - } - break; - case PDF_DICT: - r = pdf_foreach_dict(vp, modstrings, dp); - break; - case PDF_STREAM: - r = pdf_foreach_dict(pdf_stream_dict(vp), modstrings, dp); - break; - } - - return r; -} - -static pdf_obj * -my_parse_pdf_dict (const char **pp, const char *endptr, struct tounicode *cd) -{ - pdf_obj *dict; - -#ifdef XETEX -/* disable this test, as we do utf8 reencoding with no cmap */ -#else - if (cd->cmap_id < 0) - return parse_pdf_dict(pp, endptr, NULL); -#endif - - /* :( */ - if (cd && cd->unescape_backslash) - dict = parse_pdf_tainted_dict(pp, endptr); - else { - dict = parse_pdf_dict(pp, endptr, NULL); - } - if (dict) - pdf_foreach_dict(dict, modstrings, cd); - - return dict; -} - -#endif /* ENABLE_TOUNICODE */ - - -static int -spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *annot_dict; - pdf_rect rect; - char *ident = NULL; - pdf_coord cp; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] == '@') { - ident = parse_opt_ident(&args->curptr, args->endptr); - skip_white(&args->curptr, args->endptr); - } - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - if (ident) - RELEASE(ident); - return -1; - } - - if ((ti.flags & INFO_HAS_USER_BBOX) && - ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { - spc_warn(spe, "You can't specify both bbox and width/height."); - if (ident) - RELEASE(ident); - return -1; - } - -#ifdef ENABLE_TOUNICODE - annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!annot_dict) { - spc_warn(spe, "Could not find dictionary object."); - if (ident) - RELEASE(ident); - return -1; - } else if (!PDF_OBJ_DICTTYPE(annot_dict)) { - spc_warn(spe, "Invalid type: not dictionary object."); - if (ident) - RELEASE(ident); - pdf_release_obj(annot_dict); - return -1; - } - - cp.x = spe->x_user; cp.y = spe->y_user; - pdf_dev_transform(&cp, NULL); - if (ti.flags & INFO_HAS_USER_BBOX) { - rect.llx = ti.bbox.llx + cp.x; - rect.lly = ti.bbox.lly + cp.y; - rect.urx = ti.bbox.urx + cp.x; - rect.ury = ti.bbox.ury + cp.y; - } else { - rect.llx = cp.x; - rect.lly = cp.y - spe->mag * ti.depth; - rect.urx = cp.x + spe->mag * ti.width; - rect.ury = cp.y + spe->mag * ti.height; - } - - /* Order is important... */ - if (ident) - spc_push_object(ident, pdf_link_obj(annot_dict)); - /* This add reference. */ - pdf_doc_add_annot(pdf_doc_current_page_number(), &rect, annot_dict, 1); - - if (ident) { - spc_flush_object(ident); - RELEASE(ident); - } - pdf_release_obj(annot_dict); - - return 0; -} - -/* NOTE: This can't have ident. See "Dvipdfm User's Manual". */ -static int -spc_handler_pdfm_bann (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int error = 0; - - if (sd->annot_dict) { - spc_warn(spe, "Can't begin an annotation when one is pending."); - return -1; - } - - skip_white(&args->curptr, args->endptr); - -#ifdef ENABLE_TOUNICODE - sd->annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - sd->annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!sd->annot_dict) { - spc_warn(spe, "Ignoring annotation with invalid dictionary."); - return -1; - } else if (!PDF_OBJ_DICTTYPE(sd->annot_dict)) { - spc_warn(spe, "Invalid type: not a dictionary object."); - pdf_release_obj(sd->annot_dict); - sd->annot_dict = NULL; - return -1; - } - - error = spc_begin_annot(spe, sd->annot_dict); - - return error; -} - -static int -spc_handler_pdfm_eann (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int error = 0; - - if (!sd->annot_dict) { - spc_warn(spe, "Tried to end an annotation without starting one!"); - return -1; - } - - error = spc_end_annot(spe); - - pdf_release_obj(sd->annot_dict); - sd->annot_dict = NULL; - - return error; -} - - -/* Color:.... */ -static int -spc_handler_pdfm_bcolor (struct spc_env *spe, struct spc_arg *ap) -{ - int error; - pdf_color fc, sc; - pdf_color *pfc, *psc; - - pdf_color_get_current(&psc, &pfc); - error = spc_util_read_pdfcolor(spe, &fc, ap, pfc); - if (!error) { - if (ap->curptr < ap->endptr) { - error = spc_util_read_pdfcolor(spe, &sc, ap, psc); - } else { - pdf_color_copycolor(&sc, &fc); - } - } - - if (error) - spc_warn(spe, "Invalid color specification?"); - else { - pdf_color_push(&sc, &fc); /* save currentcolor */ - } - - return error; -} - -/* - * This special changes the current color without clearing the color stack. - * It therefore differs from "color rgb 1 0 0". - */ -static int -spc_handler_pdfm_scolor (struct spc_env *spe, struct spc_arg *ap) -{ - int error; - pdf_color fc, sc; - pdf_color *pfc, *psc; - - pdf_color_get_current(&psc, &pfc); - error = spc_util_read_pdfcolor(spe, &fc, ap, pfc); - if (!error) { - if (ap->curptr < ap->endptr) { - error = spc_util_read_pdfcolor(spe, &sc, ap, psc); - } else { - pdf_color_copycolor(&sc, &fc); - } - } - - if (error) - spc_warn(spe, "Invalid color specification?"); - else { - pdf_color_set(&sc, &fc); - } - - return error; -} - -static int -spc_handler_pdfm_ecolor (struct spc_env *spe, struct spc_arg *args) -{ - pdf_color_pop(); - return 0; -} - - -static int -spc_handler_pdfm_btrans (struct spc_env *spe, struct spc_arg *args) -{ - pdf_tmatrix M; - transform_info ti; - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - return -1; - } - - /* Create transformation matrix */ - pdf_copymatrix(&M, &(ti.matrix)); - 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); - - pdf_dev_gsave(); - pdf_dev_concat(&M); - - return 0; -} - -static int -spc_handler_pdfm_etrans (struct spc_env *spe, struct spc_arg *args) -{ - pdf_dev_grestore(); - - /* - * Unfortunately, the following line is necessary in case - * of a color change inside of the save/restore pair. - * (Font changes are automatically corrected by pdf_dev_grestore().) - * Anything that was done there must be redone, so in effect, - * we make no assumptions about what fonts. We act like we are - * starting a new page. - */ - pdf_dev_reset_color(0); - - return 0; -} - -static int -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, 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, NULL); - if (!tmp) { - spc_warn(spe, "Missing number for outline item depth."); - return -1; - } else if (!PDF_OBJ_NUMBERTYPE(tmp)) { - pdf_release_obj(tmp); - spc_warn(spe, "Expecting number for outline item depth."); - return -1; - } - - item_dict = NULL; - - level = (int) pdf_number_value(tmp); - pdf_release_obj(tmp); - - /* What is this? Starting at level 3 and can go down to level 1? - * - * Here is the original comment: - * Make sure we know where the starting level is - * - * NOTE: added - * We need this for converting pages from 3rd to... :( - */ - sd->lowest_level = MIN(sd->lowest_level, level); - - level += 1 - sd->lowest_level; - -#ifdef ENABLE_TOUNICODE - item_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - item_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!item_dict) { - spc_warn(spe, "Ignoring invalid dictionary."); - return -1; - } - current_depth = pdf_doc_bookmarks_depth(); - if (current_depth > level) { - while (current_depth-- > level) - pdf_doc_bookmarks_up(); - } else if (current_depth < level) { - while (current_depth++ < level) - pdf_doc_bookmarks_down(); - } - - pdf_doc_bookmarks_add(item_dict, is_open); - - return 0; -} - -static int -spc_handler_pdfm_article (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - char *ident; - pdf_obj *info_dict; - - skip_white (&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Article name expected but not found."); - return -1; - } - -#ifdef ENABLE_TOUNICODE - info_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - info_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!info_dict) { - spc_warn(spe, "Ignoring article with invalid info dictionary."); - RELEASE(ident); - return -1; - } - - pdf_doc_begin_article(ident, pdf_link_obj(info_dict)); - spc_push_object(ident, info_dict); - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_bead (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *article; - pdf_obj *article_info; - char *article_name; - pdf_rect rect; - long page_no; - transform_info ti; - pdf_coord cp; - - skip_white(&args->curptr, args->endptr); - - if (args->curptr[0] != '@') { - spc_warn(spe, "Article identifier expected but not found."); - return -1; - } - - article_name = parse_opt_ident(&args->curptr, args->endptr); - if (!article_name) { - spc_warn(spe, "Article reference expected but not found."); - return -1; - } - - /* If okay so far, try to get a bounding box */ - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(article_name); - return -1; - } - - if ((ti.flags & INFO_HAS_USER_BBOX) && - ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { - spc_warn(spe, "You can't specify both bbox and width/height."); - RELEASE(article_name); - return -1; - } - - cp.x = spe->x_user; cp.y = spe->y_user; - pdf_dev_transform(&cp, NULL); - if (ti.flags & INFO_HAS_USER_BBOX) { - rect.llx = ti.bbox.llx + cp.x; - rect.lly = ti.bbox.lly + cp.y; - rect.urx = ti.bbox.urx + cp.x; - rect.ury = ti.bbox.ury + cp.y; - } else { - rect.llx = cp.x; - rect.lly = cp.y - spe->mag * ti.depth; - rect.urx = cp.x + spe->mag * ti.width; - rect.ury = cp.y + spe->mag * ti.height; - } - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] != '<') { - article_info = pdf_new_dict(); - } else { -#ifdef ENABLE_TOUNICODE - article_info = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - article_info = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!article_info) { - spc_warn(spe, "Error in reading dictionary."); - RELEASE(article_name); - return -1; - } - } - - /* Does this article exist yet */ - article = spc_lookup_object(article_name); - if (article) { - pdf_merge_dict (article, article_info); - pdf_release_obj(article_info); - } else { - pdf_doc_begin_article(article_name, pdf_link_obj(article_info)); - spc_push_object(article_name, article_info); - } - page_no = pdf_doc_current_page_number(); - pdf_doc_add_bead(article_name, NULL, page_no, &rect); - - RELEASE(article_name); - return 0; -} - -static int -spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int xobj_id; - char *ident = NULL; - pdf_obj *fspec, *attr = NULL; - transform_info ti; - long page_no; - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] == '@') { - ident = parse_opt_ident(&args->curptr, args->endptr); - xobj_id = findresource(sd, ident); - if (xobj_id >= 0) { - spc_warn(spe, "Object reference name for image \"%s\" already used.", ident); - RELEASE(ident); - return -1; - } - } - - transform_info_clear(&ti); - page_no = 1; - if (spc_util_read_dimtrns(spe, &ti, args, &page_no, 0) < 0) { - if (ident) - RELEASE(ident); - return -1; - } - - skip_white(&args->curptr, args->endptr); - fspec = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!fspec) { - spc_warn(spe, "Missing filename string for pdf:image."); - if (ident) - RELEASE(ident); - return -1; - } 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; - } - - skip_white(&args->curptr, args->endptr); - if (args->curptr < args->endptr) { - attr = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!attr || !PDF_OBJ_DICTTYPE(attr)) { - spc_warn(spe, "Ignore invalid attribute dictionary."); - if (attr) pdf_release_obj(attr); - } - } - - xobj_id = pdf_ximage_findresource(pdf_string_value(fspec), page_no, attr); - if (xobj_id < 0) { - spc_warn(spe, "Could not find image resource..."); - pdf_release_obj(fspec); - if (ident) - RELEASE(ident); - return -1; - } - - if (!(ti.flags & INFO_DO_HIDE)) - pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); - - if (ident) { - if (compat_mode && - pdf_ximage_get_subtype(xobj_id) == PDF_XOBJECT_TYPE_IMAGE) - pdf_ximage_set_attr(xobj_id, 1, 1, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0); - addresource(sd, ident, xobj_id); - RELEASE(ident); - } - - pdf_release_obj(fspec); - - return 0; -} - -/* Use do_names instead. */ -static int -spc_handler_pdfm_dest (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *name, *array; - - skip_white(&args->curptr, args->endptr); - - name = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!name) { - spc_warn(spe, "PDF string expected for destination name but not found."); - return -1; - } else if (!PDF_OBJ_STRINGTYPE(name)) { - spc_warn(spe, "PDF string expected for destination name but invalid type."); - pdf_release_obj(name); - return -1; - } - -#ifdef XETEX -#ifdef ENABLE_TOUNICODE - if (maybe_reencode_utf8(name) < 0) - WARN("Failed to convert input string to UTF16..."); -#endif -#endif - - array = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!array) { - spc_warn(spe, "No destination specified for pdf:dest."); - pdf_release_obj(name); - return -1; - } else if (!PDF_OBJ_ARRAYTYPE(array)) { - spc_warn(spe, "Destination not specified as an array object!"); - pdf_release_obj(name); - pdf_release_obj(array); - return -1; - } - - pdf_doc_add_names("Dests", - pdf_string_value (name), - pdf_string_length(name), - array); - pdf_release_obj(name); - - return 0; -} - -static int -spc_handler_pdfm_names (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *category, *key, *value, *tmp; - int i, size; - - category = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!category) { - spc_warn(spe, "PDF name expected but not found."); - return -1; - } else if (!PDF_OBJ_NAMETYPE(category)) { - spc_warn(spe, "PDF name expected but not found."); - pdf_release_obj(category); - return -1; - } - - tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "PDF object expected but not found."); - pdf_release_obj(category); - return -1; - } else if (PDF_OBJ_ARRAYTYPE(tmp)) { - size = pdf_array_length(tmp); - if (size % 2 != 0) { - spc_warn(spe, "Array size not multiple of 2 for pdf:names."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } - - for (i = 0; i < size / 2; i++) { - key = pdf_get_array(tmp, 2 * i); - value = pdf_get_array(tmp, 2 * i + 1); - if (!PDF_OBJ_STRINGTYPE(key)) { - spc_warn(spe, "Name tree key must be string."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } else if (pdf_doc_add_names(pdf_name_value(category), - pdf_string_value (key), - pdf_string_length(key), - pdf_link_obj(value)) < 0) { - spc_warn(spe, "Failed to add Name tree entry..."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } - } - pdf_release_obj(tmp); - } else if (PDF_OBJ_STRINGTYPE(tmp)) { - key = tmp; - value = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!value) { - pdf_release_obj(category); - pdf_release_obj(key); - spc_warn(spe, "PDF object expected but not found."); - return -1; - } - if (pdf_doc_add_names(pdf_name_value(category), - pdf_string_value (key), - pdf_string_length(key), - value) < 0) { - spc_warn(spe, "Failed to add Name tree entry..."); - pdf_release_obj(category); - pdf_release_obj(key); - return -1; - } - pdf_release_obj(key); - } else { - pdf_release_obj(tmp); - pdf_release_obj(category); - spc_warn(spe, "Invalid object type for pdf:names."); - return -1; - } - pdf_release_obj(category); - - return 0; -} - -static int -spc_handler_pdfm_docinfo (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *docinfo, *dict; - -#ifdef ENABLE_TOUNICODE - dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!dict) { - spc_warn(spe, "Dictionary object expected but not found."); - return -1; - } - - docinfo = pdf_doc_docinfo(); - pdf_merge_dict(docinfo, dict); - pdf_release_obj(dict); - - return 0; -} - -static int -spc_handler_pdfm_docview (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *catalog, *dict; - pdf_obj *pref_old, *pref_add; - -#ifdef ENABLE_TOUNICODE - dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!dict) { - spc_warn(spe, "Dictionary object expected but not found."); - return -1; - } - - catalog = pdf_doc_catalog(); - /* Avoid overriding whole ViewerPreferences */ - pref_old = pdf_lookup_dict(catalog, "ViewerPreferences"); - pref_add = pdf_lookup_dict(dict, "ViewerPreferences"); - if (pref_old && pref_add) { - pdf_merge_dict (pref_old, pref_add); - pdf_remove_dict(dict, "ViewerPreferences"); - } - pdf_merge_dict (catalog, dict); - pdf_release_obj(dict); - - return 0; -} - -static int -spc_handler_pdfm_close (struct spc_env *spe, struct spc_arg *args) -{ - char *ident; - - skip_white(&args->curptr, args->endptr); - ident = parse_opt_ident(&args->curptr, args->endptr); - if (ident) { - spc_flush_object(ident); - RELEASE(ident); - } else { /* Close all? */ - spc_clear_objects(); - } - - return 0; -} - -static int -spc_handler_pdfm_object (struct spc_env *spe, struct spc_arg *args) -{ - char *ident; - pdf_obj *object; - - skip_white(&args->curptr, args->endptr); - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Could not find a object identifier."); - return -1; - } - - object = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!object) { - spc_warn(spe, "Could not find an object definition for \"%s\".", ident); - RELEASE(ident); - return -1; - } else { - spc_push_object(ident, object); - } - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_content (struct spc_env *spe, struct spc_arg *args) -{ - long len = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr < args->endptr) { - pdf_tmatrix M; - - pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user, spe->y_user); - work_buffer[len++] = ' '; - work_buffer[len++] = 'q'; - work_buffer[len++] = ' '; - len += pdf_sprint_matrix(work_buffer + len, &M); - work_buffer[len++] = ' '; - work_buffer[len++] = 'c'; - work_buffer[len++] = 'm'; - work_buffer[len++] = ' '; - - pdf_doc_add_page_content(work_buffer, len); /* op: q cm */ - len = (long) (args->endptr - args->curptr); - pdf_doc_add_page_content(args->curptr, len); /* op: ANY */ - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - } - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_literal (struct spc_env *spe, struct spc_arg *args) -{ - int direct = 0; - - skip_white(&args->curptr, args->endptr); - while (args->curptr < args->endptr) { - if (args->curptr + 7 <= args->endptr && - !strncmp(args->curptr, "reverse", 7)) { - args->curptr += 7; - WARN("The special \"pdf:literal reverse ...\" is no longer supported.\nIgnore the \"reverse\" option."); - } else if (args->curptr + 6 <= args->endptr && - !strncmp(args->curptr, "direct", 6)) { - direct = 1; - args->curptr += 6; - } else { - break; - } - skip_white(&args->curptr, args->endptr); - } - - if (args->curptr < args->endptr) { - pdf_tmatrix M; - if (!direct) { - M.a = M.d = 1.0; M.b = M.c = 0.0; - M.e = spe->x_user; M.f = spe->y_user; - pdf_dev_concat(&M); - } - pdf_doc_add_page_content(" ", 1); /* op: */ - pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ - if (!direct) { - M.e = -spe->x_user; M.f = -spe->y_user; - pdf_dev_concat(&M); - } - } - - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_bcontent (struct spc_env *spe, struct spc_arg *args) -{ - pdf_tmatrix M; - double xpos, ypos; - - pdf_dev_gsave(); - pdf_dev_get_coord(&xpos, &ypos); - pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user - xpos, spe->y_user - ypos); - pdf_dev_concat(&M); - pdf_dev_push_coord(spe->x_user, spe->y_user); - return 0; -} - -static int -spc_handler_pdfm_econtent (struct spc_env *spe, struct spc_arg *args) -{ - pdf_dev_pop_coord(); - pdf_dev_grestore(); - pdf_dev_reset_color(0); - - return 0; -} - -static int -spc_handler_pdfm_code (struct spc_env *spe, struct spc_arg *args) -{ - skip_white(&args->curptr, args->endptr); - - if (args->curptr < args->endptr) { - pdf_doc_add_page_content(" ", 1); /* op: */ - pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ - args->curptr = args->endptr; - } - - return 0; -} - -static int -spc_handler_pdfm_do_nothing (struct spc_env *spe, struct spc_arg *args) -{ - args->curptr = args->endptr; - return 0; -} - -#define STRING_STREAM 0 -#define FILE_STREAM 1 - -static int -spc_handler_pdfm_stream_with_type (struct spc_env *spe, struct spc_arg *args, int type) -{ - pdf_obj *fstream; - long nb_read; - char *ident, *instring, *fullname; - pdf_obj *tmp; - FILE *fp; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Missing objname for pdf:(f)stream."); - return -1; - } - - skip_white(&args->curptr, args->endptr); - - tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "Missing input string for pdf:(f)stream."); - RELEASE(ident); - return -1; - } else if (!PDF_OBJ_STRINGTYPE(tmp)) { - spc_warn(spe, "Invalid type of input string for pdf:(f)stream."); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - - instring = pdf_string_value(tmp); - - switch (type) { - case FILE_STREAM: - if (!instring) { - spc_warn(spe, "Missing filename for pdf:fstream."); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - fullname = kpse_find_pict(instring); - if (!fullname) { - spc_warn(spe, "File \"%s\" not found.", instring); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - fp = DPXFOPEN(fullname, DPX_RES_TYPE_BINARY); - if (!fp) { - spc_warn(spe, "Could not open file: %s", instring); - pdf_release_obj(tmp); - RELEASE(ident); - RELEASE(fullname); - return -1; - } - fstream = pdf_new_stream(STREAM_COMPRESS); - while ((nb_read = - fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) - pdf_add_stream(fstream, work_buffer, nb_read); - MFCLOSE(fp); - RELEASE(fullname); - break; - case STRING_STREAM: - fstream = pdf_new_stream(STREAM_COMPRESS); - if (instring) - pdf_add_stream(fstream, instring, strlen(instring)); - break; - default: - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - pdf_release_obj(tmp); - - /* - * Optional dict. - * - * TODO: check Length, Filter... - */ - skip_white(&args->curptr, args->endptr); - - if (args->curptr[0] == '<') { - pdf_obj *stream_dict; - - stream_dict = pdf_stream_dict(fstream); - - tmp = parse_pdf_dict(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "Parsing dictionary failed."); - pdf_release_obj(fstream); - RELEASE(ident); - return -1; - } - if (pdf_lookup_dict(tmp, "Length")) { - pdf_remove_dict(tmp, "Length"); - } else if (pdf_lookup_dict(tmp, "Filter")) { - pdf_remove_dict(tmp, "Filter"); - } - pdf_merge_dict(stream_dict, tmp); - pdf_release_obj(tmp); - } - - /* Users should explicitly close this. */ - spc_push_object(ident, fstream); - RELEASE(ident); - - return 0; -} - -/* - * STREAM: Create a PDF stream object from an input string. - * - * pdf: stream @objname (input_string) [PDF_DICT] - */ -static int -spc_handler_pdfm_stream (struct spc_env *spe, struct spc_arg *args) -{ - return spc_handler_pdfm_stream_with_type (spe, args, STRING_STREAM); -} - -/* - * FSTREAM: Create a PDF stream object from an existing file. - * - * pdf: fstream @objname (filename) [PDF_DICT] - */ -static int -spc_handler_pdfm_fstream (struct spc_env *spe, struct spc_arg *args) -{ - return spc_handler_pdfm_stream_with_type (spe, args, FILE_STREAM); -} - -/* Grab page content as follows: - * - * Reference point = (x_user, y_user) - * - * Case 1. \special{pdf:bxobj @obj width WD height HT depth DP} - * - * Grab the box with the lower-left corner (x_user, y_user-DP) - * and the upper right corner (x_user+WD, y_user+HT). - * - * Case 2. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} - * - * Grab the box with the lower-left corner (x_user+LLX, y_user+LLY) - * and the upper right corner (x_user+URX, y_user+URY). - * - * Note that scale, xscale, yscale, xoffset, yoffset options are ignored. - */ -static int -spc_handler_pdfm_bform (struct spc_env *spe, struct spc_arg *args) -{ - int xobj_id; - char *ident; - pdf_rect cropbox; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "A form XObject must have name."); - return -1; - } - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(ident); - return -1; - } - - /* A XForm with zero dimension results in a non-invertible transformation - * matrix. And it may result in unpredictable behaviour. It might be an - * error in Acrobat. Bounding box with zero dimension may cause division - * by zero. - */ - if (ti.flags & INFO_HAS_USER_BBOX) { - if (ti.bbox.urx - ti.bbox.llx == 0.0 || - ti.bbox.ury - ti.bbox.lly == 0.0) { - spc_warn(spe, "Bounding box has a zero dimension."); - RELEASE(ident); - return -1; - } - cropbox.llx = ti.bbox.llx; - cropbox.lly = ti.bbox.lly; - cropbox.urx = ti.bbox.urx; - cropbox.ury = ti.bbox.ury; - } else { - if (ti.width == 0.0 || - ti.depth + ti.height == 0.0) { - spc_warn(spe, "Bounding box has a zero dimension."); - RELEASE(ident); - return -1; - } - cropbox.llx = 0.0; - cropbox.lly = -ti.depth; - cropbox.urx = ti.width; - cropbox.ury = ti.height; - } - - xobj_id = pdf_doc_begin_grabbing(ident, spe->x_user, spe->y_user, &cropbox); - - if (xobj_id < 0) { - RELEASE(ident); - spc_warn(spe, "Couldn't start form object."); - return -1; - } - - spc_push_object(ident, pdf_ximage_get_reference(xobj_id)); - RELEASE(ident); - - return 0; -} - -/* An extra dictionary after exobj must be merged to the form dictionary, - * not resource dictionary. - * Please use pdf:put @resources (before pdf:exobj) instead. - */ -static int -spc_handler_pdfm_eform (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *attrib = NULL; - - skip_white(&args->curptr, args->endptr); - - if (args->curptr < args->endptr) { - attrib = parse_pdf_dict(&args->curptr, args->endptr, NULL); - if (attrib && !PDF_OBJ_DICTTYPE(attrib)) { - pdf_release_obj(attrib); - attrib = NULL; - } - } - pdf_doc_end_grabbing(attrib); - - return 0; -} - -/* Saved XObjects can be used as follows: - * - * Reference point = (x_user, y_user) - * - * Case 1. \special{pdf:uxobj @obj width WD height HT depth DP} - * - * Scale the XObject to fit in the box - * [x_user, y_user-DP, x_user+WD, y_user+HT]. - * - * Case 2. \special{pdf:uxobj @obj xscale XS yscale YS} - * - * Scale the XObject with XS and YS. Note that width and xscale - * or height and yscale cannot be used together. - * - * Case 3. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} - * - * Scale the XObject to fit in the box - * [x_user+LLX, y_user+LLY, x_user+URX, y_user+URY]. - * - * Note that xoffset and yoffset moves the reference point where the - * lower-left corner of the XObject will be put. - */ -static int -spc_handler_pdfm_uxobj (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int xobj_id; - char *ident; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "No object identifier given."); - return -1; - } - - transform_info_clear(&ti); - if (args->curptr < args->endptr) { - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(ident); - return -1; - } - } - - /* Dvipdfmx was suddenly changed to use file name to identify - * external images. We can't use ident to find image resource - * here. - */ - xobj_id = findresource(sd, ident); - if (xobj_id < 0) { - xobj_id = pdf_ximage_findresource(ident, 0, NULL); - if (xobj_id < 0) { - spc_warn(spe, "Specified (image) object doesn't exist: %s", ident); - RELEASE(ident); - return -1; - } - } - - pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_link (struct spc_env *spe, struct spc_arg *args) -{ - return spc_resume_annot(spe); -} - -static int -spc_handler_pdfm_nolink (struct spc_env *spe, struct spc_arg *args) -{ - return spc_suspend_annot(spe); -} - - - -/* Handled at BOP */ -static int -spc_handler_pdfm_pagesize (struct spc_env *spe, struct spc_arg *args) -{ - args->curptr = args->endptr; - - return 0; -} - -/* Please remove this. - * This should be handled before processing pages! - */ -static int -spc_handler_pdfm_bgcolor (struct spc_env *spe, struct spc_arg *args) -{ - int error; - pdf_color colorspec; - - error = spc_util_read_pdfcolor(spe, &colorspec, args, NULL); - if (error) - spc_warn(spe, "No valid color specified?"); - else { - pdf_doc_set_bgcolor(&colorspec); - } - - return error; -} - -static int -spc_handler_pdfm_mapline (struct spc_env *spe, struct spc_arg *ap) -{ - fontmap_rec *mrec; - char *map_name, opchr; - int error = 0; - - skip_white(&ap->curptr, ap->endptr); - if (ap->curptr >= ap->endptr) { - spc_warn(spe, "Empty mapline special?"); - return -1; - } - - opchr = ap->curptr[0]; - if (opchr == '-' || opchr == '+') - ap->curptr++; - - skip_white(&ap->curptr, ap->endptr); - - switch (opchr) { - case '-': - map_name = parse_ident(&ap->curptr, ap->endptr); - if (map_name) { - pdf_remove_fontmap_record(map_name); - RELEASE(map_name); - } else { - spc_warn(spe, "Invalid fontmap line: Missing TFM name."); - error = -1; - } - break; - case '+': - mrec = NEW(1, fontmap_rec); - pdf_init_fontmap_record(mrec); - error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); - if (error) - spc_warn(spe, "Invalid fontmap line."); - else { - pdf_append_fontmap_record(mrec->map_name, mrec); - } - pdf_clear_fontmap_record(mrec); - RELEASE(mrec); - break; - default: - mrec = NEW(1, fontmap_rec); - pdf_init_fontmap_record(mrec); - error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); - if (error) - spc_warn(spe, "Invalid fontmap line."); - else { - pdf_insert_fontmap_record(mrec->map_name, mrec); - } - pdf_clear_fontmap_record(mrec); - RELEASE(mrec); - break; - } - if (!error) - ap->curptr = ap->endptr; - - return 0; -} - -static int -spc_handler_pdfm_mapfile (struct spc_env *spe, struct spc_arg *args) -{ - char *mapfile; - int mode, error = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr >= args->endptr) - return 0; - - switch (args->curptr[0]) { - case '-': - mode = FONTMAP_RMODE_REMOVE; - args->curptr++; - break; - case '+': - mode = FONTMAP_RMODE_APPEND; - args->curptr++; - break; - default: - mode = FONTMAP_RMODE_REPLACE; - break; - } - - mapfile = parse_val_ident(&args->curptr, args->endptr); - if (!mapfile) { - spc_warn(spe, "No fontmap file specified."); - return -1; - } else { - error = pdf_load_fontmap_file(mapfile, mode); - } - RELEASE(mapfile); - - return error; -} - - -#ifdef ENABLE_TOUNICODE -static int -spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - char *cmap_name; - - /* First clear */ - sd->cd.cmap_id = -1; - sd->cd.unescape_backslash = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr >= args->endptr) { - spc_warn(spe, "Missing CMap name for pdf:tounicode."); - return -1; - } - - /* _FIXME_ - * Any valid char allowed for PDF name object should be allowed here. - * The argument to this special should be a PDF name obejct. - * But it's too late to change this special. - */ - cmap_name = parse_ident(&args->curptr, args->endptr); - if (!cmap_name) { - spc_warn(spe, "Missing ToUnicode mapping name..."); - 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); - 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 (sd->cd.cmap_id >= 0) { - if (strstr(cmap_name, "RKSJ") || - strstr(cmap_name, "B5") || - strstr(cmap_name, "GBK") || - strstr(cmap_name, "KSC")) - sd->cd.unescape_backslash = 1; - } - RELEASE(cmap_name); - return 0; -} -#endif /* ENABLE_TOUNICODE */ - - -static struct spc_handler pdfm_handlers[] = { - {"annotation", spc_handler_pdfm_annot}, - {"annotate", spc_handler_pdfm_annot}, - {"annot", spc_handler_pdfm_annot}, - {"ann", spc_handler_pdfm_annot}, - - {"outline", spc_handler_pdfm_outline}, - {"out", spc_handler_pdfm_outline}, - - {"article", spc_handler_pdfm_article}, - {"art", spc_handler_pdfm_article}, - - {"bead", spc_handler_pdfm_bead}, - {"thread", spc_handler_pdfm_bead}, - - {"destination", spc_handler_pdfm_dest}, - {"dest", spc_handler_pdfm_dest}, - - - {"object", spc_handler_pdfm_object}, - {"obj", spc_handler_pdfm_object}, - - - {"docinfo", spc_handler_pdfm_docinfo}, - {"docview", spc_handler_pdfm_docview}, - - {"content", spc_handler_pdfm_content}, - {"put", spc_handler_pdfm_put}, - {"close", spc_handler_pdfm_close}, - {"bop", spc_handler_pdfm_bop}, - {"eop", spc_handler_pdfm_eop}, - - {"image", spc_handler_pdfm_image}, - {"img", spc_handler_pdfm_image}, - {"epdf", spc_handler_pdfm_image}, - - {"link", spc_handler_pdfm_link}, - {"nolink", spc_handler_pdfm_nolink}, - - {"begincolor", spc_handler_pdfm_bcolor}, - {"bcolor", spc_handler_pdfm_bcolor}, - {"bc", spc_handler_pdfm_bcolor}, - - {"setcolor", spc_handler_pdfm_scolor}, - {"scolor", spc_handler_pdfm_scolor}, - {"sc", spc_handler_pdfm_scolor}, - - {"endcolor", spc_handler_pdfm_ecolor}, - {"ecolor", spc_handler_pdfm_ecolor}, - {"ec", spc_handler_pdfm_ecolor}, - - {"begingray", spc_handler_pdfm_bcolor}, - {"bgray", spc_handler_pdfm_bcolor}, - {"bg", spc_handler_pdfm_bcolor}, - - {"endgray", spc_handler_pdfm_ecolor}, - {"egray", spc_handler_pdfm_ecolor}, - {"eg", spc_handler_pdfm_ecolor}, - - {"bgcolor", spc_handler_pdfm_bgcolor}, - {"bgc", spc_handler_pdfm_bgcolor}, - {"bbc", spc_handler_pdfm_bgcolor}, - {"bbg", spc_handler_pdfm_bgcolor}, - - {"pagesize", spc_handler_pdfm_pagesize}, - - {"bannot", spc_handler_pdfm_bann}, - {"beginann", spc_handler_pdfm_bann}, - {"bann", spc_handler_pdfm_bann}, - - {"eannot", spc_handler_pdfm_eann}, - {"endann", spc_handler_pdfm_eann}, - {"eann", spc_handler_pdfm_eann}, - - {"btrans", spc_handler_pdfm_btrans}, - {"begintransform", spc_handler_pdfm_btrans}, - {"begintrans", spc_handler_pdfm_btrans}, - {"bt", spc_handler_pdfm_btrans}, - - {"etrans", spc_handler_pdfm_etrans}, - {"endtransform", spc_handler_pdfm_etrans}, - {"endtrans", spc_handler_pdfm_etrans}, - {"et", spc_handler_pdfm_etrans}, - - {"bform", spc_handler_pdfm_bform}, - {"beginxobj", spc_handler_pdfm_bform}, - {"bxobj", spc_handler_pdfm_bform}, - - {"eform", spc_handler_pdfm_eform}, - {"endxobj", spc_handler_pdfm_eform}, - {"exobj", spc_handler_pdfm_eform}, - - {"usexobj", spc_handler_pdfm_uxobj}, - {"uxobj", spc_handler_pdfm_uxobj}, - -#ifdef ENABLE_TOUNICODE - {"tounicode", spc_handler_pdfm_tounicode}, -#endif /* ENABLE_TOUNICODE */ - {"literal", spc_handler_pdfm_literal}, - {"stream", spc_handler_pdfm_stream}, - {"fstream", spc_handler_pdfm_fstream}, - {"names", spc_handler_pdfm_names}, - {"mapline", spc_handler_pdfm_mapline}, - {"mapfile", spc_handler_pdfm_mapfile}, - - {"bcontent", spc_handler_pdfm_bcontent}, - {"econtent", spc_handler_pdfm_econtent}, - {"code", spc_handler_pdfm_code}, - - {"minorversion", spc_handler_pdfm_do_nothing}, - {"encrypt", spc_handler_pdfm_do_nothing}, -}; - -int -spc_pdfm_check_special (const char *buf, long len) -{ - int r = 0; - const char *p, *endptr; - - p = buf; - endptr = p + len; - - skip_white(&p, endptr); - if (p + strlen("pdf:") <= endptr && - !memcmp(p, "pdf:", strlen("pdf:"))) { - r = 1; - } - - return r; -} - -int -spc_pdfm_setup_handler (struct spc_handler *sph, - struct spc_env *spe, struct spc_arg *ap) -{ - int error = -1, i; - char *q; - - ASSERT(sph && spe && ap); - - skip_white(&ap->curptr, ap->endptr); - if (ap->curptr + strlen("pdf:") >= ap->endptr || - memcmp(ap->curptr, "pdf:", strlen("pdf:"))) { - spc_warn(spe, "Not pdf: special???"); - return -1; - } - ap->curptr += strlen("pdf:"); - - skip_white(&ap->curptr, ap->endptr); - q = parse_c_ident(&ap->curptr, ap->endptr); - if (q) { - for (i = 0; - i < sizeof(pdfm_handlers) / sizeof(struct spc_handler); i++) { - if (!strcmp(q, pdfm_handlers[i].key)) { - ap->command = pdfm_handlers[i].key; - sph->key = "pdf:"; - sph->exec = pdfm_handlers[i].exec; - skip_white(&ap->curptr, ap->endptr); - error = 0; - break; - } - } - RELEASE(q); - } - - return error; -} - diff --git a/Build/source/texk/dvipdfm-x/src/spc_tpic.c b/Build/source/texk/dvipdfm-x/src/spc_tpic.c deleted file mode 100644 index 6fdf50eb0ed..00000000000 --- a/Build/source/texk/dvipdfm-x/src/spc_tpic.c +++ /dev/null @@ -1,1136 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "numbers.h" -#include "dpxutil.h" - -#include "pdfdoc.h" - -#include "pdfdraw.h" -#include "pdfdev.h" - -#include "specials.h" -#include "spc_tpic.h" - -#define DEBUG 1 -#define ENABLE_SPC_NAMESPACE 1 - -/* - * Following "constant" converts milli-inches to - * device (in this case PDF stream) coordinates. - */ - -#define MI2DEV (0.072/pdf_dev_scale()) - -/* - * Value for 'sh' command 'g' is interpreted as - * - * gray color value 1-g for "solid" - * opacity value g for "opacity" - * shape value g for "shape" - */ -#define TPIC_MODE__FILL_SOLID 0 -#define TPIC_MODE__FILL_OPACITY 1 -#define TPIC_MODE__FILL_SHAPE 2 - -#ifndef ISBLANK -# define ISBLANK(c) ( (c) == ' ' || (c) == '\t' ) -#endif - -static void -skip_blank (const char **pp, const char *endptr) -{ - const char *p = *pp; - for ( ; p < endptr && ISBLANK(*p); p++); - *pp = p; -} - -struct spc_tpic_ -{ - struct { - int fill; - } mode; - - /* state */ - double pen_size; - int fill_shape; /* boolean */ - double fill_color; - - pdf_coord *points; - int num_points; - int max_points; -}; - -#if 1 -static struct spc_tpic_ _tpic_state; -#endif - -/* We use pdf_doc_add_page_content() here - * since we always draw isolated graphics. - */ -static void -tpic__clear (struct spc_tpic_ *tp) -{ - if (tp->points) { - RELEASE(tp->points); - tp->points = NULL; - } - tp->num_points = 0; - tp->max_points = 0; - tp->fill_shape = 0; - tp->fill_color = 0.0; -} - - -static pdf_obj * -create_xgstate (double a /* alpha */, int f_ais /* alpha is shape */) -{ - pdf_obj *dict; - - dict = pdf_new_dict(); - pdf_add_dict(dict, - pdf_new_name("Type"), - pdf_new_name("ExtGState")); - if (f_ais) { - pdf_add_dict(dict, - pdf_new_name("AIS"), - pdf_new_boolean(1)); - } - pdf_add_dict(dict, - pdf_new_name("ca"), - pdf_new_number(a)); - - return dict; -} - -static int -check_resourcestatus (const char *category, const char *resname) -{ - pdf_obj *dict1, *dict2; - - dict1 = pdf_doc_current_page_resources(); - if (!dict1) - return 0; - - dict2 = pdf_lookup_dict(dict1, category); - if (dict2 && - pdf_obj_typeof(dict2) == PDF_DICT) { - if (pdf_lookup_dict(dict2, resname)) - return 1; - } - return 0; -} - -static int -set_linestyle (double pn, double da) -{ - double dp[2]; /* dash pattern */ - - pdf_dev_setlinejoin(1); - pdf_dev_setmiterlimit(1.4); - pdf_dev_setlinewidth(pn); - if (da > 0.0) { - dp[0] = da * 72.0; - pdf_dev_setdash(1, dp, 0); - pdf_dev_setlinecap(0); - } else if (da < 0.0) { - dp[0] = pn; - dp[1] = -da * 72.0; - pdf_dev_setdash(2, dp, 0); - pdf_dev_setlinecap(1); - } else { - pdf_dev_setlinecap(0); - } - - return 0; -} - -static int -set_fillstyle (double g, double a, int f_ais) -{ - pdf_obj *dict; - char resname[32]; - char buf[32]; - int alp, len = 0; - - if (a > 0.0) { - alp = round(100.0 * a); - sprintf(resname, "_Tps_a%03d_", alp); - if (!check_resourcestatus("ExtGState", resname)) { - dict = create_xgstate(ROUND(0.01 * alp, 0.01), f_ais); - pdf_doc_add_page_resource("ExtGState", - resname, pdf_ref_obj(dict)); - pdf_release_obj(dict); - } - len += sprintf(buf + len, " /%s gs", resname); - - pdf_doc_add_page_content(buf, len); /* op: gs */ - } - - { - pdf_color *sc, *fc, new_fc; - - pdf_color_get_current (&sc, &fc); /* get stroking and fill colors */ - pdf_color_brighten_color(&new_fc, fc, g); - pdf_dev_set_nonstrokingcolor(&new_fc); - } - - return 0; -} - -static void -set_styles (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_fs, - int f_vp, - double pn, - double da) { - pdf_tmatrix M; - - pdf_setmatrix (&M, 1.0, 0.0, 0.0, -1.0, c->x, c->y); - pdf_dev_concat(&M); - - if (f_vp) - set_linestyle(pn, da); - - if (f_fs) { - double g, a; - int f_ais; - -#ifdef XETEX - switch (tp->mode.fill) { - case TPIC_MODE__FILL_SOLID: - g = 1.0 - tp->fill_color; - a = 0.0; - break; - case TPIC_MODE__FILL_SHAPE: - case TPIC_MODE__FILL_OPACITY: - if (tp->fill_color > 0.0) { - a = tp->fill_color; - g = 0.0; - } else { - a = 0.0; - g = 1.0; - } - break; - default: - g = 0.5; - a = 0.0; - } -#else - if (tp->mode.fill == TPIC_MODE__FILL_SOLID || !tp->fill_color) { - g = 1.0 - tp->fill_color; - a = 0.0; - } else { - g = 0.0; - a = tp->fill_color; - } -#endif - - f_ais = (tp->mode.fill == TPIC_MODE__FILL_SHAPE) ? 1 : 0; - - set_fillstyle(g, a, f_ais); - } -} - -static void -showpath (int f_vp, int f_fs) /* visible_path, fill_shape */ -{ - if (f_vp) { - if (f_fs) - pdf_dev_flushpath('b', PDF_FILL_RULE_NONZERO); - else { - pdf_dev_flushpath('S', PDF_FILL_RULE_NONZERO); - } - } else { - /* - * Acrobat claims 'Q' as illegal operation when there are unfinished - * path (a path without path-painting operator applied)? - */ - if (f_fs) - pdf_dev_flushpath('f', PDF_FILL_RULE_NONZERO); - else { - pdf_dev_newpath(); - } - } -} - -#define CLOSED_PATH(s) (\ - (s)->points[0].x == (s)->points[(s)->num_points-1].x && \ - (s)->points[0].y == (s)->points[(s)->num_points-1].y \ -) - -static int -tpic__polyline (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da) -{ - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - int i, error = 0; - - /* Shading is applied only to closed path. */ - f_fs = CLOSED_PATH(tp) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_moveto(tp->points[0].x, tp->points[0].y); - for (i = 0; i < tp->num_points; i++) - pdf_dev_lineto(tp->points[i].x, tp->points[i].y); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - - tpic__clear(tp); - - return error; -} - -/* - * Accroding to - * "Tpic: Pic for TEX", Tim Morgan, Original by Brian Kernighan, p.20: - * - * A spline is a smooth curve guided by a set of straight lines just - * like the line above. It begins at the same place, ends at the same - * place, and in between is tangent to the mid-point of each guiding - * line. The syntax for a spline is identical to a (path) line except - * for using spline instead of line. - * - * Spline is not a curve drawn by spline-fitting points p0, p1, ..., pn, - * defined by tpic special "pa" command. Instead, a path defined by set - * of points p0, p1, ... is guiding line mentioned above. - * - * Dvipsk draws them as a straight line from p0 to q1 = (p0 + p1)/2, - * followed by a quadratic B-spline curve with starting point q1, (off- - * curve) control point p1, end point q2 = (p1 + p2)/2, ..., and a - * straight line from qn to pn. - */ - -static int -tpic__spline (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da) -{ - double v[6]; - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - int i, error = 0; - - f_fs = CLOSED_PATH(tp) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_moveto(tp->points[0].x, tp->points[0].y); - - v[0] = 0.5 * (tp->points[0].x + tp->points[1].x); - v[1] = 0.5 * (tp->points[0].y + tp->points[1].y); - pdf_dev_lineto(v[0], v[1]); - for (i = 1; i < tp->num_points - 1; i++) { - /* B-spline control points */ - v[0] = 0.5 * (tp->points[i-1].x + tp->points[i].x); - v[1] = 0.5 * (tp->points[i-1].y + tp->points[i].y); - v[2] = tp->points[i].x; - v[3] = tp->points[i].y; - v[4] = 0.5 * (tp->points[i].x + tp->points[i+1].x); - v[5] = 0.5 * (tp->points[i].y + tp->points[i+1].y); - pdf_dev_bspline(v[0], v[1], v[2], v[3], v[4], v[5]); - } - pdf_dev_lineto(tp->points[i].x, tp->points[i].y); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - tpic__clear(tp); - - return error; -} - -static int -tpic__arc (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da, - double *v /* 6 numbers */ ) -{ - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - - f_fs = (round(fabs(v[4] - v[5]) + 0.5) >= 360) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_arcx(v[0], v[1], v[2], v[3], v[4], v[5], +1, 0.0); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - tpic__clear(tp); - - return 0; -} - -#if 1 -static int -spc_currentpoint (struct spc_env *spe, long *pg, pdf_coord *cp) -{ - *pg = 0; - cp->x = spe->x_user; - cp->y = spe->y_user; - return 0; -} -#endif - -static int -spc_handler_tpic_pn (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid pen size specified?"); - return -1; - } - tp->pen_size = atof(q) * MI2DEV; - RELEASE(q); - - return 0; -} - -static int -spc_handler_tpic_pa (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - int i; - double v[2]; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 2 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Missing numbers for TPIC \"pa\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 2) { - spc_warn(spe, "Invalid arg for TPIC \"pa\" command."); - return -1; - } - - if (tp->num_points >= tp->max_points) { - tp->max_points += 256; - tp->points = RENEW(tp->points, tp->max_points, pdf_coord); - } - tp->points[tp->num_points].x = v[0] * MI2DEV; - tp->points[tp->num_points].y = v[1] * MI2DEV; - tp->num_points += 1; - - return 0; -} - -static int -spc_handler_tpic_fp (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, 0.0); -} - -static int -spc_handler_tpic_ip (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 0, 0.0); -} - -static int -spc_handler_tpic_da (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = atof(q); - RELEASE(q); - } - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_dt (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = -atof(q); - RELEASE(q); - } - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_sp (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = atof(q); - RELEASE(q); - } - if (tp->num_points <= 2) { - spc_warn(spe, "Too few points (< 3) for spline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__spline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_ar (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - double v[6]; - pdf_coord cp; - long pg; - char *q; - int i; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 6 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid args. in TPIC \"ar\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 6) { - spc_warn(spe, "Invalid arg for TPIC \"ar\" command."); - return -1; - } - - v[0] *= MI2DEV; v[1] *= MI2DEV; - v[2] *= MI2DEV; v[3] *= MI2DEV; - v[4] *= 180.0 / M_PI; - v[5] *= 180.0 / M_PI; - - spc_currentpoint(spe, &pg, &cp); - - return tpic__arc(tp, &cp, 1, 0.0, v); -} - -static int -spc_handler_tpic_ia (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - double v[6]; - pdf_coord cp; - long pg; - char *q; - int i; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 6 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid args. in TPIC \"ia\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 6) { - spc_warn(spe, "Invalid arg for TPIC \"ia\" command."); - return -1; - } - - v[0] *= MI2DEV; v[1] *= MI2DEV; - v[2] *= MI2DEV; v[3] *= MI2DEV; - v[4] *= 180.0 / M_PI; - v[5] *= 180.0 / M_PI; - - spc_currentpoint(spe, &pg, &cp); - - return tpic__arc(tp, &cp, 0, 0.0, v); -} - -static int -spc_handler_tpic_sh (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 0.5; - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - double g = atof(q); - RELEASE(q); - if (g >= 0.0 && g <= 1.0) - tp->fill_color = g; - else { - WARN("Invalid fill color specified: %g\n", g); - return -1; - } - } - - return 0; -} - -static int -spc_handler_tpic_wh (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 0.0; - - return 0; -} - -static int -spc_handler_tpic_bk (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 1.0; - - return 0; -} - -static int -spc_handler_tpic_tx (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - spc_warn(spe, "TPIC command \"tx\" not supported."); - - return -1; -} - - -static int -spc_handler_tpic__init (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - -#if 0 - tp->mode.fill = TPIC_MODE__FILL_SOLID; -#endif - tp->pen_size = 1.0; - tp->fill_shape = 0; - tp->fill_color = 0.0; - - tp->points = NULL; - tp->num_points = 0; - tp->max_points = 0; - - if (tp->mode.fill != TPIC_MODE__FILL_SOLID && pdf_get_version() < 4) { - spc_warn(spe, "Tpic shading support requires PDF version 1.4."); - tp->mode.fill = TPIC_MODE__FILL_SOLID; - } - - return 0; -} - -static int -spc_handler_tpic__bophook (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - tpic__clear(tp); - - return 0; -} - -static int -spc_handler_tpic__eophook (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - if (tp->num_points > 0) - spc_warn(spe, "Unflushed tpic path at end of the page."); - tpic__clear(tp); - - return 0; -} - -static int -spc_handler_tpic__clean (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - if (tp->num_points > 0) - spc_warn(spe, "Unflushed tpic path at end of the document."); - - tpic__clear(tp); -#if 0 - RELEASE(tp); -#endif - - return 0; -} - -void -tpic_set_fill_mode (int mode) -{ - struct spc_tpic_ *tp = &_tpic_state; - tp->mode.fill = mode; -} - - -int -spc_tpic_at_begin_page (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__bophook(NULL, NULL, tp); -} - -int -spc_tpic_at_end_page (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__eophook(NULL, NULL, tp); -} - - -int -spc_tpic_at_begin_document (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__init(NULL, NULL, tp); -} - -int -spc_tpic_at_end_document (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__clean(NULL, NULL, tp); -} - - -#if DEBUG -#include "pdfparse.h" /* parse_val_ident :( */ - -static pdf_obj * -spc_parse_kvpairs (struct spc_env *spe, struct spc_arg *ap) -{ - pdf_obj *dict; - char *kp, *vp; - int error = 0; - - dict = pdf_new_dict(); - - skip_blank(&ap->curptr, ap->endptr); - while (!error && ap->curptr < ap->endptr) { - kp = parse_val_ident(&ap->curptr, ap->endptr); - if (!kp) - break; - skip_blank(&ap->curptr, ap->endptr); - if (ap->curptr < ap->endptr && - ap->curptr[0] == '=') { - ap->curptr++; - skip_blank(&ap->curptr, ap->endptr); - if (ap->curptr == ap->endptr) { - RELEASE(kp); - error = -1; - break; - } - vp = parse_c_string(&ap->curptr, ap->endptr); - if (!vp) - error = -1; - else { - pdf_add_dict(dict, - pdf_new_name(kp), - pdf_new_string(vp, strlen(vp) + 1)); /* NULL terminate */ - RELEASE(vp); - } - } else { - /* Treated as 'flag' */ - pdf_add_dict(dict, - pdf_new_name(kp), - pdf_new_boolean(1)); - } - RELEASE(kp); - if (!error) - skip_blank(&ap->curptr, ap->endptr); - } - - if (error) { - pdf_release_obj(dict); - dict = NULL; - } - - return dict; -} - -static int -tpic_filter_getopts (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - struct spc_tpic_ *tp = dp; - char *k, *v; - int error = 0; - - ASSERT( kp && vp && tp ); - - k = pdf_name_value(kp); - if (!strcmp(k, "fill-mode")) { - if (pdf_obj_typeof(vp) != PDF_STRING) { - WARN("Invalid value for TPIC option fill-mode..."); - error = -1; - } else { - v = pdf_string_value(vp); - if (!strcmp(v, "shape")) - tp->mode.fill = TPIC_MODE__FILL_SHAPE; - else if (!strcmp(v, "opacity")) - tp->mode.fill = TPIC_MODE__FILL_OPACITY; - else if (!strcmp(v, "solid")) - tp->mode.fill = TPIC_MODE__FILL_SOLID; - else { - WARN("Invalid value for TPIC option fill-mode: %s", v); - error = -1; - } - } - } else { - WARN("Unrecognized option for TPIC special handler: %s", k); - error = -1; - } - - return error; -} - -static int -spc_handler_tpic__setopts (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_obj *dict; - int error = 0; - - dict = spc_parse_kvpairs(spe, ap); - if (!dict) - return -1; - error = pdf_foreach_dict(dict, tpic_filter_getopts, tp); - if (!error) { - if (tp->mode.fill != TPIC_MODE__FILL_SOLID && - pdf_get_version() < 4) { - spc_warn(spe, "Transparent fill mode requires PDF version 1.4."); - tp->mode.fill = TPIC_MODE__FILL_SOLID; - } - } - - return error; -} -#endif /* DEBUG */ - - -static struct spc_handler tpic_handlers[] = { - {"pn", spc_handler_tpic_pn}, - {"pa", spc_handler_tpic_pa}, - {"fp", spc_handler_tpic_fp}, - {"ip", spc_handler_tpic_ip}, - {"da", spc_handler_tpic_da}, - {"dt", spc_handler_tpic_dt}, - {"sp", spc_handler_tpic_sp}, - {"ar", spc_handler_tpic_ar}, - {"ia", spc_handler_tpic_ia}, - {"sh", spc_handler_tpic_sh}, - {"wh", spc_handler_tpic_wh}, - {"bk", spc_handler_tpic_bk}, - {"tx", spc_handler_tpic_tx} -}; - -int -spc_tpic_check_special (const char *buf, long len) -{ - int istpic = 0; - char *q; - const char *p, *endptr; - int i, hasnsp = 0; - - p = buf; - endptr = p + len; - - skip_blank(&p, endptr); -#if ENABLE_SPC_NAMESPACE - if (p + strlen("tpic:") < endptr && - !memcmp(p, "tpic:", strlen("tpic:"))) - { - p += strlen("tpic:"); - hasnsp = 1; - } -#endif - q = parse_c_ident(&p, endptr); - - if (!q) - istpic = 0; - else if (q && hasnsp && !strcmp(q, "__setopt__")) { -#if DEBUG - istpic = 1; -#endif - RELEASE(q); - } else { - for (i = 0; - i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { - if (!strcmp(q, tpic_handlers[i].key)) { - istpic = 1; - break; - } - } - RELEASE(q); - } - - return istpic; -} - - -int -spc_tpic_setup_handler (struct spc_handler *sph, - struct spc_env *spe, struct spc_arg *ap) -{ - char *q; - int i, hasnsp = 0, error = -1; - - ASSERT(sph && spe && ap); - - skip_blank(&ap->curptr, ap->endptr); -#if ENABLE_SPC_NAMESPACE - if (ap->curptr + strlen("tpic:") < ap->endptr && - !memcmp(ap->curptr, "tpic:", strlen("tpic:"))) - { - ap->curptr += strlen("tpic:"); - hasnsp = 1; - } -#endif - q = parse_c_ident(&ap->curptr, ap->endptr); - - if (!q) - error = -1; - else if (q && hasnsp && !strcmp(q, "__setopt__")) { -#if DEBUG - ap->command = "__setopt__"; - sph->key = "tpic:"; - sph->exec = spc_handler_tpic__setopts; - skip_blank(&ap->curptr, ap->endptr); - error = 0; -#endif - RELEASE(q); - } else { - for (i = 0; - i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { - if (!strcmp(q, tpic_handlers[i].key)) { - ap->command = tpic_handlers[i].key; - sph->key = "tpic:"; - sph->exec = tpic_handlers[i].exec; - skip_blank(&ap->curptr, ap->endptr); - error = 0; - break; - } - } - RELEASE(q); - } - - return error; -} - - -#if 0 -int -spc_load_tpic_special (struct spc_env *spe, pdf_obj *lopts) -{ - struct spc_def *spd; - struct spc_tpic_ *sd; - - sd = NEW(1, struct spc_tpic_); - - spd = NEW(1, struct spc_def); - spc_init_def(spd); - - spc_def_init (spd, &spc_handler_tpic__init); - spc_def_setopts(spd, &spc_handler_tpic__setopts); - spc_def_bophook(spd, &spc_handler_tpic__bophook); - spc_def_eophook(spd, &spc_handler_tpic__eophook); - spc_def_clean (spd, &spc_handler_tpic__clean); - - spc_def_func(spd, "pn", &spc_handler_tpic_pn); - spc_def_func(spd, "pa", &spc_handler_tpic_pa); - spc_def_func(spd, "fp", &spc_handler_tpic_fp); - spc_def_func(spd, "ip", &spc_handler_tpic_ip); - spc_def_func(spd, "da", &spc_handler_tpic_da); - spc_def_func(spd, "dt", &spc_handler_tpic_dt); - spc_def_func(spd, "sp", &spc_handler_tpic_sp); - spc_def_func(spd, "ar", &spc_handler_tpic_ar); - spc_def_func(spd, "ia", &spc_handler_tpic_ia); - spc_def_func(spd, "sh", &spc_handler_tpic_sh); - spc_def_func(spd, "wh", &spc_handler_tpic_wh); - spc_def_func(spd, "bk", &spc_handler_tpic_bk); - spc_def_func(spd, "tx", &spc_handler_tpic_tx); - - spc_add_special(spe, "tpic", spd, sd); - - return 0; -} -#endif /* 0 */ - diff --git a/Build/source/texk/dvipdfm-x/src/tt_cmap.c b/Build/source/texk/dvipdfm-x/src/tt_cmap.c deleted file mode 100644 index da68af19787..00000000000 --- a/Build/source/texk/dvipdfm-x/src/tt_cmap.c +++ /dev/null @@ -1,1938 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - 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. -*/ - -/* - * A large part of codes are brought from ttfdump-0.5.5. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "sfnt.h" - - -/* Sorry for placing this here. - * We need to rewrite TrueType font support code... - */ -#include "cmap.h" -#include "cmap_write.h" - -#include "tt_aux.h" -#include "tt_gsub.h" - -#include "unicode.h" -#include "agl.h" -#include "pdfparse.h" -#include "pdfresource.h" -#include "otl_conf.h" - -#include "dpxfile.h" - -/* Hash */ -#include "dpxutil.h" - -#include "tt_cmap.h" - -#define VERBOSE_LEVEL_MIN 0 -static int verbose = 0; -void -otf_cmap_set_verbose (void) -{ - otl_gsub_set_verbose(); - verbose++; -} - -/* format 0: byte encoding table */ -struct cmap0 -{ - BYTE glyphIndexArray[256]; -}; - -static struct cmap0 * -read_cmap0 (sfnt *sfont, ULONG len) -{ - struct cmap0 *map; - int i; - - if (len < 256) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap0); - - for (i = 0; i < 256; i++) - map->glyphIndexArray[i] = sfnt_get_byte(sfont); - - return map; -} - -static void -release_cmap0(struct cmap0 *map) -{ - if (map) - RELEASE(map); -} - -static USHORT -lookup_cmap0 (struct cmap0 *map, USHORT cc) -{ - return ((cc > 255) ? 0 : map->glyphIndexArray[cc]); -} - -/* format 2: high-byte mapping through table */ -struct SubHeader -{ - USHORT firstCode; - USHORT entryCount; - SHORT idDelta; - USHORT idRangeOffset; -}; - -struct cmap2 -{ - USHORT subHeaderKeys[256]; - struct SubHeader *subHeaders; - USHORT *glyphIndexArray; -}; - -static struct cmap2 * -read_cmap2 (sfnt *sfont, ULONG len) -{ - struct cmap2 *map; - USHORT i, n; - - if (len < 512) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap2); - - for (i = 0; i < 256; i++) - map->subHeaderKeys[i] = sfnt_get_ushort(sfont); - - for (n = 0, i = 0; i < 256; i++) { - map->subHeaderKeys[i] /= 8; - if (n < map->subHeaderKeys[i]) - n = map->subHeaderKeys[i]; - } - n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ - - map->subHeaders = NEW(n, struct SubHeader); - for (i = 0; i < n; i++) { - map->subHeaders[i].firstCode = sfnt_get_ushort(sfont); - map->subHeaders[i].entryCount = sfnt_get_ushort(sfont); - map->subHeaders[i].idDelta = sfnt_get_short(sfont); - map->subHeaders[i].idRangeOffset = sfnt_get_ushort(sfont); - - /* It makes things easier to let the offset starts from - * the beginning of glyphIndexArray. - */ - if (map->subHeaders[i].idRangeOffset != 0) - map->subHeaders[i].idRangeOffset -= (2 + (n - i - 1) * 8); - } - - /* Caculate the length of glyphIndexArray, this is ugly, - * there should be a better way to get this information. - */ - n = (USHORT) (len - 518 - n * 8) / 2; - - map->glyphIndexArray = NEW(n, USHORT); - for (i = 0; i < n; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - - return map; -} - -static void -release_cmap2 (struct cmap2 *map) -{ - if (map) { - if (map->subHeaders) - RELEASE(map->subHeaders); - if (map->glyphIndexArray) - RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap2 (struct cmap2 *map, USHORT cc) -{ - USHORT idx = 0; - SHORT idDelta; - USHORT firstCode, entryCount, idRangeOffset; - int hi, lo; - USHORT i; - - hi = (cc >> 8) & 0xff; - lo = cc & 0xff; - - /* select which subHeader to use */ - i = map->subHeaderKeys[hi]; - - firstCode = map->subHeaders[i].firstCode; - entryCount = map->subHeaders[i].entryCount; - idDelta = map->subHeaders[i].idDelta; - idRangeOffset = map->subHeaders[i].idRangeOffset / 2; - - if (lo >= firstCode && - lo < firstCode + entryCount) { - idRangeOffset += lo - firstCode; - idx = map->glyphIndexArray[idRangeOffset]; - if (idx != 0) - idx = (idx + idDelta) & 0xffff; - } - - return idx; -} - -/* - * format 4: segment mapping to delta values - * - Microsoft standard character to glyph index mapping table - */ -struct cmap4 -{ - USHORT segCountX2; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; - USHORT *endCount; - USHORT reservedPad; - USHORT *startCount; - USHORT *idDelta; - USHORT *idRangeOffset; - USHORT *glyphIndexArray; -}; - -static struct cmap4 * -read_cmap4(sfnt *sfont, ULONG len) -{ - struct cmap4 *map; - USHORT i, n, segCount; - - if (len < 8) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap4); - - map->segCountX2 = segCount = sfnt_get_ushort(sfont); - map->searchRange = sfnt_get_ushort(sfont); - map->entrySelector = sfnt_get_ushort(sfont); - map->rangeShift = sfnt_get_ushort(sfont); - - segCount /= 2; - - map->endCount = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->endCount[i] = sfnt_get_ushort(sfont); - - map->reservedPad = sfnt_get_ushort(sfont); - - map->startCount = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->startCount[i] = sfnt_get_ushort(sfont); - - map->idDelta = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->idDelta[i] = sfnt_get_ushort(sfont); - - map->idRangeOffset = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->idRangeOffset[i] = sfnt_get_ushort(sfont); - - n = (len - 16 - 8 * segCount) / 2; - if (n == 0) - map->glyphIndexArray = NULL; - else { - map->glyphIndexArray = NEW(n, USHORT); - for (i = 0; i < n; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - } - - return map; -} - -static void -release_cmap4 (struct cmap4 *map) -{ - if (map) { - if (map->endCount) RELEASE(map->endCount); - if (map->startCount) RELEASE(map->startCount); - if (map->idDelta) RELEASE(map->idDelta); - if (map->idRangeOffset) RELEASE(map->idRangeOffset); - if (map->glyphIndexArray) RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap4 (struct cmap4 *map, USHORT cc) -{ - USHORT gid = 0; - USHORT i, j, segCount; - - /* - * Segments are sorted in order of increasing endCode values. - * Last segment maps 0xffff to gid 0 (?) - */ - i = segCount = map->segCountX2 / 2; - while (i-- > 0 && cc <= map->endCount[i]) { - if (cc >= map->startCount[i]) { - if (map->idRangeOffset[i] == 0) { - gid = (cc + map->idDelta[i]) & 0xffff; - } else { - j = map->idRangeOffset[i] - (segCount - i) * 2; - j = (cc - map->startCount[i]) + (j / 2); - gid = map->glyphIndexArray[j]; - if (gid != 0) - gid = (gid + map->idDelta[i]) & 0xffff; - } - break; - } - } - - return gid; -} - -/* format 6: trimmed table mapping */ -struct cmap6 -{ - USHORT firstCode; - USHORT entryCount; - USHORT *glyphIndexArray; -}; - -static struct cmap6 * -read_cmap6 (sfnt *sfont, ULONG len) -{ - struct cmap6 *map; - USHORT i; - - if (len < 4) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap6); - map->firstCode = sfnt_get_ushort(sfont); - map->entryCount = sfnt_get_ushort(sfont); - map->glyphIndexArray = NEW(map->entryCount, USHORT); - - for (i = 0; i < map->entryCount; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - - return map; -} - -static void -release_cmap6 (struct cmap6 *map) -{ - if (map) { - if (map->glyphIndexArray) - RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap6 (struct cmap6 *map, USHORT cc) -{ - USHORT idx; - - idx = cc - map->firstCode; - if (idx < map->entryCount) - return map->glyphIndexArray[idx]; - else - return 0; - - return 0; -} - -/* Format 8 and 10 not supported... - * - * format 8: mixed 16-bit and 32-bit coverage - * format 10: trimmed array - */ - -/* - * format 12: segmented coverage - * - * startGlyphID is 32-bit long, however, GlyphID is still 16-bit long ! - */ - -struct charGroup -{ - ULONG startCharCode; - ULONG endCharCode; - ULONG startGlyphID; -}; - -struct cmap12 -{ - ULONG nGroups; - struct charGroup *groups; -}; - -/* ULONG length */ -static struct cmap12 * -read_cmap12 (sfnt *sfont, ULONG len) -{ - struct cmap12 *map; - ULONG i; - - if (len < 4) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap12); - map->nGroups = sfnt_get_ulong(sfont); - map->groups = NEW(map->nGroups, struct charGroup); - - for (i = 0; i < map->nGroups; i++) { - map->groups[i].startCharCode = sfnt_get_ulong(sfont); - map->groups[i].endCharCode = sfnt_get_ulong(sfont); - map->groups[i].startGlyphID = sfnt_get_ulong(sfont); - } - - return map; -} - -static void -release_cmap12 (struct cmap12 *map) -{ - if (map) { - if (map->groups) - RELEASE(map->groups); - RELEASE(map); - } -} - -static USHORT -lookup_cmap12 (struct cmap12 *map, ULONG cccc) -{ - USHORT gid = 0; - ULONG i; - - i = map->nGroups; - while (i-- >= 0 && - cccc <= map->groups[i].endCharCode) { - if (cccc >= map->groups[i].startCharCode) { - gid = (USHORT) ((cccc - - map->groups[i].startCharCode + - map->groups[i].startGlyphID) & 0xffff); - break; - } - } - - return gid; -} - -/* read cmap */ -tt_cmap * -tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) -{ - tt_cmap *cmap = NULL; - ULONG offset, length = 0; - USHORT p_id, e_id; - USHORT i, n_subtabs; - - ASSERT(sfont); - - offset = sfnt_locate_table(sfont, "cmap"); - (void) sfnt_get_ushort(sfont); - n_subtabs = sfnt_get_ushort(sfont); - - for (i = 0; i < n_subtabs; i++) { - p_id = sfnt_get_ushort(sfont); - e_id = sfnt_get_ushort(sfont); - if (p_id != platform || e_id != encoding) - sfnt_get_ulong(sfont); - else { - offset += sfnt_get_ulong(sfont); - break; - } - } - - if (i == n_subtabs) - return NULL; - - cmap = NEW(1, tt_cmap); - cmap->map = NULL; - cmap->platform = platform; - cmap->encoding = encoding; - - sfnt_seek_set(sfont, offset); - cmap->format = sfnt_get_ushort(sfont); - /* Length and version (language) is ULONG for - * format 8, 10, 12 ! - */ - if (cmap->format <= 6) { - length = sfnt_get_ushort(sfont); - cmap->language = sfnt_get_ushort(sfont); /* language (Mac) */ - } else { - if (sfnt_get_ushort(sfont) != 0) { /* reverved - 0 */ - WARN("Unrecognized cmap subtable format."); - tt_cmap_release(cmap); - return NULL; - } else { - length = sfnt_get_ulong(sfont); - cmap->language = sfnt_get_ulong(sfont); - } - } - - switch(cmap->format) { - case 0: - cmap->map = read_cmap0(sfont, length); - break; - case 2: - cmap->map = read_cmap2(sfont, length); - break; - case 4: - cmap->map = read_cmap4(sfont, length); - break; - case 6: - cmap->map = read_cmap6(sfont, length); - break; - case 12: - WARN("UCS-4 TrueType cmap table..."); - cmap->map = read_cmap12(sfont, length); - break; - default: - WARN("Unrecognized TrueType cmap format."); - tt_cmap_release(cmap); - return NULL; - } - - if (!cmap->map) { - tt_cmap_release(cmap); - cmap = NULL; - } - - return cmap; -} - -void -tt_cmap_release (tt_cmap *cmap) -{ - - if (cmap) { - if (cmap->map) { - switch(cmap->format) { - case 0: - release_cmap0(cmap->map); - break; - case 2: - release_cmap2(cmap->map); - break; - case 4: - release_cmap4(cmap->map); - break; - case 6: - release_cmap6(cmap->map); - break; - case 12: - release_cmap12(cmap->map); - break; - default: - ERROR("Unrecognized TrueType cmap format."); - } - } - RELEASE(cmap); - } - - return; -} - - -USHORT -tt_cmap_lookup (tt_cmap *cmap, long cc) -{ - USHORT gid = 0; - - ASSERT(cmap); - - if (cc > 0xffffL && cmap->format < 12) { - WARN("Four bytes charcode not supported in TrueType cmap format 0...6."); - return 0; - } - - switch (cmap->format) { - case 0: - gid = lookup_cmap0(cmap->map, (USHORT) cc); - break; - case 2: - gid = lookup_cmap2(cmap->map, (USHORT) cc); - break; - case 4: - gid = lookup_cmap4(cmap->map, (USHORT) cc); - break; - case 6: - gid = lookup_cmap6(cmap->map, (USHORT) cc); - break; - case 12: - gid = lookup_cmap12(cmap->map, (ULONG) cc); - break; - default: - ERROR("Unrecognized TrueType cmap subtable format"); - break; - } - - return gid; -} - -/* Sorry for placing this here. - * We need to rewrite TrueType font support code... - */ - -#define WBUF_SIZE 1024 -static unsigned char wbuf[WBUF_SIZE]; - -static unsigned char srange_min[2] = {0x00, 0x00}; -static unsigned char srange_max[2] = {0xff, 0xff}; -static unsigned char lrange_min[4] = {0x00, 0x00, 0x00, 0x00}; -static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff}; - -static void -load_cmap4 (struct cmap4 *map, - unsigned char *GIDToCIDMap, CMap *cmap) -{ - USHORT c0, c1, gid, cid; - USHORT j, d, segCount; - USHORT ch; - long i; - - segCount = map->segCountX2 / 2; - for (i = segCount - 1; i >= 0 ; i--) { - c0 = map->startCount[i]; - c1 = map->endCount[i]; - d = map->idRangeOffset[i] / 2 - (segCount - i); - for (j = 0; j <= c1 - c0; j++) { - ch = c0 + j; - if (map->idRangeOffset[i] == 0) { - gid = (ch + map->idDelta[i]) & 0xffff; - } else { - gid = (map->glyphIndexArray[j+d] + - map->idDelta[i]) & 0xffff; - } - if (gid != 0 && gid != 0xffff) { - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); - if (cid == 0) - WARN("GID %u does not have corresponding CID %u.", - gid, cid); - } else { - cid = gid; - } - wbuf[0] = 0; - wbuf[1] = 0; - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - CMap_add_cidchar(cmap, wbuf, 4, cid); - } - } - } - - return; -} - -static void -load_cmap12 (struct cmap12 *map, - unsigned char *GIDToCIDMap, CMap *cmap) -{ - ULONG i, ch; /* LONG ? */ - USHORT gid, cid; - - for (i = 0; i < map->nGroups; i++) { - for (ch = map->groups[i].startCharCode; - ch <= map->groups[i].endCharCode; - ch++) { - long d = ch - map->groups[i].startCharCode; - gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); - if (cid == 0) - WARN("GID %u does not have corresponding CID %u.", gid, cid); - } else { - cid = gid; - } - wbuf[0] = (ch >> 24) & 0xff; - wbuf[1] = (ch >> 16) & 0xff; - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - CMap_add_cidchar(cmap, wbuf, 4, cid); - } - } - - return; -} - -/* OpenType CIDFont: - * - * We don't use GID for them. OpenType cmap table is for - * charcode to GID mapping rather than to-CID mapping. - */ -#include "cid.h" - -#include "tt_table.h" -#include "cff_types.h" -#include "cff_dict.h" -#include "cff.h" - -static int -handle_CIDFont (sfnt *sfont, - unsigned char **GIDToCIDMap, CIDSysInfo *csi) -{ - cff_font *cffont; - long offset, i; - card16 num_glyphs, gid; - cff_charsets *charset; - unsigned char *map; - struct tt_maxp_table *maxp; - - ASSERT(csi); - - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) { - csi->registry = NULL; - csi->ordering = NULL; - *GIDToCIDMap = NULL; - return 0; - } - - maxp = tt_read_maxp_table(sfont); - num_glyphs = (card16) maxp->numGlyphs; - RELEASE(maxp); - if (num_glyphs < 1) - ERROR("No glyph contained in this font..."); - - cffont = cff_open(sfont->stream, offset, 0); - if (!cffont) - ERROR("Could not open CFF font..."); - - - if (!(cffont->flag & FONTTYPE_CIDFONT)) { - cff_close(cffont); - csi->registry = NULL; - csi->ordering = NULL; - *GIDToCIDMap = NULL; - return 0; - } - - if (!cff_dict_known(cffont->topdict, "ROS")) { - ERROR("No CIDSystemInfo???"); - } else { - card16 reg, ord; - - reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0); - ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1); - - csi->registry = cff_get_string(cffont, reg); - csi->ordering = cff_get_string(cffont, ord); - csi->supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2); - } - - cff_read_charsets(cffont); - charset = cffont->charsets; - if (!charset) { - ERROR("No CFF charset data???"); - } - - map = NEW(num_glyphs * 2, unsigned char); - memset(map, 0, num_glyphs * 2); - switch (charset->format) { - case 0: - { - s_SID *cids; /* CID... */ - - cids = charset->data.glyphs; - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - map[2*gid ] = (cids[i] >> 8) & 0xff; - map[2*gid+1] = cids[i] & 0xff; - gid++; - } - } - break; - case 1: - { - cff_range1 *ranges; - card16 cid, count; - - ranges = charset->data.range1; - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - cid = ranges[i].first; - count = ranges[i].n_left + 1; /* card8 */ - while (count-- > 0 && - gid <= num_glyphs) { - map[2*gid ] = (cid >> 8) & 0xff; - map[2*gid + 1] = cid & 0xff; - gid++; - } - } - } - break; - case 2: - { - cff_range2 *ranges; - card16 cid, count; - - ranges = charset->data.range2; - if (charset->num_entries == 1 && - ranges[0].first == 1) { - /* "Complete" CIDFont */ - RELEASE(map); map = NULL; - } else { - /* Not trivial mapping */ - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - cid = ranges[i].first; - count = ranges[i].n_left + 1; - while (count-- > 0 && - gid <= num_glyphs) { - map[gid] = (cid >> 8) & 0xff; - map[gid] = cid & 0xff; - gid++; - } - } - - } - } - break; - default: - RELEASE(map); map = NULL; - ERROR("Unknown CFF charset format...: %d", charset->format); - break; - } - cff_close(cffont); - - *GIDToCIDMap = map; - return 1; -} - -/* - * Substituted glyphs: - * - * Mapping information stored in cmap_add. - */ -#ifndef is_used_char2 -#define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8)))) -#endif - -static USHORT -handle_subst_glyphs (CMap *cmap, - CMap *cmap_add, const char *used_glyphs) -{ - USHORT count; - USHORT i, gid; - - for (count = 0, i = 0; i < 8192; i++) { - int j; - long len, inbytesleft, outbytesleft; - const unsigned char *inbuf; - unsigned char *outbuf; - - if (used_glyphs[i] == 0) - continue; - - for (j = 0; j < 8; j++) { - gid = 8 * i + j; - - if (!is_used_char2(used_glyphs, gid)) - continue; - - if (!cmap_add) { -#if XETEX - if (FT_HAS_GLYPH_NAMES(sfont->ft_face)) { - /* JK: try to look up Unicode values from the glyph name... */ -#define MAX_UNICODES 16 -#define MAX_NAME 256 - static char name[MAX_NAME] = "(none)"; - long unicodes[MAX_UNICODES]; - int unicode_count = -1; - FT_Error err = FT_Get_Glyph_Name(sfont->ft_face, gid, name, MAX_NAME); - if (!err) { - unicode_count = agl_get_unicodes(name, unicodes, MAX_UNICODES); - } -#undef MAX_UNICODES -#undef MAX_NAME - if (unicode_count == -1) { - MESG("No Unicode mapping available: GID=%u, name=%s\n", gid, name); - } else { - /* the Unicode characters go into wbuf[2] and following, in UTF16BE */ - /* we rely on WBUF_SIZE being more than adequate for MAX_UNICODES */ - unsigned char* p = wbuf + 2; - int k; - len = 0; - 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); - } - } -#else - WARN("No Unicode mapping available: GID=%u", gid); -#endif - } else { - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = gid & 0xff; - inbuf = wbuf; - inbytesleft = 2; - outbuf = wbuf + 2; - outbytesleft = WBUF_SIZE - 2; - CMap_decode(cmap_add, - &inbuf , &inbytesleft, - &outbuf, &outbytesleft); - if (inbytesleft != 0) { - WARN("CMap conversion failed..."); - } else { - len = WBUF_SIZE - 2 - outbytesleft; - CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len); - count++; - - if (verbose > VERBOSE_LEVEL_MIN) { - long _i; - - MESG("otf_cmap>> Additional ToUnicode mapping: <%04X> <", gid); - for (_i = 0; _i < len; _i++) { - MESG("%02X", wbuf[2 + _i]); - } - MESG(">\n"); - } - - } - } - - } - } - - return count; -} - -static pdf_obj * -create_ToUnicode_cmap4 (struct cmap4 *map, - const char *cmap_name, CMap *cmap_add, - const char *used_glyphs) -{ - pdf_obj *stream = NULL; - CMap *cmap; - USHORT c0, c1, gid, count, ch; - USHORT i, j, d, segCount; - char used_glyphs_copy[8192]; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - CMap_add_codespacerange(cmap, srange_min, srange_max, 2); - - memcpy(used_glyphs_copy, used_glyphs, 8192); - - segCount = map->segCountX2 / 2; - for (count = 0, i = 0; i < segCount; i++) { - c0 = map->startCount[i]; - c1 = map->endCount[i]; - d = map->idRangeOffset[i] / 2 - (segCount - i); - for (j = 0; j <= c1 - c0; j++) { - ch = c0 + j; - if (map->idRangeOffset[i] == 0) { - gid = (ch + map->idDelta[i]) & 0xffff; - } else { - gid = (map->glyphIndexArray[j+d] + - map->idDelta[i]) & 0xffff; - } - if (is_used_char2(used_glyphs_copy, gid)) { - count++; - - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = (gid & 0xff); - - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, 2); - - /* Avoid duplicate entry - * There are problem when two Unicode code is mapped to - * single glyph... - */ - used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); - count++; - } - } - } - - count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy); - - if (count < 1) - stream = NULL; - else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - - -static pdf_obj * -create_ToUnicode_cmap12 (struct cmap12 *map, - const char *cmap_name, CMap *cmap_add, - const char *used_glyphs) -{ - pdf_obj *stream = NULL; - CMap *cmap; - ULONG i, ch; - USHORT gid, count; - char used_glyphs_copy[8192]; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - CMap_add_codespacerange(cmap, srange_min, srange_max, 2); - - memcpy(used_glyphs_copy, used_glyphs, 8192); - for (count = 0, i = 0; i < map->nGroups; i++) { - for (ch = map->groups[i].startCharCode; - ch <= map->groups[i].endCharCode; ch++) { - unsigned char *p; - int len; - long d; - - p = wbuf + 2; - d = ch - map->groups[i].startCharCode; - gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); - if (is_used_char2(used_glyphs_copy, gid)) { - count++; - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = (gid & 0xff); - len = UC_sput_UTF16BE((long)ch, &p, wbuf+WBUF_SIZE); - - used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); - } - } - } - - count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy); - - if (count < 1) - stream = NULL; - else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - -#ifdef XETEX -typedef struct { - short platform; - short encoding; -} cmap_plat_enc_rec; - -static cmap_plat_enc_rec cmap_plat_encs[] = { - { 3, 10 }, - { 0, 3 }, - { 0, 0 }, - { 3, 1 }, - { 0, 1 } -}; -#endif - -pdf_obj * -otf_create_ToUnicode_stream (const char *font_name, - int ttc_index, /* 0 for non-TTC */ -#ifdef XETEX - FT_Face face, -#endif - const char *used_glyphs) -{ - pdf_obj *cmap_ref = NULL; - long res_id; - pdf_obj *cmap_obj = NULL; - CMap *cmap_add; - int cmap_add_id; - tt_cmap *ttcmap; - char *normalized_font_name; - char *cmap_name; - FILE *fp = NULL; - sfnt *sfont; - long offset = 0; - int i; - - /* replace slash in map name with dash to make the output cmap name valid, - * happens when XeTeX embeds full font path - * https://sourceforge.net/p/xetex/bugs/52/ - */ - normalized_font_name = NEW(strlen(font_name)+1, char); - strcpy(normalized_font_name, font_name); - for (i = 0; i < strlen(font_name); ++i) { - if (normalized_font_name[i] == '/') - normalized_font_name[i] = '-'; - } - - cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+5, char); - sprintf(cmap_name, "%s,%03d-UTF16", normalized_font_name, ttc_index); - - res_id = pdf_findresource("CMap", cmap_name); - if (res_id >= 0) { - RELEASE(cmap_name); - cmap_ref = pdf_get_resource_reference(res_id); - return cmap_ref; - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - MESG("otf_cmap>> Creating ToUnicode CMap for \"%s\"...\n", font_name); - } - -#ifdef XETEX - sfont = sfnt_open(face, -1); -#else - fp = DPXFOPEN(font_name, DPX_RES_TYPE_TTFONT); - if (!fp) { - fp = DPXFOPEN(font_name, DPX_RES_TYPE_OTFONT); - } - - if (!fp) { - RELEASE(cmap_name); - return NULL; - } - - sfont = sfnt_open(fp); -#endif - - if (!sfont) { - ERROR("Could not open TrueType font file \"%s\"", font_name); - } - - switch (sfont->type) { - case SFNT_TYPE_TTC: - offset = ttc_read_offset(sfont, ttc_index); - if (offset == 0) { - ERROR("Invalid TTC index"); - } - break; - default: - offset = 0; - break; - } - - if (sfnt_read_table_directory(sfont, offset) < 0) { - ERROR("Could not read TrueType table directory."); - } - - cmap_add_id = CMap_cache_find(cmap_name); - if (cmap_add_id < 0) { - cmap_add = NULL; - } else { - cmap_add = CMap_cache_get(cmap_add_id); - } - - CMap_set_silent(1); /* many warnings without this... */ - ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */ - if (ttcmap && - ttcmap->format == 12) { - WARN("Format 12 cmap table ... untested"); - cmap_obj = create_ToUnicode_cmap12(ttcmap->map, - cmap_name, cmap_add, used_glyphs); - } else { - ttcmap = tt_cmap_read(sfont, 3, 1); /* Microsoft UCS2 */ - if (ttcmap && - ttcmap->format == 4) { - cmap_obj = create_ToUnicode_cmap4(ttcmap->map, - cmap_name, cmap_add, used_glyphs); - } else { - ttcmap = tt_cmap_read(sfont, 0, 3); /* Unicode 2.0 or later */ - if (ttcmap && - ttcmap->format == 4) { - cmap_obj = create_ToUnicode_cmap4(ttcmap->map, - cmap_name, cmap_add, used_glyphs); - } else { - ERROR("Unable to read OpenType/TrueType Unicode cmap table."); - } - } - } - tt_cmap_release(ttcmap); - CMap_set_silent(0); - - if (cmap_obj) { - res_id = pdf_defineresource("CMap", cmap_name, - cmap_obj, PDF_RES_FLUSH_IMMEDIATE); - cmap_ref = pdf_get_resource_reference(res_id); - } else { - cmap_ref = NULL; - } - RELEASE(cmap_name); - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return cmap_ref; -} - -/* Must be smaller than (WBUF_SIZE-2)/8 */ -#define MAX_UNICODES 16 - -struct gent -{ - USHORT gid; - long ucv; /* assigned PUA unicode */ - - int num_unicodes; - long unicodes[MAX_UNICODES]; -}; - -static void -create_cmaps (CMap *cmap, CMap *tounicode, - struct ht_table *unencoded, unsigned char *GIDToCIDMap) -{ - struct ht_iter iter; - - ASSERT(cmap && unencoded); - - if (ht_set_iter(unencoded, &iter) < 0) - return; - - CMap_set_silent(1); /* many warnings without this... */ - - do { - struct gent *glyph; - unsigned char *ucv; - int i, len; - unsigned char *p, *endptr; - CID cid; - - glyph = (struct gent *) ht_iter_getval(&iter); - ucv = (unsigned char *) ht_iter_getkey(&iter, &len); - - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]); - if (cid == 0) - WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid); - } else { - cid = glyph->gid; - } - - CMap_add_cidchar(cmap, ucv, 4, cid); - - if (tounicode) { - wbuf[0] = (cid >> 8) & 0xff; - wbuf[1] = cid & 0xff; - p = wbuf + 2; - endptr = wbuf + WBUF_SIZE; - len = 0; - for (i = 0; i < glyph->num_unicodes; i++) { - len += UC_sput_UTF16BE(glyph->unicodes[i], &p, endptr); - } - CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len); - } - } while (ht_iter_next(&iter) >= 0); - - CMap_set_silent(0); - - ht_clear_iter(&iter); -} - -static void -add_glyph (struct ht_table *unencoded, - USHORT gid, long ucv, int num_unicodes, long *unicodes) -{ - struct gent *glyph; - int i; - - ASSERT(unencoded); - - if (gid == 0 || num_unicodes < 1) { - return; - } - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - glyph = NEW(1, struct gent); - glyph->gid = gid; - glyph->num_unicodes = num_unicodes; - for (i = 0; - i < num_unicodes && i < MAX_UNICODES; i++) { - glyph->unicodes[i] = unicodes[i]; - } - - ht_append_table(unencoded, wbuf, 4, glyph); -} - -/* This seriously affects speed... */ -static struct gent * -find_glyph (struct ht_table *unencoded, long ucv) -{ - ASSERT(unencoded); - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - return (struct gent *) ht_lookup_table(unencoded, wbuf, 4); -} - -static void -handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - pdf_obj *tmp; - long i, j, src_size, dst_size; - long src, dst; - long src_start, src_end, dst_start, dst_end; - - src_size = pdf_array_length(src_obj); - dst_size = pdf_array_length(dst_obj); - - dst_start = dst_end = -1; dst = 0; - src_start = src_end = -1; src = 0; - for (i = 0, j = 0; - i < src_size && j < dst_size; i++) { - USHORT gid; - int rv; - struct gent *glyph; - - tmp = pdf_get_array(src_obj, i); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - src_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); - src_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - src_start = src_end = (long) pdf_number_value(tmp); - } - for (src = src_start; src <= src_end; src++) { - glyph = find_glyph(unencoded, src); - if (glyph) - gid = glyph->gid; - else { - gid = tt_cmap_lookup(ttcmap, src); - } - dst++; - if (dst > dst_end) { - tmp = pdf_get_array(dst_obj, j++); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - dst_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); - dst_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - dst_start = dst_end = (long) pdf_number_value(tmp); - } - dst = dst_start; - } - if (gid == 0) { - if (flag == 'r' || flag == 'p') { - if (src < 0x10000) { - WARN("Font does not have glyph for U+%04X.", src); - } else { - WARN("Font does not have glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - rv = otl_gsub_apply(gsub_list, &gid); - if (rv < 0) { - if (flag == 'p' || flag == 'r') { - if (src < 0x10000) { - WARN("No substituted glyph for U+%04X.", src); - } else { - WARN("No substituted glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - - if (glyph) { - glyph->gid = gid; - } else { - add_glyph(unencoded, gid, dst, 1, &src); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - if (dst < 0x10000) { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n", - gid, dst); - } else { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n", - gid, dst); - } - } - - } - } - - if (dst < dst_end || src < src_end || - i < src_size || j < dst_size) { - WARN("Number of glyphs in left-side and right-side not equal..."); - WARN("Please check .otl file..."); - } -} - -static void -handle_assign (pdf_obj *dst, pdf_obj *src, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - long unicodes[MAX_UNICODES], ucv; - int i, n_unicodes, rv; - USHORT gid_in[MAX_UNICODES], lig; - - n_unicodes = pdf_array_length(src); /* FIXME */ - ucv = (long) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */ - if (!UC_is_valid(ucv)) { - if (flag == 'r' || flag == 'p') { - if (ucv < 0x10000) { - WARN("Invalid Unicode in: %04X", ucv); - } else { - WARN("Invalid Unicode in: %06X", ucv); - } - } - if (flag == 'r') { - ERROR("Invalid Unicode code specified.", ucv); - } - return; - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Ligature component:"); - } - - for (i = 0; i < n_unicodes; i++) { - unicodes[i] = - (long) pdf_number_value(pdf_get_array(src, i)); - gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (unicodes[i] < 0x10000) { - MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]); - } else { - MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]); - } - } - - if (gid_in[i] == 0) { - if (flag == 'r' || flag == 'p') { - if (unicodes[i] < 0x10000) { - WARN("Unicode char U+%04X not exist in font...", unicodes[i]); - } else { - WARN("Unicode char U+%06X not exist in font...", unicodes[i]); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - return; - } - - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - } - - rv = otl_gsub_apply_lig(gsub_list, - gid_in, (USHORT)n_unicodes, &lig); - if (rv < 0) { - if (flag == 'p') - WARN("No ligature found..."); - else if (flag == 'r') - ERROR("No ligature found..."); - return; - } - - add_glyph(unencoded, lig, ucv, n_unicodes, unicodes); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (ucv < 0x10000) { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv); - } else { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv); - } - } - - return; -} - -static int -load_base_CMap (const char *cmap_name, int wmode, - CIDSysInfo *csi, unsigned char *GIDToCIDMap, - tt_cmap *ttcmap) -{ - int cmap_id; - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id < 0) { - CMap *cmap; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); - - if (csi) { /* CID */ - CMap_set_CIDSysInfo(cmap, csi); - } else { - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - } - - if (ttcmap->format == 12) { - load_cmap12(ttcmap->map, GIDToCIDMap, cmap); - } else if (ttcmap->format == 4) { - load_cmap4(ttcmap->map, GIDToCIDMap, cmap); - } - - cmap_id = CMap_cache_add(cmap); - } - - return cmap_id; -} - -static void -load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont) -{ - pdf_obj *rule; - char *script, *language, *feature; - long i, size; - - rule = otl_conf_get_rule(conf); - if (!rule) - return; - - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - int flag; - long j, num_comms; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array(rule, i+1); - num_comms = pdf_array_length(commands); - - /* (assign|substitute) tag dst src */ - for (j = 0 ; j < num_comms; j += 4) { - tmp = pdf_get_array(commands, 1); - if (PDF_OBJ_STRINGTYPE(tmp)) { - feature = pdf_string_value(tmp); - if (otl_gsub_add_feat(gsub_list, - script, language, feature, sfont) < 0) { - if (flag == 'p') - WARN("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - else if (flag == 'r') - ERROR("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - } - } - - } - } - -} - -static void -handle_gsub (pdf_obj *conf, - tt_cmap *ttcmap, otl_gsub *gsub_list, - struct ht_table *unencoded) -{ - pdf_obj *rule; - char *script, *language, *feature; - long i, size; - - if (!conf) - return; - - rule = otl_conf_get_rule(conf); - if (!rule) { - return; - } - - if (!PDF_OBJ_ARRAYTYPE(rule)) { - WARN("Not arraytype?"); - return; - } - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - long j, num_comms; - int flag; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array (rule, i+1); - num_comms = pdf_array_length(commands); - - for (j = 0; j < num_comms; j += 4) { - pdf_obj *operator; - pdf_obj *src, *dst, *feat; - int rv; - - /* (assing|substitute) tag dst src */ - operator = pdf_get_array(commands, j); - - feat = pdf_get_array(commands, j+1); - if (PDF_OBJ_STRINGTYPE(feat)) - feature = pdf_string_value(feat); - else - feature = NULL; - - dst = pdf_get_array(commands, j+2); - src = pdf_get_array(commands, j+3); - - rv = otl_gsub_select(gsub_list, script, language, feature); - if (rv < 0) { - if (flag == 'p') { - WARN("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } else if (flag == 'r') { - ERROR("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } - } else { - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> %s:\n", pdf_name_value(operator)); - } - - if (!strcmp(pdf_name_value(operator), "assign")) { - handle_assign(dst, src, flag, - gsub_list, ttcmap, unencoded); - } else if (!strcmp(pdf_name_value(operator), "substitute")) { - handle_subst(dst, src, flag, - gsub_list, ttcmap, unencoded); - } - } - - } - - } - -} - -static void CDECL -hval_free (void *hval) -{ - RELEASE(hval); -} - -int -otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */ - const char *otl_tags, int wmode) -{ - int cmap_id = -1; - int tounicode_id = -1, is_cidfont = 0; - sfnt *sfont; - unsigned long offset = 0; - char *base_name = NULL, *cmap_name = NULL; - char *tounicode_name = NULL; - FILE *fp = NULL; - otl_gsub *gsub_list = NULL; - tt_cmap *ttcmap; - CMap *cmap, *base, *tounicode = NULL; - CIDSysInfo csi = {NULL, NULL, 0}; - unsigned char *GIDToCIDMap = NULL; - - if (!map_name) - return -1; - - if (ttc_index > 999 || ttc_index < 0) { - return -1; /* Sorry for this... */ - } - -#ifdef XETEX - fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); - sfont = NULL; /* FIXME */ -#else - fp = DPXFOPEN(map_name, DPX_RES_TYPE_TTFONT); - if (!fp) { - fp = DPXFOPEN(map_name, DPX_RES_TYPE_OTFONT); - } - if (!fp) { - fp = DPXFOPEN(map_name, DPX_RES_TYPE_DFONT); - if (!fp) return -1; - sfont = dfont_open(fp, ttc_index); - } else { - sfont = sfnt_open(fp); - } -#endif - - if (!sfont) { - ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name); - } - switch (sfont->type) { - case SFNT_TYPE_TTC: - offset = ttc_read_offset(sfont, ttc_index); - if (offset == 0) { - ERROR("Invalid TTC index"); - } - break; - case SFNT_TYPE_TRUETYPE: - case SFNT_TYPE_POSTSCRIPT: - offset = 0; - break; - case SFNT_TYPE_DFONT: - offset = sfont->offset; - break; - default: - ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name); - break; - } - - if (sfnt_read_table_directory(sfont, offset) < 0) - ERROR("Could not read OpenType/TrueType table directory."); - - base_name = NEW(strlen(map_name)+strlen("-UCS4-H")+5, char); - if (wmode) - sprintf(base_name, "%s,%03d-UCS4-V", map_name, ttc_index); - else { - sprintf(base_name, "%s,%03d-UCS4-H", map_name, ttc_index); - } - - if (otl_tags) { - cmap_name = NEW(strlen(map_name)+strlen(otl_tags)+strlen("-UCS4-H")+6, char); - if (wmode) - sprintf(cmap_name, "%s,%03d,%s-UCS4-V", map_name, ttc_index, otl_tags); - else - sprintf(cmap_name, "%s,%03d,%s-UCS4-H", map_name, ttc_index, otl_tags); - } else { - cmap_name = NEW(strlen(base_name)+1, char); - strcpy(cmap_name, base_name); - } - - if (sfont->type == SFNT_TYPE_POSTSCRIPT) { - is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi); - } else { - is_cidfont = 0; - } - - if (is_cidfont) { - tounicode_name = NULL; - } else { - tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char); - sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n", - map_name, (otl_tags ? otl_tags : "none")); - } - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id >= 0) { - RELEASE(cmap_name); - RELEASE(base_name); - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); - - sfnt_close(sfont); - DPXFCLOSE(fp); - - if (verbose > VERBOSE_LEVEL_MIN) - MESG("otf_cmap>> Found at cmap_id=%d.\n", cmap_id); - - return cmap_id; - } - - ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */ - if (!ttcmap) { - 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 OpenType/TrueType cmap table."); - - if (!otl_tags) { - RELEASE(cmap_name); - RELEASE(base_name); - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); - if (is_cidfont) { - if (csi.registry) - RELEASE(csi.registry); - if (csi.ordering) - RELEASE(csi.ordering); - } - tt_cmap_release(ttcmap); - sfnt_close(sfont); - DPXFCLOSE(fp); - - return cmap_id; - } - - base = CMap_cache_get(cmap_id); - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */ - CMap_set_usecmap(cmap, base); - CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */ - - if (is_cidfont) { - CMap_set_CIDSysInfo(cmap, &csi); - if (csi.registry) - RELEASE(csi.registry); - if (csi.ordering) - RELEASE(csi.ordering); - } else { - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - } - - gsub_list = otl_gsub_new(); - - { - struct ht_table unencoded; - char *conf_name, *opt_tag; - pdf_obj *conf, *opt_conf; - - conf_name = NEW(strlen(otl_tags)+1, char); - memset (conf_name, 0, strlen(otl_tags)+1); - opt_tag = strchr(otl_tags, ':'); - if (opt_tag) { - opt_tag++; - strncpy(conf_name, otl_tags, - strlen(otl_tags) - strlen(opt_tag) - 1); - } else { - strcpy(conf_name, otl_tags); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name); - } - - conf = otl_find_conf(conf_name); - if (!conf) - ERROR("Layout file \"%s\" not found...", conf_name); - - load_gsub(conf, gsub_list, sfont); - if (opt_tag) { - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag); - } - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - load_gsub(opt_conf, gsub_list, sfont); - } - - ht_init_table(&unencoded, hval_free); - - handle_gsub(conf, ttcmap, gsub_list, &unencoded); - if (opt_tag) { - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded); - } - if (is_cidfont) { - tounicode_id = -1; - tounicode = NULL; - } else { - tounicode_id = CMap_cache_find(tounicode_name); - if (tounicode_id >= 0) - tounicode = CMap_cache_get(tounicode_id); - else { - tounicode = CMap_new(); - CMap_set_name (tounicode, tounicode_name); - CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE); - CMap_set_wmode(tounicode, 0); - CMap_add_codespacerange(tounicode, srange_min, srange_max, 2); - CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE); - /* FIXME */ - CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2); - } - } - create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap); - - ht_clear_table(&unencoded); - RELEASE(conf_name); - } - - cmap_id = CMap_cache_add(cmap); - if (!is_cidfont && tounicode_id < 0) /* New */ - CMap_cache_add(tounicode); - - tt_cmap_release(ttcmap); - if (gsub_list) - otl_gsub_release(gsub_list); - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n", - base_name, cmap_name); - } - - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (base_name) - RELEASE(base_name); - if (cmap_name) - RELEASE(cmap_name); - if (tounicode_name) - RELEASE(tounicode_name); - - sfnt_close(sfont); - DPXFCLOSE(fp); - - return cmap_id; -} diff --git a/Build/source/texk/dvipdfm-x/src/type1c.c b/Build/source/texk/dvipdfm-x/src/type1c.c deleted file mode 100644 index 89c0866e287..00000000000 --- a/Build/source/texk/dvipdfm-x/src/type1c.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -/* - * CFF/OpenType Font support: - * - * Adobe Technical Note #5176, "The Compact Font Format Specfication" - * - * NOTE: - * - * Many CFF/OpenType does not have meaningful/correct CFF encoding. - * Encoding should be expilicitly supplied in the fontmap. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfobj.h" -#include "pdffont.h" - -#include "pdfencoding.h" -#include "unicode.h" - -/* Font info. from OpenType tables */ -#include "sfnt.h" -#include "tt_aux.h" - -#include "cff_types.h" -#include "cff_limits.h" -#include "cff.h" -#include "cff_dict.h" -#include "cs_type2.h" - -#include "type1c.h" - -#include "tfm.h" - -int -pdf_font_open_type1c (pdf_font *font) -{ - char *fontname; -#ifndef XETEX - char *ident; -#endif - FILE *fp = NULL; - sfnt *sfont; - cff_font *cffont; - pdf_obj *descriptor, *tmp; - unsigned long offset = 0; - int encoding_id, embedding; - - ASSERT(font); - -#ifndef XETEX - ident = -#endif - pdf_font_get_ident (font); - encoding_id = pdf_font_get_encoding(font); - -#ifdef XETEX - sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); -#endif - if (!sfont || - sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0) { - ERROR("Not a CFF/OpenType font?"); - } - - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset < 1) { - ERROR("No \"CFF \" table found. Not a CFF/OpenType font?"); - } - - cffont = cff_open(sfont->stream, offset, 0); - if (!cffont) { - ERROR("Could not read CFF font data"); - } - - if (cffont->flag & FONTTYPE_CIDFONT) { - cff_close (cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - return -1; - } - - fontname = cff_get_name(cffont); - if (!fontname) { - ERROR("No valid FontName found in CFF/OpenType font."); - } - pdf_font_set_fontname(font, fontname); - RELEASE(fontname); - - cff_close(cffont); - - /* - * Font like AdobePiStd does not have meaningful built-in encoding. - * Some software generate CFF/OpenType font with incorrect encoding. - */ - if (encoding_id < 0) { - WARN("Built-in encoding used for CFF/OpenType font."); - WARN("CFF font in OpenType font sometimes have strange built-in encoding."); - WARN("If you find text is not encoded properly in the generated PDF file,"); - WARN("please specify appropriate \".enc\" file in your fontmap."); - } - pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1C); - - embedding = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1; - descriptor = pdf_font_get_descriptor(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, 1, NULL); - if (!tmp) { - ERROR("Could not obtain neccesary font info from OpenType table."); - return -1; - } - pdf_merge_dict (descriptor, tmp); /* copy */ - pdf_release_obj(tmp); - if (!embedding) { /* tt_get_fontdesc may have changed this */ - pdf_font_set_flags(font, PDF_FONT_FLAG_NOEMBED); - } - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - -static void -add_SimpleMetrics (pdf_font *font, cff_font *cffont, - double *widths, card16 num_glyphs) -{ - pdf_obj *fontdict; - int code, firstchar, lastchar, tfm_id; - char *usedchars; - pdf_obj *tmp_array; - double scaling; - - fontdict = pdf_font_get_resource(font); - usedchars = pdf_font_get_usedchars(font); - - /* The widhts array in the font dictionary must be given relative - * to the default scaling of 1000:1, not relative to the scaling - * given by the font matrix. - */ - if (cff_dict_known(cffont->topdict, "FontMatrix")) - scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0); - else - scaling = 1; - - tmp_array = pdf_new_array(); - if (num_glyphs <= 1) { - /* This should be error. */ - firstchar = lastchar = 0; - pdf_add_array(tmp_array, pdf_new_number(0.0)); - } else { - firstchar = 255; lastchar = 0; - for (code = 0; code < 256; code++) { - if (usedchars[code]) { - if (code < firstchar) firstchar = code; - if (code > lastchar) lastchar = code; - } - } - if (firstchar > lastchar) { - ERROR("No glyphs used at all!"); - pdf_release_obj(tmp_array); - return; - } - tfm_id = tfm_open(pdf_font_get_mapname(font), 0); - for (code = firstchar; code <= lastchar; code++) { - if (usedchars[code]) { - double width; - if (tfm_id < 0) /* tfm is not found */ - width = scaling * widths[code]; - else - width = 1000. * tfm_get_width(tfm_id, code); - pdf_add_array(tmp_array, - pdf_new_number(ROUND(width, 0.1))); - } else { - pdf_add_array(tmp_array, pdf_new_number(0.0)); - } - } - } - - if (pdf_array_length(tmp_array) > 0) { - pdf_add_dict(fontdict, - pdf_new_name("Widths"), pdf_ref_obj(tmp_array)); - } - pdf_release_obj(tmp_array); - - pdf_add_dict(fontdict, - pdf_new_name("FirstChar"), pdf_new_number(firstchar)); - pdf_add_dict(fontdict, - pdf_new_name("LastChar"), pdf_new_number(lastchar)); - - return; -} - -int -pdf_font_load_type1c (pdf_font *font) -{ - pdf_obj *fontdict, *descriptor; - char *usedchars; - char *fontname, *uniqueTag, *ident, *fullname; - FILE *fp = NULL; - int encoding_id; - pdf_obj *fontfile, *stream_dict; - char **enc_vec; - sfnt *sfont; - cff_font *cffont; - cff_index *charstrings, *topdict, *cs_idx; - cff_charsets *charset = NULL; - cff_encoding *encoding = NULL; - long topdict_offset, private_size; - long charstring_len, max_len; - long size, offset = 0; - long stream_data_len = 0; - card8 *stream_data_ptr, *data; - card16 num_glyphs, cs_count, code; - cs_ginfo ginfo; - double nominal_width, default_width, notdef_width; - double widths[256]; - int verbose; - - ASSERT(font); - - verbose = pdf_font_get_verbose(); - - if (!pdf_font_is_in_use(font)) { - return 0; - } - - if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { - ERROR("Only embedded font supported for CFF/OpenType font."); - } - - usedchars = pdf_font_get_usedchars (font); - fontname = pdf_font_get_fontname (font); - ident = pdf_font_get_ident (font); - uniqueTag = pdf_font_get_uniqueTag (font); - if (!usedchars || - !fontname || !ident) { - ERROR("Unexpected error...."); - } - - fontdict = pdf_font_get_resource (font); - descriptor = pdf_font_get_descriptor(font); - encoding_id = pdf_font_get_encoding (font); - -#ifdef XETEX - sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); - if (!fp) { - ERROR("Could not open OpenType font: %s", ident); - } - - sfont = sfnt_open(fp); -#endif - if (!sfont) { - ERROR("Could not open OpenType font: %s", ident); - } - if (sfnt_read_table_directory(sfont, 0) < 0) { - ERROR("Could not read OpenType table directory: %s", ident); - } - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font ?"); - } - - cffont = cff_open(fp, offset, 0); - if (!cffont) { - ERROR("Could not open CFF font."); - } - if (cffont->flag & FONTTYPE_CIDFONT) { - ERROR("This is CIDFont..."); - } - - fullname = NEW(strlen(fontname) + 8, char); - sprintf(fullname, "%6s+%s", uniqueTag, fontname); - - /* Offsets from DICTs */ - cff_read_charsets(cffont); - if (encoding_id < 0) - cff_read_encoding(cffont); - cff_read_private(cffont); - cff_read_subrs (cffont); - - /* FIXME */ - cffont->_string = cff_new_index(0); - - /* New Charsets data */ - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = 0; - charset->data.glyphs = NEW(256, s_SID); - - /* - * Encoding related things. - */ - enc_vec = NULL; - if (encoding_id >= 0) { - enc_vec = pdf_encoding_get_encoding(encoding_id); - } else { - pdf_obj *tounicode; - - /* - * Create enc_vec and ToUnicode CMap for built-in encoding. - */ - enc_vec = NEW(256, char *); - for (code = 0; code < 256; code++) { - if (usedchars[code]) { - card16 gid; - - gid = cff_encoding_lookup(cffont, code); - enc_vec[code] = cff_get_string(cffont, - cff_charsets_lookup_inverse(cffont, gid)); - } else { - enc_vec[code] = NULL; - } - } - if (!pdf_lookup_dict(fontdict, "ToUnicode")) { - tounicode = pdf_create_ToUnicode_CMap(fullname, - enc_vec, usedchars); - if (tounicode) { - pdf_add_dict(fontdict, - pdf_new_name("ToUnicode"), - pdf_ref_obj (tounicode)); - pdf_release_obj(tounicode); - } - } - } - - /* - * New Encoding data: - * - * We should not use format 0 here. - * The number of encoded glyphs (num_entries) is limited to 255 in format 0, - * and hence it causes problem for encodings that uses full 256 code-points. - * As we always sort glyphs by encoding, we can avoid this problem simply - * by using format 1; Using full range result in a single range, 0 255. - * - * Creating actual encoding date is delayed to eliminate character codes to - * be mapped to .notdef and to handle multiply-encoded glyphs. - */ - encoding = NEW(1, cff_encoding); - encoding->format = 1; - encoding->num_entries = 0; - encoding->data.range1 = NEW(255, cff_range1); - encoding->num_supps = 0; - encoding->supp = NEW(255, cff_map); - - /* - * Charastrings. - */ - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - cs_idx = cff_get_index_header(cffont); - - /* Offset is now absolute offset ... fixme */ - offset = ftell(cffont->stream); - cs_count = cs_idx->count; - if (cs_count < 2) { - ERROR("No valid charstring data found."); - } - - /* New CharStrings INDEX */ - charstrings = cff_new_index(257); /* 256 + 1 for ".notdef" glyph */ - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - /* - * Information from OpenType table is rough estimate. Replace with accurate value. - */ - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "StdVW")) { - double stemv; - - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - pdf_add_dict(descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - } - - /* - * Widths - */ - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "defaultWidthX")) { - default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - default_width = CFF_DEFAULTWIDTHX_DEFAULT; - } - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominal_width = CFF_NOMINALWIDTHX_DEFAULT; - } - - data = NEW(CS_STR_LEN_MAX, card8); - - /* First we add .notdef glyph. - * All Type 1 font requires .notdef glyph to be present. - */ - if (verbose > 2) { - MESG("[glyphs:/.notdef"); - } - size = cs_idx->offset[1] - cs_idx->offset[0]; - if (size > CS_STR_LEN_MAX) { - ERROR("Charstring too long: gid=%u, %ld bytes", 0, size); - } - charstrings->offset[0] = charstring_len + 1; - seek_absolute(cffont->stream, offset + cs_idx->offset[0] - 1); - fread(data, 1, size, cffont->stream); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, cffont->subrs[0], - default_width, nominal_width, &ginfo); - notdef_width = ginfo.wx; - - /* - * Subset font - */ - num_glyphs = 1; - for (code = 0; code < 256; code++) { - card16 gid, j; - s_SID sid_orig, sid; - - widths[code] = notdef_width; - - if (!usedchars[code] || !enc_vec[code] || - !strcmp(enc_vec[code], ".notdef")) - continue; - - /* - * FIXME: - * cff_get_sid() obtain SID from original String INDEX. - * It should be cff_string_get_sid(string, ...). - * cff_add_string(cff, ...) -> cff_string_add(string, ...). - */ - sid_orig = cff_get_sid (cffont, enc_vec[code]); - sid = sid_orig < CFF_STDSTR_MAX ? - sid_orig : cff_add_string(cffont, enc_vec[code], 0); - /* - * We use "unique = 0" because duplicate strings are impossible - * at this stage unless the original font already had duplicates. - */ - - /* - * Check if multiply-encoded glyph. - */ - for (j = 0; j < charset->num_entries; j++) { - if (sid == charset->data.glyphs[j]) { - /* Already have this glyph. */ - encoding->supp[encoding->num_supps].code = code; - encoding->supp[encoding->num_supps].glyph = sid; - usedchars[code] = 0; /* Used but multiply-encoded. */ - encoding->num_supps += 1; - break; - } - } - if (j < charset->num_entries) { - continue; /* Prevent duplication. */ - } - - /* This is new encoding entry. */ - gid = cff_charsets_lookup(cffont, sid_orig); /* FIXME */ - if (gid == 0) { - WARN("Glyph \"%s\" missing in font \"%s\".", enc_vec[code], fontname); - WARN("Maybe incorrect encoding specified."); - usedchars[code] = 0; /* Set unused for writing correct encoding */ - continue; - } - if (verbose > 2) { - MESG("/%s", enc_vec[code]); - } - - size = cs_idx->offset[gid+1] - cs_idx->offset[gid]; - if (size > CS_STR_LEN_MAX) { - ERROR("Charstring too long: gid=%u, %ld bytes", gid, size); - } - - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - charstrings->offset[num_glyphs] = charstring_len + 1; - seek_absolute(cffont->stream, offset + cs_idx->offset[gid] - 1); - fread(data, sizeof(char), size, cffont->stream); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, cffont->subrs[0], - default_width, nominal_width, &ginfo); - widths[code] = ginfo.wx; - charset->data.glyphs[charset->num_entries] = sid; - charset->num_entries += 1; - num_glyphs++; - } - if (verbose > 2) { - MESG("]"); - } - RELEASE(data); - - /* - * Now we create encoding data. - */ - if (encoding->num_supps > 0) - encoding->format |= 0x80; /* Have supplemantary data. */ - else { - RELEASE(encoding->supp); /* FIXME */ - } - for (code = 0; code < 256; code++) { - if (!usedchars[code] || - !enc_vec[code] || !strcmp(enc_vec[code], ".notdef")) - continue; - encoding->data.range1[encoding->num_entries].first = code; - encoding->data.range1[encoding->num_entries].n_left = 0; - code++; - while (code < 256 && usedchars[code] && - enc_vec[code] && strcmp(enc_vec[code], ".notdef")) { - encoding->data.range1[encoding->num_entries].n_left += 1; - code++; - } - encoding->num_entries += 1; - /* The above while() loop stopped at unused char or code == 256. */ - } - - /* cleanup */ - if (encoding_id < 0 && enc_vec) { - for (code = 0; code < 256; code++) { - if (enc_vec[code]) { - RELEASE(enc_vec[code]); - } - } - RELEASE(enc_vec); - } - - cff_release_index(cs_idx); - - charstrings->offset[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - charstring_len = cff_index_size(charstrings); - cffont->num_glyphs = num_glyphs; - - /* - * Discard old one, set new data. - */ - if (cffont->charsets) - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - if (cffont->encoding) - cff_release_encoding(cffont->encoding); - cffont->encoding = encoding; - /* - * We don't use subroutines at all. - */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - if (cffont->subrs[0]) - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - - /* - * Flag must be reset since cff_pack_encoding(charset) does not write - * encoding(charset) if HAVE_STANDARD_ENCODING(CHARSET) is set. We are - * re-encoding font. - */ - cffont->flag = FONTTYPE_FONT; - - /* - * FIXME: - * Update String INDEX to delete unused strings. - */ - cff_dict_update(cffont->topdict, cffont); - if (cffont->private[0]) - cff_dict_update(cffont->private[0], cffont); - cff_update_string(cffont); - - /* - * Calculate sizes of Top DICT and Private DICT. - * All offset values in DICT are set to long (32-bit) integer - * in cff_dict_pack(), those values are updated later. - */ - topdict = cff_new_index(1); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - - /* - * Force existence of Encoding. - */ - if (!cff_dict_known(cffont->topdict, "Encoding")) - cff_dict_add(cffont->topdict, "Encoding", 1); - topdict->offset[1] = cff_dict_pack(cffont->topdict, - (card8 *) work_buffer, - WORK_BUFFER_SIZE) + 1; - private_size = 0; - if (cffont->private[0]) { - cff_dict_remove(cffont->private[0], "Subrs"); /* no Subrs */ - private_size = cff_dict_pack(cffont->private[0], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - } - - /* - * Estimate total size of fontfile. - */ - stream_data_len = 4; /* header size */ - - stream_data_len += cff_set_name(cffont, fullname); - RELEASE(fullname); - - stream_data_len += cff_index_size(topdict); - stream_data_len += cff_index_size(cffont->string); - stream_data_len += cff_index_size(cffont->gsubr); - - /* We are using format 1 for Encoding and format 0 for charset. - * TODO: Should implement cff_xxx_size(). - */ - stream_data_len += 2 + (encoding->num_entries)*2 + 1 + (encoding->num_supps)*3; - stream_data_len += 1 + (charset->num_entries)*2; - stream_data_len += charstring_len; - stream_data_len += private_size; - - /* - * Now we create FontFile data. - */ - stream_data_ptr = NEW(stream_data_len, card8); - - /* - * Data Layout order as described in CFF spec., sec 2 "Data Layout". - */ - offset = 0; - /* Header */ - offset += cff_put_header(cffont, stream_data_ptr + offset, stream_data_len - offset); - /* Name */ - offset += cff_pack_index(cffont->name, stream_data_ptr + offset, stream_data_len - offset); - /* Top DICT */ - topdict_offset = offset; - offset += cff_index_size(topdict); - /* Strings */ - offset += cff_pack_index(cffont->string, - stream_data_ptr + offset, stream_data_len - offset); - /* Global Subrs */ - offset += cff_pack_index(cffont->gsubr, - stream_data_ptr + offset, stream_data_len - offset); - /* Encoding */ - cff_dict_set(cffont->topdict, "Encoding", 0, offset); - offset += cff_pack_encoding(cffont, - stream_data_ptr + offset, stream_data_len - offset); - /* charset */ - cff_dict_set(cffont->topdict, "charset", 0, offset); - offset += cff_pack_charsets(cffont, - stream_data_ptr + offset, stream_data_len - offset); - /* CharStrings */ - cff_dict_set(cffont->topdict, "CharStrings", 0, offset); - offset += cff_pack_index(charstrings, - stream_data_ptr + offset, charstring_len); - cff_release_index(charstrings); - /* Private */ - cff_dict_set(cffont->topdict, "Private", 1, offset); - if (cffont->private[0] && private_size > 0) - private_size = cff_dict_pack(cffont->private[0], - stream_data_ptr + offset, private_size); - cff_dict_set(cffont->topdict, "Private", 0, private_size); - offset += private_size; - - /* Finally Top DICT */ - topdict->data = NEW(topdict->offset[1] - 1, card8); - cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1); - cff_pack_index(topdict, - stream_data_ptr + topdict_offset, cff_index_size(topdict)); - cff_release_index(topdict); - - /* Copyright and Trademark Notice ommited. */ - - /* Handle Widths in fontdict. */ - add_SimpleMetrics(font, cffont, widths, num_glyphs); - - /* Close font */ - cff_close (cffont); - sfnt_close(sfont); - - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) { - MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, offset); - } - - /* - * CharSet might be recommended for subsetted font, but it is meaningful - * only for Type 1 font... - */ - - /* - * Write PDF FontFile data. - */ - fontfile = pdf_new_stream(STREAM_COMPRESS); - stream_dict = pdf_stream_dict(fontfile); - pdf_add_dict(descriptor, - pdf_new_name("FontFile3"), pdf_ref_obj (fontfile)); - pdf_add_dict(stream_dict, - pdf_new_name("Subtype"), pdf_new_name("Type1C")); - pdf_add_stream (fontfile, (void *) stream_data_ptr, offset); - pdf_release_obj(fontfile); - - RELEASE(stream_data_ptr); - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/src/xbb.c b/Build/source/texk/dvipdfm-x/src/xbb.c deleted file mode 100644 index cb5ca200a91..00000000000 --- a/Build/source/texk/dvipdfm-x/src/xbb.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - - This is extractbb, a bounding box extraction program. - - Copyright (C) 2008-2012 by Jin-Hwan Cho and Matthias Franz - - 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 -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "numbers.h" -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "pdfobj.h" -#include "pdfdev.h" -#include "pdfdoc.h" -#include "pdfparse.h" - -#include "config.h" - -#include "jpegimage.h" -#include "pngimage.h" - -#include "dvipdfmx.h" - -#define XBB_PROGRAM "extractbb" -#define XBB_VERSION VERSION - -static int really_quiet = 0; - -static void show_version(void) -{ - if (really_quiet) return; - - fprintf (stdout, "%s, version %s, Copyright (C) 2009 by Jin-Hwan Cho and Matthias Franz\n", - XBB_PROGRAM, XBB_VERSION); - fprintf (stdout, "A bounding box extraction utility from PDF, PNG, and JPEG.\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"); - fprintf (stdout, "(at your option) any later version.\n"); -} - -static void show_usage(void) -{ - if (really_quiet) return; - - fprintf (stdout, "\nUsage: %s [-v|-q] [-O] [-m|-x] [files]\n", XBB_PROGRAM); - fprintf (stdout, "\t-v\tBe verbose\n"); - fprintf (stdout, "\t-q\tBe quiet\n"); - fprintf (stdout, "\t-O\tWrite output to stdout\n"); - if(compat_mode) { - fprintf (stdout, "\t-m\tOutput .bb file used in DVIPDFM (default)\n"); - fprintf (stdout, "\t-x\tOutput .xbb file used in DVIPDFMx\n"); - } else { - fprintf (stdout, "\t-m\tOutput .bb file used in DVIPDFM\n"); - fprintf (stdout, "\t-x\tOutput .xbb file used in DVIPDFMx (default)\n"); - } -} - -static void usage(void) -{ - if (really_quiet) return; - - fprintf(stdout, "\nTry \"%s --help\" for more information.\n", XBB_PROGRAM); - exit(1); -} - -static char verbose = 0; - -static void do_time(FILE *file) -{ - time_t current_time; - struct tm *bd_time; - - time(¤t_time); - bd_time = localtime(¤t_time); - fprintf(file, "%%%%CreationDate: %s\n", asctime(bd_time)); -} - -const char *extensions[] = { - ".jpeg", ".JPEG", ".jpg", ".JPG", ".pdf", ".PDF", ".png", ".PNG" -}; - -static int xbb_to_file = 1; - -static char *make_xbb_filename(const char *name) -{ - int i; - char *result; - - for (i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) { - if (strlen(extensions[i]) < strlen(name) && - strncmp(name+strlen(name)-strlen(extensions[i]), extensions[i], strlen(extensions[i])) == 0) - break; - } - if (i == sizeof(extensions) / sizeof(extensions[0])) { - WARN("%s: Filename does not end in a recognizable extension.\n", name); - result = NEW(strlen(name)+5, char); /* 5 = ".xbb" + trailing 0 */ - strcpy(result, name); - } else { /* Remove extension */ - result = NEW(strlen(name)-strlen(extensions[i])+5, char); /* 5 = ".xbb" + trailing 0 */ - strncpy(result, name, strlen(name)-strlen(extensions[i])); - result[strlen(name)-strlen(extensions[i])] = 0; - } - strcat(result, (compat_mode ? ".bb" : ".xbb")); - return result; -} - -static void write_xbb(char *fname, - double bbllx_f, double bblly_f, - double bburx_f, double bbury_f, - int pdf_version, long pagecount) -{ - char *outname = NULL; - FILE *fp; - - long bbllx = ROUND(bbllx_f, 1.0), bblly = ROUND(bblly_f, 1.0); - long bburx = ROUND(bburx_f, 1.0), bbury = ROUND(bbury_f, 1.0); - - if (xbb_to_file) { - outname = make_xbb_filename(fname); - if ((fp = MFOPEN(outname, FOPEN_W_MODE)) == NULL) { - ERROR("Unable to open output file: %s\n", outname); - } - } else { - fp = stdout; -#ifdef WIN32 - setmode(fileno(fp), _O_BINARY); -#endif - } - - if (verbose) { - MESG("Writing to %s: ", xbb_to_file ? outname : "stdout"); - MESG("Bounding box: %d %d %d %d\n", bbllx, bblly, bburx, bbury); - } - - fprintf(fp, "%%%%Title: %s\n", fname); - fprintf(fp, "%%%%Creator: %s %s\n", XBB_PROGRAM, XBB_VERSION); - fprintf(fp, "%%%%BoundingBox: %ld %ld %ld %ld\n", bbllx, bblly, bburx, bbury); - - if (!compat_mode) { - /* Note: - * According to Adobe Technical Note #5644, the arguments to - * "%%HiResBoundingBox:" must be of type real. And according - * to the PostScript Language Reference, a real number must - * be written with a decimal point (or an exponent). Hence - * it seems illegal to replace "0.0" by "0". - */ - fprintf(fp, "%%%%HiResBoundingBox: %f %f %f %f\n", - bbllx_f, bblly_f, bburx_f, bbury_f); - if (pdf_version >= 0) { - fprintf(fp, "%%%%PDFVersion: 1.%d\n", pdf_version); - fprintf(fp, "%%%%Pages: %ld\n", pagecount); - } - } - - do_time(fp); - - if (xbb_to_file) { - RELEASE(outname); - MFCLOSE(fp); - } -} - -static void do_jpeg (FILE *fp, char *filename) -{ - long width, height; - double xdensity, ydensity; - - if (jpeg_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { - WARN("%s does not look like a JPEG file...\n", filename); - return; - } - - write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); - return; -} - -#ifdef HAVE_LIBPNG -static void do_png (FILE *fp, char *filename) -{ - long width, height; - double xdensity, ydensity; - - if (png_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { - WARN("%s does not look like a PNG file...\n", filename); - return; - } - - write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); - return; -} -#endif /* HAVE_LIBPNG */ - -#ifdef XETEX -static int rect_equal (pdf_obj *rect1, pdf_obj *rect2) -{ - int i; - if (!rect1 || !rect2) return 0; - for (i = 0; i < 4; i++) { - if (pdf_number_value(pdf_get_array(rect1, i)) != pdf_number_value(pdf_get_array(rect2, i))) return 0; - } - return 1; -} - -static int pdf_get_info (FILE *image_file, char *filename, int *version, - double *llx, double *lly, double *urx, double *ury) -{ - pdf_obj *page_tree; - pdf_obj *bbox; - pdf_file *pf; - - page_tree = NULL; - { - pdf_obj *trailer, *catalog; - - pf = pdf_open(filename, image_file); - if (!pf) - return -1; - - trailer = pdf_file_get_trailer(pf); - - if (pdf_lookup_dict(trailer, "Encrypt")) { - WARN("This PDF document is encrypted."); - pdf_release_obj(trailer); - pdf_close(pf); - return -1; - } - catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); - if (!catalog) { - WARN("Catalog isn't where I expect it."); - pdf_close(pf); - return -1; - } - pdf_release_obj(trailer); - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - pdf_release_obj(catalog); - } - if (!page_tree) { - WARN("Page tree not found."); - pdf_close(pf); - return -1; - } - { - pdf_obj *kids_ref, *kids; - pdf_obj *crop_box; - 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; - - while ((kids_ref = pdf_lookup_dict(page_tree, "Kids")) != NULL) { - kids = pdf_deref_obj(kids_ref); - pdf_release_obj(page_tree); - page_tree = pdf_deref_obj(pdf_get_array(kids, 0)); - pdf_release_obj(kids); - - 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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(tmp); - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - } - if (crop_box) { - pdf_release_obj(bbox); - bbox = crop_box; - } - } - pdf_release_obj(page_tree); - - if (!bbox) { - WARN("No BoundingBox information available."); - pdf_close(pf); - return -1; - } - - *version = pdf_file_get_version(pf); - - *llx = pdf_number_value(pdf_get_array(bbox, 0)); - *lly = pdf_number_value(pdf_get_array(bbox, 1)); - *urx = pdf_number_value(pdf_get_array(bbox, 2)); - *ury = pdf_number_value(pdf_get_array(bbox, 3)); - - pdf_release_obj(bbox); - - pdf_close(pf); - return 0; -} - -static void do_pdf (FILE *fp, char *filename) -{ - double llx, lly, urx, ury; - int version; - - if (pdf_get_info(fp, filename, &version, &llx, &lly, &urx, &ury) < 0) { - fprintf (stderr, "%s does not look like a PDF file...\n", filename); - return; - } - write_xbb(filename, llx, lly, urx, ury, version, 1); - return; -} -#else -static void do_pdf (FILE *fp, char *filename) -{ - pdf_obj *page; - pdf_file *pf; - long page_no = 1; - long count; - pdf_rect bbox; - - pf = pdf_open(filename, fp); - if (!pf) { - WARN("%s does not look like a PDF file...\n", filename); - return; - } - - page = pdf_doc_get_page(pf, page_no, &count, &bbox, NULL); - - pdf_close(pf); - - if (!page) - return; - - pdf_release_obj(page); - write_xbb(filename, bbox.llx, bbox.lly, bbox.urx, bbox.ury, - pdf_file_get_version(pf), count); -} -#endif - -int extractbb (int argc, char *argv[]) -{ - pdf_files_init(); - - pdf_set_version(5); - - argc -= 1; argv += 1; - if (argc == 0) - usage(); - - while (argc > 0 && *argv[0] == '-') { - char *flag = argv[0] + 1; - switch (*flag) { - case '-': - if (++flag) { - if (!strcmp(flag, "help")) { - show_version(); - show_usage(); - exit(0); - } else if (!strcmp(flag, "version")) { - show_version(); - exit(0); - } - } - if (!really_quiet) - fprintf(stderr, "Unknown option in \"--%s\"", flag); - usage(); - break; - case 'O': - xbb_to_file = 0; - argc -= 1; argv += 1; - break; - case 'm': - compat_mode = 1; - argc -= 1; argv += 1; - break; - case 'x': - compat_mode = 0; - argc -= 1; argv += 1; - break; - case 'v': - verbose = 1; - argc -= 1; argv += 1; - break; - case 'h': - usage(); - argc -= 1; argv += 1; - break; - case 'q': - really_quiet = 1; - shut_up(1); - argc -= 1; argv += 1; - break; - case 'b': - if (compat_mode) { - /* ignore obsolete "binary mode" option */ - argc -= 1; argv += 1; - break; - } - /* else fall through */ - default: - if (!really_quiet) - fprintf(stderr, "Unknown option in \"-%s\"", flag); - usage(); - } - } - - for (; argc > 0; argc--, argv++) { - FILE *infile = NULL; - char *kpse_file_name; - if (!(kpse_file_name = kpse_find_pict(argv[0])) || - (infile = MFOPEN(kpse_file_name, FOPEN_RBIN_MODE)) == NULL) { - WARN("Can't find file (%s)...skipping\n", argv[0]); - goto cont; - } - if (check_for_jpeg(infile)) { - do_jpeg(infile, kpse_file_name); - goto cont; - } - if (check_for_pdf(infile)) { - do_pdf(infile, kpse_file_name); - goto cont; - } -#ifdef HAVE_LIBPNG - if (check_for_png(infile)) { - do_png(infile, kpse_file_name); - goto cont; - } -#endif /* HAVE_LIBPNG */ - WARN("Can't handle file type for file named %s\n", argv[0]); - cont: - if (kpse_file_name) - RELEASE(kpse_file_name); - if (infile) - MFCLOSE(infile); - } - - pdf_files_close(); - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/tfm.c b/Build/source/texk/dvipdfm-x/tfm.c index 9955caf7bad..683daa17af9 100644 --- a/Build/source/texk/dvipdfm-x/tfm.c +++ b/Build/source/texk/dvipdfm-x/tfm.c @@ -53,10 +53,8 @@ static int verbose = 0; #define JFM_ID 11 #define JFMV_ID 9 #define IS_JFM(i) ((i) == JFM_ID || (i) == JFMV_ID) -#endif /* !WITHOUT_ASCII_PTEX */ -#ifndef WITHOUT_ASCII_PTEX -#define CHARACTER_INDEX(i) ((i>0xFFFFul ? 0x10000ul : i)) +#define CHARACTER_INDEX(i) ((i > 0xFFFFUL ? 0x10000UL : i)) #else #define CHARACTER_INDEX(i) ((i)) #endif diff --git a/Build/source/texk/dvipdfm-x/truetype.c b/Build/source/texk/dvipdfm-x/truetype.c index 9e22c012557..0994eba8e3b 100644 --- a/Build/source/texk/dvipdfm-x/truetype.c +++ b/Build/source/texk/dvipdfm-x/truetype.c @@ -148,11 +148,7 @@ pdf_font_open_truetype (pdf_font *font) ERROR("Can't find valid fontname for \"%s\".", ident); pdf_font_set_fontname(font, fontname); -#ifdef XETEX tmp = tt_get_fontdesc(sfont, &embedding, -1, 1, fontname); -#else - tmp = tt_get_fontdesc(sfont, &embedding, -1, 1, NULL); -#endif if (!tmp) { ERROR("Could not obtain necessary font info."); sfnt_close(sfont); diff --git a/Build/source/texk/dvipdfm-x/tt_aux.c b/Build/source/texk/dvipdfm-x/tt_aux.c index 086a7391050..38e30581989 100644 --- a/Build/source/texk/dvipdfm-x/tt_aux.c +++ b/Build/source/texk/dvipdfm-x/tt_aux.c @@ -36,14 +36,12 @@ #include "tt_post.h" #include "tt_aux.h" -#ifdef XETEX static int verbose = 0; void tt_aux_set_verbose(void) { ++verbose; } -#endif ULONG ttc_read_offset (sfnt *sfont, int ttc_idx) { @@ -191,30 +189,20 @@ pdf_obj *tt_get_fontdesc (sfnt *sfont, int *embed, int stemv, int type, const ch /* the least restrictive license granted takes precedence. */ *embed = 1; } else if (os2->fsType & 0x0004) { -#ifdef XETEX if (verbose > 0) - MESG("** NOTICE: Font \"%s\" permits \"Preview & Print\" embedding only **\n", fontname); -#else - fprintf(stderr, - "\n** NOTICE: This document contains `Preview & Print' only"); - fprintf(stderr, " licensed font **\n"); -#endif + WARN("Font \"%s\" permits \"Preview & Print\" embedding only **\n", fontname); *embed = 1; } else { -#ifdef XETEX if (always_embed) { - MESG("** NOTICE: Font \"%s\" may be subject to embedding restrictions **\n", fontname); + if (verbose > 0) + WARN("Font \"%s\" may be subject to embedding restrictions **\n", fontname); *embed = 1; } else { - WARN("Embedding of font \"%s\" disabled due to license restrictions", fontname); + if (verbose > 0) + WARN("Embedding of font \"%s\" disabled due to license restrictions", fontname); *embed = 0; } -#else - fprintf(stderr, - "\n*** Embedding disabled due to licensing restriction ***\n"); - *embed = 0; -#endif } } diff --git a/Build/source/texk/dvipdfm-x/tt_aux.h b/Build/source/texk/dvipdfm-x/tt_aux.h index 738399a4304..3b17d3a70aa 100644 --- a/Build/source/texk/dvipdfm-x/tt_aux.h +++ b/Build/source/texk/dvipdfm-x/tt_aux.h @@ -26,11 +26,9 @@ #include "pdfobj.h" #include "sfnt.h" -#ifdef XETEX extern int always_embed; /* flag declared in dvipdfmx.c */ extern void tt_aux_set_verbose(void); -#endif /* TTC (TrueType Collection) */ extern ULONG ttc_read_offset (sfnt *sfont, int ttc_idx); diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.c b/Build/source/texk/dvipdfm-x/tt_cmap.c new file mode 100644 index 00000000000..facc0e13c23 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/tt_cmap.c @@ -0,0 +1,1946 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, + the dvipdfmx project team. + + 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. +*/ + +/* + * A large part of codes are brought from ttfdump-0.5.5. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "system.h" +#include "mem.h" +#include "error.h" + +#include "sfnt.h" + + +/* Sorry for placing this here. + * We need to rewrite TrueType font support code... + */ +#include "cmap.h" +#include "cmap_write.h" + +#include "tt_aux.h" +#include "tt_gsub.h" + +#include "unicode.h" +#include "agl.h" +#include "pdfparse.h" +#include "pdfresource.h" +#include "otl_conf.h" + +#include "dpxfile.h" + +/* Hash */ +#include "dpxutil.h" + +#include "tt_cmap.h" + +#define VERBOSE_LEVEL_MIN 0 +static int verbose = 0; +void +otf_cmap_set_verbose (void) +{ + otl_gsub_set_verbose(); + verbose++; +} + +/* format 0: byte encoding table */ +struct cmap0 +{ + BYTE glyphIndexArray[256]; +}; + +static struct cmap0 * +read_cmap0 (sfnt *sfont, ULONG len) +{ + struct cmap0 *map; + int i; + + if (len < 256) + ERROR("invalid cmap subtable"); + + map = NEW(1, struct cmap0); + + for (i = 0; i < 256; i++) + map->glyphIndexArray[i] = sfnt_get_byte(sfont); + + return map; +} + +static void +release_cmap0(struct cmap0 *map) +{ + if (map) + RELEASE(map); +} + +static USHORT +lookup_cmap0 (struct cmap0 *map, USHORT cc) +{ + return ((cc > 255) ? 0 : map->glyphIndexArray[cc]); +} + +/* format 2: high-byte mapping through table */ +struct SubHeader +{ + USHORT firstCode; + USHORT entryCount; + SHORT idDelta; + USHORT idRangeOffset; +}; + +struct cmap2 +{ + USHORT subHeaderKeys[256]; + struct SubHeader *subHeaders; + USHORT *glyphIndexArray; +}; + +static struct cmap2 * +read_cmap2 (sfnt *sfont, ULONG len) +{ + struct cmap2 *map; + USHORT i, n; + + if (len < 512) + ERROR("invalid cmap subtable"); + + map = NEW(1, struct cmap2); + + for (i = 0; i < 256; i++) + map->subHeaderKeys[i] = sfnt_get_ushort(sfont); + + for (n = 0, i = 0; i < 256; i++) { + map->subHeaderKeys[i] /= 8; + if (n < map->subHeaderKeys[i]) + n = map->subHeaderKeys[i]; + } + n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ + + map->subHeaders = NEW(n, struct SubHeader); + for (i = 0; i < n; i++) { + map->subHeaders[i].firstCode = sfnt_get_ushort(sfont); + map->subHeaders[i].entryCount = sfnt_get_ushort(sfont); + map->subHeaders[i].idDelta = sfnt_get_short(sfont); + map->subHeaders[i].idRangeOffset = sfnt_get_ushort(sfont); + + /* It makes things easier to let the offset starts from + * the beginning of glyphIndexArray. + */ + if (map->subHeaders[i].idRangeOffset != 0) + map->subHeaders[i].idRangeOffset -= (2 + (n - i - 1) * 8); + } + + /* Caculate the length of glyphIndexArray, this is ugly, + * there should be a better way to get this information. + */ + n = (USHORT) (len - 518 - n * 8) / 2; + + map->glyphIndexArray = NEW(n, USHORT); + for (i = 0; i < n; i++) + map->glyphIndexArray[i] = sfnt_get_ushort(sfont); + + return map; +} + +static void +release_cmap2 (struct cmap2 *map) +{ + if (map) { + if (map->subHeaders) + RELEASE(map->subHeaders); + if (map->glyphIndexArray) + RELEASE(map->glyphIndexArray); + RELEASE(map); + } +} + +static USHORT +lookup_cmap2 (struct cmap2 *map, USHORT cc) +{ + USHORT idx = 0; + SHORT idDelta; + USHORT firstCode, entryCount, idRangeOffset; + int hi, lo; + USHORT i; + + hi = (cc >> 8) & 0xff; + lo = cc & 0xff; + + /* select which subHeader to use */ + i = map->subHeaderKeys[hi]; + + firstCode = map->subHeaders[i].firstCode; + entryCount = map->subHeaders[i].entryCount; + idDelta = map->subHeaders[i].idDelta; + idRangeOffset = map->subHeaders[i].idRangeOffset / 2; + + if (lo >= firstCode && + lo < firstCode + entryCount) { + idRangeOffset += lo - firstCode; + idx = map->glyphIndexArray[idRangeOffset]; + if (idx != 0) + idx = (idx + idDelta) & 0xffff; + } + + return idx; +} + +/* + * format 4: segment mapping to delta values + * - Microsoft standard character to glyph index mapping table + */ +struct cmap4 +{ + USHORT segCountX2; + USHORT searchRange; + USHORT entrySelector; + USHORT rangeShift; + USHORT *endCount; + USHORT reservedPad; + USHORT *startCount; + USHORT *idDelta; + USHORT *idRangeOffset; + USHORT *glyphIndexArray; +}; + +static struct cmap4 * +read_cmap4(sfnt *sfont, ULONG len) +{ + struct cmap4 *map; + USHORT i, n, segCount; + + if (len < 8) + ERROR("invalid cmap subtable"); + + map = NEW(1, struct cmap4); + + map->segCountX2 = segCount = sfnt_get_ushort(sfont); + map->searchRange = sfnt_get_ushort(sfont); + map->entrySelector = sfnt_get_ushort(sfont); + map->rangeShift = sfnt_get_ushort(sfont); + + segCount /= 2; + + map->endCount = NEW(segCount, USHORT); + for (i = 0; i < segCount; i++) + map->endCount[i] = sfnt_get_ushort(sfont); + + map->reservedPad = sfnt_get_ushort(sfont); + + map->startCount = NEW(segCount, USHORT); + for (i = 0; i < segCount; i++) + map->startCount[i] = sfnt_get_ushort(sfont); + + map->idDelta = NEW(segCount, USHORT); + for (i = 0; i < segCount; i++) + map->idDelta[i] = sfnt_get_ushort(sfont); + + map->idRangeOffset = NEW(segCount, USHORT); + for (i = 0; i < segCount; i++) + map->idRangeOffset[i] = sfnt_get_ushort(sfont); + + n = (len - 16 - 8 * segCount) / 2; + if (n == 0) + map->glyphIndexArray = NULL; + else { + map->glyphIndexArray = NEW(n, USHORT); + for (i = 0; i < n; i++) + map->glyphIndexArray[i] = sfnt_get_ushort(sfont); + } + + return map; +} + +static void +release_cmap4 (struct cmap4 *map) +{ + if (map) { + if (map->endCount) RELEASE(map->endCount); + if (map->startCount) RELEASE(map->startCount); + if (map->idDelta) RELEASE(map->idDelta); + if (map->idRangeOffset) RELEASE(map->idRangeOffset); + if (map->glyphIndexArray) RELEASE(map->glyphIndexArray); + RELEASE(map); + } +} + +static USHORT +lookup_cmap4 (struct cmap4 *map, USHORT cc) +{ + USHORT gid = 0; + USHORT i, j, segCount; + + /* + * Segments are sorted in order of increasing endCode values. + * Last segment maps 0xffff to gid 0 (?) + */ + i = segCount = map->segCountX2 / 2; + while (i-- > 0 && cc <= map->endCount[i]) { + if (cc >= map->startCount[i]) { + if (map->idRangeOffset[i] == 0) { + gid = (cc + map->idDelta[i]) & 0xffff; + } else if (cc == 0xffff && map->idRangeOffset[i] == 0xffff) { + /* this is for protection against some old broken fonts... */ + gid = 0; + } else { + j = map->idRangeOffset[i] - (segCount - i) * 2; + j = (cc - map->startCount[i]) + (j / 2); + gid = map->glyphIndexArray[j]; + if (gid != 0) + gid = (gid + map->idDelta[i]) & 0xffff; + } + break; + } + } + + return gid; +} + +/* format 6: trimmed table mapping */ +struct cmap6 +{ + USHORT firstCode; + USHORT entryCount; + USHORT *glyphIndexArray; +}; + +static struct cmap6 * +read_cmap6 (sfnt *sfont, ULONG len) +{ + struct cmap6 *map; + USHORT i; + + if (len < 4) + ERROR("invalid cmap subtable"); + + map = NEW(1, struct cmap6); + map->firstCode = sfnt_get_ushort(sfont); + map->entryCount = sfnt_get_ushort(sfont); + map->glyphIndexArray = NEW(map->entryCount, USHORT); + + for (i = 0; i < map->entryCount; i++) + map->glyphIndexArray[i] = sfnt_get_ushort(sfont); + + return map; +} + +static void +release_cmap6 (struct cmap6 *map) +{ + if (map) { + if (map->glyphIndexArray) + RELEASE(map->glyphIndexArray); + RELEASE(map); + } +} + +static USHORT +lookup_cmap6 (struct cmap6 *map, USHORT cc) +{ + USHORT idx; + + idx = cc - map->firstCode; + if (idx < map->entryCount) + return map->glyphIndexArray[idx]; + else + return 0; + + return 0; +} + +/* Format 8 and 10 not supported... + * + * format 8: mixed 16-bit and 32-bit coverage + * format 10: trimmed array + */ + +/* + * format 12: segmented coverage + * + * startGlyphID is 32-bit long, however, GlyphID is still 16-bit long ! + */ + +struct charGroup +{ + ULONG startCharCode; + ULONG endCharCode; + ULONG startGlyphID; +}; + +struct cmap12 +{ + ULONG nGroups; + struct charGroup *groups; +}; + +/* ULONG length */ +static struct cmap12 * +read_cmap12 (sfnt *sfont, ULONG len) +{ + struct cmap12 *map; + ULONG i; + + if (len < 4) + ERROR("invalid cmap subtable"); + + map = NEW(1, struct cmap12); + map->nGroups = sfnt_get_ulong(sfont); + map->groups = NEW(map->nGroups, struct charGroup); + + for (i = 0; i < map->nGroups; i++) { + map->groups[i].startCharCode = sfnt_get_ulong(sfont); + map->groups[i].endCharCode = sfnt_get_ulong(sfont); + map->groups[i].startGlyphID = sfnt_get_ulong(sfont); + } + + return map; +} + +static void +release_cmap12 (struct cmap12 *map) +{ + if (map) { + if (map->groups) + RELEASE(map->groups); + RELEASE(map); + } +} + +static USHORT +lookup_cmap12 (struct cmap12 *map, ULONG cccc) +{ + USHORT gid = 0; + ULONG i; + + i = map->nGroups; + while (i-- >= 0 && + cccc <= map->groups[i].endCharCode) { + if (cccc >= map->groups[i].startCharCode) { + gid = (USHORT) ((cccc - + map->groups[i].startCharCode + + map->groups[i].startGlyphID) & 0xffff); + break; + } + } + + return gid; +} + +/* read cmap */ +tt_cmap * +tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) +{ + tt_cmap *cmap = NULL; + ULONG offset, length = 0; + USHORT p_id, e_id; + USHORT i, n_subtabs; + + ASSERT(sfont); + + offset = sfnt_locate_table(sfont, "cmap"); + (void) sfnt_get_ushort(sfont); + n_subtabs = sfnt_get_ushort(sfont); + + for (i = 0; i < n_subtabs; i++) { + p_id = sfnt_get_ushort(sfont); + e_id = sfnt_get_ushort(sfont); + if (p_id != platform || e_id != encoding) + sfnt_get_ulong(sfont); + else { + offset += sfnt_get_ulong(sfont); + break; + } + } + + if (i == n_subtabs) + return NULL; + + cmap = NEW(1, tt_cmap); + cmap->map = NULL; + cmap->platform = platform; + cmap->encoding = encoding; + + sfnt_seek_set(sfont, offset); + cmap->format = sfnt_get_ushort(sfont); + /* Length and version (language) is ULONG for + * format 8, 10, 12 ! + */ + if (cmap->format <= 6) { + length = sfnt_get_ushort(sfont); + cmap->language = sfnt_get_ushort(sfont); /* language (Mac) */ + } else { + if (sfnt_get_ushort(sfont) != 0) { /* reverved - 0 */ + WARN("Unrecognized cmap subtable format."); + tt_cmap_release(cmap); + return NULL; + } else { + length = sfnt_get_ulong(sfont); + cmap->language = sfnt_get_ulong(sfont); + } + } + + switch(cmap->format) { + case 0: + cmap->map = read_cmap0(sfont, length); + break; + case 2: + cmap->map = read_cmap2(sfont, length); + break; + case 4: + cmap->map = read_cmap4(sfont, length); + break; + case 6: + cmap->map = read_cmap6(sfont, length); + break; + case 12: + /* WARN("UCS-4 TrueType cmap table..."); */ + cmap->map = read_cmap12(sfont, length); + break; + default: + WARN("Unrecognized OpenType/TrueType cmap format."); + tt_cmap_release(cmap); + return NULL; + } + + if (!cmap->map) { + tt_cmap_release(cmap); + cmap = NULL; + } + + return cmap; +} + +void +tt_cmap_release (tt_cmap *cmap) +{ + + if (cmap) { + if (cmap->map) { + switch(cmap->format) { + case 0: + release_cmap0(cmap->map); + break; + case 2: + release_cmap2(cmap->map); + break; + case 4: + release_cmap4(cmap->map); + break; + case 6: + release_cmap6(cmap->map); + break; + case 12: + release_cmap12(cmap->map); + break; + default: + ERROR("Unrecognized OpenType/TrueType cmap format."); + } + } + RELEASE(cmap); + } + + return; +} + + +USHORT +tt_cmap_lookup (tt_cmap *cmap, long cc) +{ + USHORT gid = 0; + + ASSERT(cmap); + + if (cc > 0xffffL && cmap->format < 12) { + WARN("Four bytes charcode not supported in OpenType/TrueType cmap format 0...6."); + return 0; + } + + switch (cmap->format) { + case 0: + gid = lookup_cmap0(cmap->map, (USHORT) cc); + break; + case 2: + gid = lookup_cmap2(cmap->map, (USHORT) cc); + break; + case 4: + gid = lookup_cmap4(cmap->map, (USHORT) cc); + break; + case 6: + gid = lookup_cmap6(cmap->map, (USHORT) cc); + break; + case 12: + gid = lookup_cmap12(cmap->map, (ULONG) cc); + break; + default: + ERROR("Unrecognized OpenType/TrueType cmap subtable format"); + break; + } + + return gid; +} + +/* Sorry for placing this here. + * We need to rewrite TrueType font support code... + */ + +#define WBUF_SIZE 1024 +static unsigned char wbuf[WBUF_SIZE]; + +static unsigned char srange_min[2] = {0x00, 0x00}; +static unsigned char srange_max[2] = {0xff, 0xff}; +static unsigned char lrange_min[4] = {0x00, 0x00, 0x00, 0x00}; +static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff}; + +static void +load_cmap4 (struct cmap4 *map, + unsigned char *GIDToCIDMap, CMap *cmap) +{ + USHORT c0, c1, gid, cid; + USHORT j, d, segCount; + USHORT ch; + long i; + + segCount = map->segCountX2 / 2; + for (i = segCount - 1; i >= 0 ; i--) { + c0 = map->startCount[i]; + c1 = map->endCount[i]; + d = map->idRangeOffset[i] / 2 - (segCount - i); + for (j = 0; j <= c1 - c0; j++) { + ch = c0 + j; + if (map->idRangeOffset[i] == 0) { + gid = (ch + map->idDelta[i]) & 0xffff; + } else if (c0 == 0xffff && c1 == 0xffff && map->idRangeOffset[i] == 0xffff) { + /* this is for protection against some old broken fonts... */ + gid = 0; + } else { + gid = (map->glyphIndexArray[j+d] + + map->idDelta[i]) & 0xffff; + } + if (gid != 0 && gid != 0xffff) { + if (GIDToCIDMap) { + cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); + if (cid == 0) + WARN("GID %u does not have corresponding CID %u.", + gid, cid); + } else { + cid = gid; + } + wbuf[0] = 0; + wbuf[1] = 0; + wbuf[2] = (ch >> 8) & 0xff; + wbuf[3] = ch & 0xff; + CMap_add_cidchar(cmap, wbuf, 4, cid); + } + } + } + + return; +} + +static void +load_cmap12 (struct cmap12 *map, + unsigned char *GIDToCIDMap, CMap *cmap) +{ + ULONG i, ch; /* LONG ? */ + USHORT gid, cid; + + for (i = 0; i < map->nGroups; i++) { + for (ch = map->groups[i].startCharCode; + ch <= map->groups[i].endCharCode; + ch++) { + long d = ch - map->groups[i].startCharCode; + gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); + if (GIDToCIDMap) { + cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); + if (cid == 0) + WARN("GID %u does not have corresponding CID %u.", gid, cid); + } else { + cid = gid; + } + wbuf[0] = (ch >> 24) & 0xff; + wbuf[1] = (ch >> 16) & 0xff; + wbuf[2] = (ch >> 8) & 0xff; + wbuf[3] = ch & 0xff; + CMap_add_cidchar(cmap, wbuf, 4, cid); + } + } + + return; +} + +/* OpenType CIDFont: + * + * We don't use GID for them. OpenType cmap table is for + * charcode to GID mapping rather than to-CID mapping. + */ +#include "cid.h" + +#include "tt_table.h" +#include "cff_types.h" +#include "cff_dict.h" +#include "cff.h" + +static int +handle_CIDFont (sfnt *sfont, + unsigned char **GIDToCIDMap, CIDSysInfo *csi) +{ + cff_font *cffont; + long offset, i; + card16 num_glyphs, gid; + cff_charsets *charset; + unsigned char *map; + struct tt_maxp_table *maxp; + + ASSERT(csi); + + offset = sfnt_find_table_pos(sfont, "CFF "); + if (offset == 0) { + csi->registry = NULL; + csi->ordering = NULL; + *GIDToCIDMap = NULL; + return 0; + } + + maxp = tt_read_maxp_table(sfont); + num_glyphs = (card16) maxp->numGlyphs; + RELEASE(maxp); + if (num_glyphs < 1) + ERROR("No glyph contained in this font..."); + +#ifdef XETEX + cffont = cff_open(sfont, offset, 0); +#else + cffont = cff_open(sfont->stream, offset, 0); +#endif + if (!cffont) + ERROR("Could not open CFF font..."); + + + if (!(cffont->flag & FONTTYPE_CIDFONT)) { + cff_close(cffont); + csi->registry = NULL; + csi->ordering = NULL; + *GIDToCIDMap = NULL; + return 0; + } + + if (!cff_dict_known(cffont->topdict, "ROS")) { + ERROR("No CIDSystemInfo???"); + } else { + card16 reg, ord; + + reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0); + ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1); + + csi->registry = cff_get_string(cffont, reg); + csi->ordering = cff_get_string(cffont, ord); + csi->supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2); + } + + cff_read_charsets(cffont); + charset = cffont->charsets; + if (!charset) { + ERROR("No CFF charset data???"); + } + + map = NEW(num_glyphs * 2, unsigned char); + memset(map, 0, num_glyphs * 2); + switch (charset->format) { + case 0: + { + s_SID *cids; /* CID... */ + + cids = charset->data.glyphs; + for (gid = 1, i = 0; + i < charset->num_entries; i++) { + map[2*gid ] = (cids[i] >> 8) & 0xff; + map[2*gid+1] = cids[i] & 0xff; + gid++; + } + } + break; + case 1: + { + cff_range1 *ranges; + card16 cid, count; + + ranges = charset->data.range1; + for (gid = 1, i = 0; + i < charset->num_entries; i++) { + cid = ranges[i].first; + count = ranges[i].n_left + 1; /* card8 */ + while (count-- > 0 && + gid <= num_glyphs) { + map[2*gid ] = (cid >> 8) & 0xff; + map[2*gid + 1] = cid & 0xff; + gid++; + } + } + } + break; + case 2: + { + cff_range2 *ranges; + card16 cid, count; + + ranges = charset->data.range2; + if (charset->num_entries == 1 && + ranges[0].first == 1) { + /* "Complete" CIDFont */ + RELEASE(map); map = NULL; + } else { + /* Not trivial mapping */ + for (gid = 1, i = 0; + i < charset->num_entries; i++) { + cid = ranges[i].first; + count = ranges[i].n_left + 1; + while (count-- > 0 && + gid <= num_glyphs) { + map[gid] = (cid >> 8) & 0xff; + map[gid] = cid & 0xff; + gid++; + } + } + + } + } + break; + default: + RELEASE(map); map = NULL; + ERROR("Unknown CFF charset format...: %d", charset->format); + break; + } + cff_close(cffont); + + *GIDToCIDMap = map; + return 1; +} + +/* + * Substituted glyphs: + * + * Mapping information stored in cmap_add. + */ +#ifndef is_used_char2 +#define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8)))) +#endif + +static USHORT +handle_subst_glyphs (CMap *cmap, + CMap *cmap_add, const char *used_glyphs, + sfnt *sfont) +{ + USHORT count; + USHORT i, gid; + + for (count = 0, i = 0; i < 8192; i++) { + int j; + long len, inbytesleft, outbytesleft; + const unsigned char *inbuf; + unsigned char *outbuf; + + if (used_glyphs[i] == 0) + continue; + + for (j = 0; j < 8; j++) { + gid = 8 * i + j; + + if (!is_used_char2(used_glyphs, gid)) + continue; + + if (!cmap_add) { +#if XETEX + if (FT_HAS_GLYPH_NAMES(sfont->ft_face)) { + /* JK: try to look up Unicode values from the glyph name... */ +#define MAX_UNICODES 16 +#define MAX_NAME 256 + static char name[MAX_NAME] = "(none)"; + long unicodes[MAX_UNICODES]; + int unicode_count = -1; + FT_Error err = FT_Get_Glyph_Name(sfont->ft_face, gid, name, MAX_NAME); + if (!err) { + unicode_count = agl_get_unicodes(name, unicodes, MAX_UNICODES); + } +#undef MAX_UNICODES +#undef MAX_NAME + if (unicode_count == -1) { + MESG("No Unicode mapping available: GID=%u, name=%s\n", gid, name); + } else { + /* the Unicode characters go into wbuf[2] and following, in UTF16BE */ + /* we rely on WBUF_SIZE being more than adequate for MAX_UNICODES */ + unsigned char* p = wbuf + 2; + int k; + len = 0; + 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); + } + } +#else + WARN("No Unicode mapping available: GID=%u", gid); +#endif + } else { + wbuf[0] = (gid >> 8) & 0xff; + wbuf[1] = gid & 0xff; + inbuf = wbuf; + inbytesleft = 2; + outbuf = wbuf + 2; + outbytesleft = WBUF_SIZE - 2; + CMap_decode(cmap_add, + &inbuf , &inbytesleft, + &outbuf, &outbytesleft); + if (inbytesleft != 0) { + WARN("CMap conversion failed..."); + } else { + len = WBUF_SIZE - 2 - outbytesleft; + CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len); + count++; + + if (verbose > VERBOSE_LEVEL_MIN) { + long _i; + + MESG("otf_cmap>> Additional ToUnicode mapping: <%04X> <", gid); + for (_i = 0; _i < len; _i++) { + MESG("%02X", wbuf[2 + _i]); + } + MESG(">\n"); + } + + } + } + + } + } + + return count; +} + +static pdf_obj * +create_ToUnicode_cmap4 (struct cmap4 *map, + const char *cmap_name, CMap *cmap_add, + const char *used_glyphs, + sfnt *sfont) +{ + pdf_obj *stream = NULL; + CMap *cmap; + USHORT c0, c1, gid, count, ch; + USHORT i, j, d, segCount; + char used_glyphs_copy[8192]; + + cmap = CMap_new(); + CMap_set_name (cmap, cmap_name); + CMap_set_wmode(cmap, 0); + CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); + CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); + CMap_add_codespacerange(cmap, srange_min, srange_max, 2); + + memcpy(used_glyphs_copy, used_glyphs, 8192); + + segCount = map->segCountX2 / 2; + for (count = 0, i = 0; i < segCount; i++) { + c0 = map->startCount[i]; + c1 = map->endCount[i]; + d = map->idRangeOffset[i] / 2 - (segCount - i); + for (j = 0; j <= c1 - c0; j++) { + ch = c0 + j; + if (map->idRangeOffset[i] == 0) { + gid = (ch + map->idDelta[i]) & 0xffff; + } else if (c0 == 0xffff && c1 == 0xffff && map->idRangeOffset[i] == 0xffff) { + /* this is for protection against some old broken fonts... */ + gid = 0; + } else { + gid = (map->glyphIndexArray[j+d] + + map->idDelta[i]) & 0xffff; + } + if (is_used_char2(used_glyphs_copy, gid)) { + count++; + + wbuf[0] = (gid >> 8) & 0xff; + wbuf[1] = (gid & 0xff); + + wbuf[2] = (ch >> 8) & 0xff; + wbuf[3] = ch & 0xff; + + CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, 2); + + /* Avoid duplicate entry + * There are problem when two Unicode code is mapped to + * single glyph... + */ + used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); + count++; + } + } + } + + count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont); + + if (count < 1) + stream = NULL; + else { + stream = CMap_create_stream(cmap, 0); + } + CMap_release(cmap); + + return stream; +} + + +static pdf_obj * +create_ToUnicode_cmap12 (struct cmap12 *map, + const char *cmap_name, CMap *cmap_add, + const char *used_glyphs, + sfnt *sfont) +{ + pdf_obj *stream = NULL; + CMap *cmap; + ULONG i, ch; + USHORT gid, count; + char used_glyphs_copy[8192]; + + cmap = CMap_new(); + CMap_set_name (cmap, cmap_name); + CMap_set_wmode(cmap, 0); + CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); + CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); + CMap_add_codespacerange(cmap, srange_min, srange_max, 2); + + memcpy(used_glyphs_copy, used_glyphs, 8192); + for (count = 0, i = 0; i < map->nGroups; i++) { + for (ch = map->groups[i].startCharCode; + ch <= map->groups[i].endCharCode; ch++) { + unsigned char *p; + int len; + long d; + + p = wbuf + 2; + d = ch - map->groups[i].startCharCode; + gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); + if (is_used_char2(used_glyphs_copy, gid)) { + count++; + wbuf[0] = (gid >> 8) & 0xff; + wbuf[1] = (gid & 0xff); + len = UC_sput_UTF16BE((long)ch, &p, wbuf+WBUF_SIZE); + + used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); + CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); + } + } + } + + count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont); + + if (count < 1) + stream = NULL; + else { + stream = CMap_create_stream(cmap, 0); + } + CMap_release(cmap); + + return stream; +} + +typedef struct { + short platform; + short encoding; +} cmap_plat_enc_rec; + +static cmap_plat_enc_rec cmap_plat_encs[] = { + { 3, 10 }, + { 0, 3 }, + { 0, 0 }, + { 3, 1 }, + { 0, 1 } +}; + +pdf_obj * +otf_create_ToUnicode_stream (const char *font_name, + int ttc_index, /* 0 for non-TTC */ +#ifdef XETEX + FT_Face face, +#endif + const char *used_glyphs) +{ + pdf_obj *cmap_ref = NULL; + long res_id; + pdf_obj *cmap_obj = NULL; + CMap *cmap_add; + int cmap_add_id; + tt_cmap *ttcmap; + char *normalized_font_name; + char *cmap_name; + FILE *fp = NULL; + sfnt *sfont; + long offset = 0; + int i; + + /* replace slash in map name with dash to make the output cmap name valid, + * happens when XeTeX embeds full font path + * https://sourceforge.net/p/xetex/bugs/52/ + */ + normalized_font_name = NEW(strlen(font_name)+1, char); + strcpy(normalized_font_name, font_name); + for (i = 0; i < strlen(font_name); ++i) { + if (normalized_font_name[i] == '/') + normalized_font_name[i] = '-'; + } + + cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+5, char); + sprintf(cmap_name, "%s,%03d-UTF16", normalized_font_name, ttc_index); + + res_id = pdf_findresource("CMap", cmap_name); + if (res_id >= 0) { + RELEASE(cmap_name); + cmap_ref = pdf_get_resource_reference(res_id); + return cmap_ref; + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("\n"); + MESG("otf_cmap>> Creating ToUnicode CMap for \"%s\"...\n", font_name); + } + +#ifdef XETEX + sfont = sfnt_open(face, -1); +#else + fp = DPXFOPEN(font_name, DPX_RES_TYPE_TTFONT); + if (!fp) { + fp = DPXFOPEN(font_name, DPX_RES_TYPE_OTFONT); + } + + if (!fp) { + RELEASE(cmap_name); + return NULL; + } + + sfont = sfnt_open(fp); +#endif + + if (!sfont) { + ERROR("Could not open OpenType/TrueType font file \"%s\"", font_name); + } + + switch (sfont->type) { + case SFNT_TYPE_TTC: + offset = ttc_read_offset(sfont, ttc_index); + if (offset == 0) { + ERROR("Invalid TTC index"); + } + break; + default: + offset = 0; + break; + } + + if (sfnt_read_table_directory(sfont, offset) < 0) { + ERROR("Could not read OpenType/TrueType table directory."); + } + + cmap_add_id = CMap_cache_find(cmap_name); + if (cmap_add_id < 0) { + cmap_add = NULL; + } else { + cmap_add = CMap_cache_get(cmap_add_id); + } + + CMap_set_silent(1); /* many warnings without this... */ + for (i = 0; i < sizeof(cmap_plat_encs) / sizeof(cmap_plat_enc_rec); ++i) { + ttcmap = tt_cmap_read(sfont, cmap_plat_encs[i].platform, cmap_plat_encs[i].encoding); + if (!ttcmap) + continue; + if (ttcmap->format == 4) { + cmap_obj = create_ToUnicode_cmap4(ttcmap->map, + cmap_name, cmap_add, used_glyphs, sfont); + break; + } + if (ttcmap->format == 12) { + cmap_obj = create_ToUnicode_cmap12(ttcmap->map, + cmap_name, cmap_add, used_glyphs, sfont); + break; + } + } + if (cmap_obj == NULL) + WARN("Unable to read OpenType/TrueType Unicode cmap table."); + tt_cmap_release(ttcmap); + CMap_set_silent(0); + + if (cmap_obj) { + res_id = pdf_defineresource("CMap", cmap_name, + cmap_obj, PDF_RES_FLUSH_IMMEDIATE); + cmap_ref = pdf_get_resource_reference(res_id); + } else { + cmap_ref = NULL; + } + RELEASE(cmap_name); + + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return cmap_ref; +} + +/* Must be smaller than (WBUF_SIZE-2)/8 */ +#define MAX_UNICODES 16 + +struct gent +{ + USHORT gid; + long ucv; /* assigned PUA unicode */ + + int num_unicodes; + long unicodes[MAX_UNICODES]; +}; + +static void +create_cmaps (CMap *cmap, CMap *tounicode, + struct ht_table *unencoded, unsigned char *GIDToCIDMap) +{ + struct ht_iter iter; + + ASSERT(cmap && unencoded); + + if (ht_set_iter(unencoded, &iter) < 0) + return; + + CMap_set_silent(1); /* many warnings without this... */ + + do { + struct gent *glyph; + unsigned char *ucv; + int i, len; + unsigned char *p, *endptr; + CID cid; + + glyph = (struct gent *) ht_iter_getval(&iter); + ucv = (unsigned char *) ht_iter_getkey(&iter, &len); + + if (GIDToCIDMap) { + cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]); + if (cid == 0) + WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid); + } else { + cid = glyph->gid; + } + + CMap_add_cidchar(cmap, ucv, 4, cid); + + if (tounicode) { + wbuf[0] = (cid >> 8) & 0xff; + wbuf[1] = cid & 0xff; + p = wbuf + 2; + endptr = wbuf + WBUF_SIZE; + len = 0; + for (i = 0; i < glyph->num_unicodes; i++) { + len += UC_sput_UTF16BE(glyph->unicodes[i], &p, endptr); + } + CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len); + } + } while (ht_iter_next(&iter) >= 0); + + CMap_set_silent(0); + + ht_clear_iter(&iter); +} + +static void +add_glyph (struct ht_table *unencoded, + USHORT gid, long ucv, int num_unicodes, long *unicodes) +{ + struct gent *glyph; + int i; + + ASSERT(unencoded); + + if (gid == 0 || num_unicodes < 1) { + return; + } + + wbuf[0] = (ucv >> 24) & 0xff; + wbuf[1] = (ucv >> 16) & 0xff; + wbuf[2] = (ucv >> 8) & 0xff; + wbuf[3] = ucv & 0xff; + + glyph = NEW(1, struct gent); + glyph->gid = gid; + glyph->num_unicodes = num_unicodes; + for (i = 0; + i < num_unicodes && i < MAX_UNICODES; i++) { + glyph->unicodes[i] = unicodes[i]; + } + + ht_append_table(unencoded, wbuf, 4, glyph); +} + +/* This seriously affects speed... */ +static struct gent * +find_glyph (struct ht_table *unencoded, long ucv) +{ + ASSERT(unencoded); + + wbuf[0] = (ucv >> 24) & 0xff; + wbuf[1] = (ucv >> 16) & 0xff; + wbuf[2] = (ucv >> 8) & 0xff; + wbuf[3] = ucv & 0xff; + + return (struct gent *) ht_lookup_table(unencoded, wbuf, 4); +} + +static void +handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag, + otl_gsub *gsub_list, tt_cmap *ttcmap, + struct ht_table *unencoded) +{ + pdf_obj *tmp; + long i, j, src_size, dst_size; + long src, dst; + long src_start, src_end, dst_start, dst_end; + + src_size = pdf_array_length(src_obj); + dst_size = pdf_array_length(dst_obj); + + dst_start = dst_end = -1; dst = 0; + src_start = src_end = -1; src = 0; + for (i = 0, j = 0; + i < src_size && j < dst_size; i++) { + USHORT gid; + int rv; + struct gent *glyph; + + tmp = pdf_get_array(src_obj, i); + if (PDF_OBJ_ARRAYTYPE(tmp)) { + src_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); + src_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); + } else { + src_start = src_end = (long) pdf_number_value(tmp); + } + for (src = src_start; src <= src_end; src++) { + glyph = find_glyph(unencoded, src); + if (glyph) + gid = glyph->gid; + else { + gid = tt_cmap_lookup(ttcmap, src); + } + dst++; + if (dst > dst_end) { + tmp = pdf_get_array(dst_obj, j++); + if (PDF_OBJ_ARRAYTYPE(tmp)) { + dst_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); + dst_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); + } else { + dst_start = dst_end = (long) pdf_number_value(tmp); + } + dst = dst_start; + } + if (gid == 0) { + if (flag == 'r' || flag == 'p') { + if (src < 0x10000) { + WARN("Font does not have glyph for U+%04X.", src); + } else { + WARN("Font does not have glyph for U+%06X.", src); + } + } + if (flag == 'r') { + ERROR("Missing glyph found..."); + } + continue; + } + rv = otl_gsub_apply(gsub_list, &gid); + if (rv < 0) { + if (flag == 'p' || flag == 'r') { + if (src < 0x10000) { + WARN("No substituted glyph for U+%04X.", src); + } else { + WARN("No substituted glyph for U+%06X.", src); + } + } + if (flag == 'r') { + ERROR("Missing glyph found..."); + } + continue; + } + + if (glyph) { + glyph->gid = gid; + } else { + add_glyph(unencoded, gid, dst, 1, &src); + } + + if (verbose > VERBOSE_LEVEL_MIN) { + if (dst < 0x10000) { + MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n", + gid, dst); + } else { + MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n", + gid, dst); + } + } + + } + } + + if (dst < dst_end || src < src_end || + i < src_size || j < dst_size) { + WARN("Number of glyphs in left-side and right-side not equal..."); + WARN("Please check .otl file..."); + } +} + +static void +handle_assign (pdf_obj *dst, pdf_obj *src, int flag, + otl_gsub *gsub_list, tt_cmap *ttcmap, + struct ht_table *unencoded) +{ + long unicodes[MAX_UNICODES], ucv; + int i, n_unicodes, rv; + USHORT gid_in[MAX_UNICODES], lig; + + n_unicodes = pdf_array_length(src); /* FIXME */ + ucv = (long) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */ + if (!UC_is_valid(ucv)) { + if (flag == 'r' || flag == 'p') { + if (ucv < 0x10000) { + WARN("Invalid Unicode in: %04X", ucv); + } else { + WARN("Invalid Unicode in: %06X", ucv); + } + } + if (flag == 'r') { + ERROR("Invalid Unicode code specified.", ucv); + } + return; + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otf_cmap>> Ligature component:"); + } + + for (i = 0; i < n_unicodes; i++) { + unicodes[i] = + (long) pdf_number_value(pdf_get_array(src, i)); + gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]); + + if (verbose > VERBOSE_LEVEL_MIN) { + if (unicodes[i] < 0x10000) { + MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]); + } else { + MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]); + } + } + + if (gid_in[i] == 0) { + if (flag == 'r' || flag == 'p') { + if (unicodes[i] < 0x10000) { + WARN("Unicode char U+%04X not exist in font...", unicodes[i]); + } else { + WARN("Unicode char U+%06X not exist in font...", unicodes[i]); + } + } + if (flag == 'r') { + ERROR("Missing glyph found..."); + } + return; + } + + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("\n"); + } + + rv = otl_gsub_apply_lig(gsub_list, + gid_in, (USHORT)n_unicodes, &lig); + if (rv < 0) { + if (flag == 'p') + WARN("No ligature found..."); + else if (flag == 'r') + ERROR("No ligature found..."); + return; + } + + add_glyph(unencoded, lig, ucv, n_unicodes, unicodes); + + if (verbose > VERBOSE_LEVEL_MIN) { + if (ucv < 0x10000) { + MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv); + } else { + MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv); + } + } + + return; +} + +static int +load_base_CMap (const char *cmap_name, int wmode, + CIDSysInfo *csi, unsigned char *GIDToCIDMap, + tt_cmap *ttcmap) +{ + int cmap_id; + + cmap_id = CMap_cache_find(cmap_name); + if (cmap_id < 0) { + CMap *cmap; + + cmap = CMap_new(); + CMap_set_name (cmap, cmap_name); + CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); + CMap_set_wmode(cmap, wmode); + CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); + + if (csi) { /* CID */ + CMap_set_CIDSysInfo(cmap, csi); + } else { + CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); + } + + if (ttcmap->format == 12) { + load_cmap12(ttcmap->map, GIDToCIDMap, cmap); + } else if (ttcmap->format == 4) { + load_cmap4(ttcmap->map, GIDToCIDMap, cmap); + } + + cmap_id = CMap_cache_add(cmap); + } + + return cmap_id; +} + +static void +load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont) +{ + pdf_obj *rule; + char *script, *language, *feature; + long i, size; + + rule = otl_conf_get_rule(conf); + if (!rule) + return; + + script = otl_conf_get_script (conf); + language = otl_conf_get_language(conf); + + size = pdf_array_length(rule); + for (i = 0; i < size; i += 2) { + pdf_obj *tmp, *commands; + int flag; + long j, num_comms; + + tmp = pdf_get_array(rule, i); + flag = (int) pdf_number_value(tmp); + + commands = pdf_get_array(rule, i+1); + num_comms = pdf_array_length(commands); + + /* (assign|substitute) tag dst src */ + for (j = 0 ; j < num_comms; j += 4) { + tmp = pdf_get_array(commands, 1); + if (PDF_OBJ_STRINGTYPE(tmp)) { + feature = pdf_string_value(tmp); + if (otl_gsub_add_feat(gsub_list, + script, language, feature, sfont) < 0) { + if (flag == 'p') + WARN("No OTL feature matches \"%s.%s.%s\" found.", + script, language, feature); + else if (flag == 'r') + ERROR("No OTL feature matches \"%s.%s.%s\" found.", + script, language, feature); + } + } + + } + } + +} + +static void +handle_gsub (pdf_obj *conf, + tt_cmap *ttcmap, otl_gsub *gsub_list, + struct ht_table *unencoded) +{ + pdf_obj *rule; + char *script, *language, *feature; + long i, size; + + if (!conf) + return; + + rule = otl_conf_get_rule(conf); + if (!rule) { + return; + } + + if (!PDF_OBJ_ARRAYTYPE(rule)) { + WARN("Not arraytype?"); + return; + } + script = otl_conf_get_script (conf); + language = otl_conf_get_language(conf); + + size = pdf_array_length(rule); + for (i = 0; i < size; i += 2) { + pdf_obj *tmp, *commands; + long j, num_comms; + int flag; + + tmp = pdf_get_array(rule, i); + flag = (int) pdf_number_value(tmp); + + commands = pdf_get_array (rule, i+1); + num_comms = pdf_array_length(commands); + + for (j = 0; j < num_comms; j += 4) { + pdf_obj *operator; + pdf_obj *src, *dst, *feat; + int rv; + + /* (assing|substitute) tag dst src */ + operator = pdf_get_array(commands, j); + + feat = pdf_get_array(commands, j+1); + if (PDF_OBJ_STRINGTYPE(feat)) + feature = pdf_string_value(feat); + else + feature = NULL; + + dst = pdf_get_array(commands, j+2); + src = pdf_get_array(commands, j+3); + + rv = otl_gsub_select(gsub_list, script, language, feature); + if (rv < 0) { + if (flag == 'p') { + WARN("No GSUB feature %s.%s.%s loaded...", + script, language, feature); + } else if (flag == 'r') { + ERROR("No GSUB feature %s.%s.%s loaded...", + script, language, feature); + } + } else { + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otf_cmap>> %s:\n", pdf_name_value(operator)); + } + + if (!strcmp(pdf_name_value(operator), "assign")) { + handle_assign(dst, src, flag, + gsub_list, ttcmap, unencoded); + } else if (!strcmp(pdf_name_value(operator), "substitute")) { + handle_subst(dst, src, flag, + gsub_list, ttcmap, unencoded); + } + } + + } + + } + +} + +static void CDECL +hval_free (void *hval) +{ + RELEASE(hval); +} + +int +otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */ + const char *otl_tags, int wmode) +{ + int cmap_id = -1; + int tounicode_id = -1, is_cidfont = 0; + sfnt *sfont; + unsigned long offset = 0; + char *base_name = NULL, *cmap_name = NULL; + char *tounicode_name = NULL; + FILE *fp = NULL; + otl_gsub *gsub_list = NULL; + tt_cmap *ttcmap; + CMap *cmap, *base, *tounicode = NULL; + CIDSysInfo csi = {NULL, NULL, 0}; + unsigned char *GIDToCIDMap = NULL; + + if (!map_name) + return -1; + + if (ttc_index > 999 || ttc_index < 0) { + return -1; /* Sorry for this... */ + } + +#ifdef XETEX + fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); + sfont = NULL; /* FIXME */ +#else + fp = DPXFOPEN(map_name, DPX_RES_TYPE_TTFONT); + if (!fp) { + fp = DPXFOPEN(map_name, DPX_RES_TYPE_OTFONT); + } + if (!fp) { + fp = DPXFOPEN(map_name, DPX_RES_TYPE_DFONT); + if (!fp) return -1; + sfont = dfont_open(fp, ttc_index); + } else { + sfont = sfnt_open(fp); + } +#endif + + if (!sfont) { + ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name); + } + switch (sfont->type) { + case SFNT_TYPE_TTC: + offset = ttc_read_offset(sfont, ttc_index); + if (offset == 0) { + ERROR("Invalid TTC index"); + } + break; + case SFNT_TYPE_TRUETYPE: + case SFNT_TYPE_POSTSCRIPT: + offset = 0; + break; + case SFNT_TYPE_DFONT: + offset = sfont->offset; + break; + default: + ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name); + break; + } + + if (sfnt_read_table_directory(sfont, offset) < 0) + ERROR("Could not read OpenType/TrueType table directory."); + + base_name = NEW(strlen(map_name)+strlen("-UCS4-H")+5, char); + if (wmode) + sprintf(base_name, "%s,%03d-UCS4-V", map_name, ttc_index); + else { + sprintf(base_name, "%s,%03d-UCS4-H", map_name, ttc_index); + } + + if (otl_tags) { + cmap_name = NEW(strlen(map_name)+strlen(otl_tags)+strlen("-UCS4-H")+6, char); + if (wmode) + sprintf(cmap_name, "%s,%03d,%s-UCS4-V", map_name, ttc_index, otl_tags); + else + sprintf(cmap_name, "%s,%03d,%s-UCS4-H", map_name, ttc_index, otl_tags); + } else { + cmap_name = NEW(strlen(base_name)+1, char); + strcpy(cmap_name, base_name); + } + + if (sfont->type == SFNT_TYPE_POSTSCRIPT) { + is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi); + } else { + is_cidfont = 0; + } + + if (is_cidfont) { + tounicode_name = NULL; + } else { + tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char); + sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index); + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("\n"); + MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n", + map_name, (otl_tags ? otl_tags : "none")); + } + + cmap_id = CMap_cache_find(cmap_name); + if (cmap_id >= 0) { + RELEASE(cmap_name); + RELEASE(base_name); + if (GIDToCIDMap) + RELEASE(GIDToCIDMap); + if (tounicode_name) + RELEASE(tounicode_name); + + sfnt_close(sfont); + DPXFCLOSE(fp); + + if (verbose > VERBOSE_LEVEL_MIN) + MESG("otf_cmap>> Found at cmap_id=%d.\n", cmap_id); + + return cmap_id; + } + + ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */ + if (!ttcmap) { + 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 OpenType/TrueType cmap table."); + + if (!otl_tags) { + RELEASE(cmap_name); + RELEASE(base_name); + if (GIDToCIDMap) + RELEASE(GIDToCIDMap); + if (tounicode_name) + RELEASE(tounicode_name); + if (is_cidfont) { + if (csi.registry) + RELEASE(csi.registry); + if (csi.ordering) + RELEASE(csi.ordering); + } + tt_cmap_release(ttcmap); + sfnt_close(sfont); + DPXFCLOSE(fp); + + return cmap_id; + } + + base = CMap_cache_get(cmap_id); + + cmap = CMap_new(); + CMap_set_name (cmap, cmap_name); + CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); + CMap_set_wmode(cmap, wmode); + /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */ + CMap_set_usecmap(cmap, base); + CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */ + + if (is_cidfont) { + CMap_set_CIDSysInfo(cmap, &csi); + if (csi.registry) + RELEASE(csi.registry); + if (csi.ordering) + RELEASE(csi.ordering); + } else { + CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); + } + + gsub_list = otl_gsub_new(); + + { + struct ht_table unencoded; + char *conf_name, *opt_tag; + pdf_obj *conf, *opt_conf; + + conf_name = NEW(strlen(otl_tags)+1, char); + memset (conf_name, 0, strlen(otl_tags)+1); + opt_tag = strchr(otl_tags, ':'); + if (opt_tag) { + opt_tag++; + strncpy(conf_name, otl_tags, + strlen(otl_tags) - strlen(opt_tag) - 1); + } else { + strcpy(conf_name, otl_tags); + } + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name); + } + + conf = otl_find_conf(conf_name); + if (!conf) + ERROR("Layout file \"%s\" not found...", conf_name); + + load_gsub(conf, gsub_list, sfont); + if (opt_tag) { + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag); + } + opt_conf = otl_conf_find_opt(conf, opt_tag); + if (!opt_conf) + ERROR("There is no option \"%s\" in \"%s\".", + opt_tag, conf_name); + load_gsub(opt_conf, gsub_list, sfont); + } + + ht_init_table(&unencoded, hval_free); + + handle_gsub(conf, ttcmap, gsub_list, &unencoded); + if (opt_tag) { + opt_conf = otl_conf_find_opt(conf, opt_tag); + if (!opt_conf) + ERROR("There is no option \"%s\" in \"%s\".", + opt_tag, conf_name); + handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded); + } + if (is_cidfont) { + tounicode_id = -1; + tounicode = NULL; + } else { + tounicode_id = CMap_cache_find(tounicode_name); + if (tounicode_id >= 0) + tounicode = CMap_cache_get(tounicode_id); + else { + tounicode = CMap_new(); + CMap_set_name (tounicode, tounicode_name); + CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE); + CMap_set_wmode(tounicode, 0); + CMap_add_codespacerange(tounicode, srange_min, srange_max, 2); + CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE); + /* FIXME */ + CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2); + } + } + create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap); + + ht_clear_table(&unencoded); + RELEASE(conf_name); + } + + cmap_id = CMap_cache_add(cmap); + if (!is_cidfont && tounicode_id < 0) /* New */ + CMap_cache_add(tounicode); + + tt_cmap_release(ttcmap); + if (gsub_list) + otl_gsub_release(gsub_list); + + if (verbose > VERBOSE_LEVEL_MIN) { + MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n", + base_name, cmap_name); + } + + if (GIDToCIDMap) + RELEASE(GIDToCIDMap); + if (base_name) + RELEASE(base_name); + if (cmap_name) + RELEASE(cmap_name); + if (tounicode_name) + RELEASE(tounicode_name); + + sfnt_close(sfont); + DPXFCLOSE(fp); + + return cmap_id; +} diff --git a/Build/source/texk/dvipdfm-x/type1c.c b/Build/source/texk/dvipdfm-x/type1c.c new file mode 100644 index 00000000000..d1895253b59 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/type1c.c @@ -0,0 +1,764 @@ +/* + + This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. + + Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. +*/ + +/* + * CFF/OpenType Font support: + * + * Adobe Technical Note #5176, "The Compact Font Format Specfication" + * + * NOTE: + * + * Many CFF/OpenType does not have meaningful/correct CFF encoding. + * Encoding should be expilicitly supplied in the fontmap. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "system.h" +#include "mem.h" +#include "error.h" + +#include "dpxfile.h" + +#include "pdfobj.h" +#include "pdffont.h" + +#include "pdfencoding.h" +#include "unicode.h" + +/* Font info. from OpenType tables */ +#include "sfnt.h" +#include "tt_aux.h" + +#include "cff_types.h" +#include "cff_limits.h" +#include "cff.h" +#include "cff_dict.h" +#include "cs_type2.h" + +#include "type1c.h" + +#include "tfm.h" + +int +pdf_font_open_type1c (pdf_font *font) +{ + char *fontname; +#ifndef XETEX + char *ident; +#endif + FILE *fp = NULL; + sfnt *sfont; + cff_font *cffont; + pdf_obj *descriptor, *tmp; + unsigned long offset = 0; + int encoding_id, embedding; + + ASSERT(font); + +#ifndef XETEX + ident = +#endif + pdf_font_get_ident (font); + encoding_id = pdf_font_get_encoding(font); + +#ifdef XETEX + sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); + if (!sfont) + return -1; +#else + fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); + if (!fp) + return -1; + + sfont = sfnt_open(fp); +#endif + if (!sfont || + sfont->type != SFNT_TYPE_POSTSCRIPT || + sfnt_read_table_directory(sfont, 0) < 0) { + ERROR("Not a CFF/OpenType font?"); + } + + offset = sfnt_find_table_pos(sfont, "CFF "); + if (offset < 1) { + ERROR("No \"CFF \" table found. Not a CFF/OpenType font?"); + } + +#ifdef XETEX + cffont = cff_open(sfont, offset, 0); +#else + cffont = cff_open(sfont->stream, offset, 0); +#endif + if (!cffont) { + ERROR("Could not read CFF font data"); + } + + if (cffont->flag & FONTTYPE_CIDFONT) { + cff_close (cffont); + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + return -1; + } + + fontname = cff_get_name(cffont); + if (!fontname) { + ERROR("No valid FontName found in CFF/OpenType font."); + } + pdf_font_set_fontname(font, fontname); + RELEASE(fontname); + + cff_close(cffont); + + /* + * Font like AdobePiStd does not have meaningful built-in encoding. + * Some software generate CFF/OpenType font with incorrect encoding. + */ + if (encoding_id < 0) { + WARN("Built-in encoding used for CFF/OpenType font."); + WARN("CFF font in OpenType font sometimes have strange built-in encoding."); + WARN("If you find text is not encoded properly in the generated PDF file,"); + WARN("please specify appropriate \".enc\" file in your fontmap."); + } + pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1C); + + embedding = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1; + descriptor = pdf_font_get_descriptor(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, 1, fontname); + if (!tmp) { + ERROR("Could not obtain neccesary font info from OpenType table."); + return -1; + } + pdf_merge_dict (descriptor, tmp); /* copy */ + pdf_release_obj(tmp); + if (!embedding) { /* tt_get_fontdesc may have changed this */ + pdf_font_set_flags(font, PDF_FONT_FLAG_NOEMBED); + } + + sfnt_close(sfont); + if (fp) + DPXFCLOSE(fp); + + return 0; +} + +static void +add_SimpleMetrics (pdf_font *font, cff_font *cffont, + double *widths, card16 num_glyphs) +{ + pdf_obj *fontdict; + int code, firstchar, lastchar, tfm_id; + char *usedchars; + pdf_obj *tmp_array; + double scaling; + + fontdict = pdf_font_get_resource(font); + usedchars = pdf_font_get_usedchars(font); + + /* The widhts array in the font dictionary must be given relative + * to the default scaling of 1000:1, not relative to the scaling + * given by the font matrix. + */ + if (cff_dict_known(cffont->topdict, "FontMatrix")) + scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0); + else + scaling = 1; + + tmp_array = pdf_new_array(); + if (num_glyphs <= 1) { + /* This should be error. */ + firstchar = lastchar = 0; + pdf_add_array(tmp_array, pdf_new_number(0.0)); + } else { + firstchar = 255; lastchar = 0; + for (code = 0; code < 256; code++) { + if (usedchars[code]) { + if (code < firstchar) firstchar = code; + if (code > lastchar) lastchar = code; + } + } + if (firstchar > lastchar) { + ERROR("No glyphs used at all!"); + pdf_release_obj(tmp_array); + return; + } + tfm_id = tfm_open(pdf_font_get_mapname(font), 0); + for (code = firstchar; code <= lastchar; code++) { + if (usedchars[code]) { + double width; + if (tfm_id < 0) /* tfm is not found */ + width = scaling * widths[code]; + else + width = 1000. * tfm_get_width(tfm_id, code); + pdf_add_array(tmp_array, + pdf_new_number(ROUND(width, 0.1))); + } else { + pdf_add_array(tmp_array, pdf_new_number(0.0)); + } + } + } + + if (pdf_array_length(tmp_array) > 0) { + pdf_add_dict(fontdict, + pdf_new_name("Widths"), pdf_ref_obj(tmp_array)); + } + pdf_release_obj(tmp_array); + + pdf_add_dict(fontdict, + pdf_new_name("FirstChar"), pdf_new_number(firstchar)); + pdf_add_dict(fontdict, + pdf_new_name("LastChar"), pdf_new_number(lastchar)); + + return; +} + +int +pdf_font_load_type1c (pdf_font *font) +{ + pdf_obj *fontdict, *descriptor; + char *usedchars; + char *fontname, *uniqueTag, *ident, *fullname; + FILE *fp = NULL; + int encoding_id; + pdf_obj *fontfile, *stream_dict; + char **enc_vec; + sfnt *sfont; + cff_font *cffont; + cff_index *charstrings, *topdict, *cs_idx; + cff_charsets *charset = NULL; + cff_encoding *encoding = NULL; + long topdict_offset, private_size; + long charstring_len, max_len; + long size, offset = 0; + long stream_data_len = 0; + card8 *stream_data_ptr, *data; + card16 num_glyphs, cs_count, code; + cs_ginfo ginfo; + double nominal_width, default_width, notdef_width; + double widths[256]; + int verbose; + + ASSERT(font); + + verbose = pdf_font_get_verbose(); + + if (!pdf_font_is_in_use(font)) { + return 0; + } + + if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { + ERROR("Only embedded font supported for CFF/OpenType font."); + } + + usedchars = pdf_font_get_usedchars (font); + fontname = pdf_font_get_fontname (font); + ident = pdf_font_get_ident (font); + uniqueTag = pdf_font_get_uniqueTag (font); + if (!usedchars || + !fontname || !ident) { + ERROR("Unexpected error...."); + } + + fontdict = pdf_font_get_resource (font); + descriptor = pdf_font_get_descriptor(font); + encoding_id = pdf_font_get_encoding (font); + +#ifdef XETEX + sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); +#else + fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); + if (!fp) { + ERROR("Could not open OpenType font: %s", ident); + } + + sfont = sfnt_open(fp); +#endif + if (!sfont) { + ERROR("Could not open OpenType font: %s", ident); + } + if (sfnt_read_table_directory(sfont, 0) < 0) { + ERROR("Could not read OpenType table directory: %s", ident); + } + if (sfont->type != SFNT_TYPE_POSTSCRIPT || + (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { + ERROR("Not a CFF/OpenType font ?"); + } + +#ifdef XETEX + cffont = cff_open(sfont, offset, 0); +#else + cffont = cff_open(fp, offset, 0); +#endif + if (!cffont) { + ERROR("Could not open CFF font."); + } + if (cffont->flag & FONTTYPE_CIDFONT) { + ERROR("This is CIDFont..."); + } + + fullname = NEW(strlen(fontname) + 8, char); + sprintf(fullname, "%6s+%s", uniqueTag, fontname); + + /* Offsets from DICTs */ + cff_read_charsets(cffont); + if (encoding_id < 0) + cff_read_encoding(cffont); + cff_read_private(cffont); + cff_read_subrs (cffont); + + /* FIXME */ + cffont->_string = cff_new_index(0); + + /* New Charsets data */ + charset = NEW(1, cff_charsets); + charset->format = 0; + charset->num_entries = 0; + charset->data.glyphs = NEW(256, s_SID); + + /* + * Encoding related things. + */ + enc_vec = NULL; + if (encoding_id >= 0) { + enc_vec = pdf_encoding_get_encoding(encoding_id); + } else { + pdf_obj *tounicode; + + /* + * Create enc_vec and ToUnicode CMap for built-in encoding. + */ + enc_vec = NEW(256, char *); + for (code = 0; code < 256; code++) { + if (usedchars[code]) { + card16 gid; + + gid = cff_encoding_lookup(cffont, code); + enc_vec[code] = cff_get_string(cffont, + cff_charsets_lookup_inverse(cffont, gid)); + } else { + enc_vec[code] = NULL; + } + } + if (!pdf_lookup_dict(fontdict, "ToUnicode")) { + tounicode = pdf_create_ToUnicode_CMap(fullname, + enc_vec, usedchars); + if (tounicode) { + pdf_add_dict(fontdict, + pdf_new_name("ToUnicode"), + pdf_ref_obj (tounicode)); + pdf_release_obj(tounicode); + } + } + } + + /* + * New Encoding data: + * + * We should not use format 0 here. + * The number of encoded glyphs (num_entries) is limited to 255 in format 0, + * and hence it causes problem for encodings that uses full 256 code-points. + * As we always sort glyphs by encoding, we can avoid this problem simply + * by using format 1; Using full range result in a single range, 0 255. + * + * Creating actual encoding date is delayed to eliminate character codes to + * be mapped to .notdef and to handle multiply-encoded glyphs. + */ + encoding = NEW(1, cff_encoding); + encoding->format = 1; + encoding->num_entries = 0; + encoding->data.range1 = NEW(255, cff_range1); + encoding->num_supps = 0; + encoding->supp = NEW(255, cff_map); + + /* + * Charastrings. + */ + offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); + cff_seek_set(cffont, offset); + cs_idx = cff_get_index_header(cffont); + + /* Offset is now absolute offset ... fixme */ + offset = cff_tell(cffont); + cs_count = cs_idx->count; + if (cs_count < 2) { + ERROR("No valid charstring data found."); + } + + /* New CharStrings INDEX */ + charstrings = cff_new_index(257); /* 256 + 1 for ".notdef" glyph */ + max_len = 2 * CS_STR_LEN_MAX; + charstrings->data = NEW(max_len, card8); + charstring_len = 0; + + /* + * Information from OpenType table is rough estimate. Replace with accurate value. + */ + if (cffont->private[0] && + cff_dict_known(cffont->private[0], "StdVW")) { + double stemv; + + stemv = cff_dict_get(cffont->private[0], "StdVW", 0); + pdf_add_dict(descriptor, + pdf_new_name("StemV"), pdf_new_number(stemv)); + } + + /* + * Widths + */ + if (cffont->private[0] && + cff_dict_known(cffont->private[0], "defaultWidthX")) { + default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); + } else { + default_width = CFF_DEFAULTWIDTHX_DEFAULT; + } + if (cffont->private[0] && + cff_dict_known(cffont->private[0], "nominalWidthX")) { + nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); + } else { + nominal_width = CFF_NOMINALWIDTHX_DEFAULT; + } + + data = NEW(CS_STR_LEN_MAX, card8); + + /* First we add .notdef glyph. + * All Type 1 font requires .notdef glyph to be present. + */ + if (verbose > 2) { + MESG("[glyphs:/.notdef"); + } + size = cs_idx->offset[1] - cs_idx->offset[0]; + if (size > CS_STR_LEN_MAX) { + ERROR("Charstring too long: gid=%u, %ld bytes", 0, size); + } + charstrings->offset[0] = charstring_len + 1; + cff_seek(cffont, offset + cs_idx->offset[0] - 1); + cff_read_data(data, size, cffont); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, cffont->subrs[0], + default_width, nominal_width, &ginfo); + notdef_width = ginfo.wx; + + /* + * Subset font + */ + num_glyphs = 1; + for (code = 0; code < 256; code++) { + card16 gid, j; + s_SID sid_orig, sid; + + widths[code] = notdef_width; + + if (!usedchars[code] || !enc_vec[code] || + !strcmp(enc_vec[code], ".notdef")) + continue; + + /* + * FIXME: + * cff_get_sid() obtain SID from original String INDEX. + * It should be cff_string_get_sid(string, ...). + * cff_add_string(cff, ...) -> cff_string_add(string, ...). + */ + sid_orig = cff_get_sid (cffont, enc_vec[code]); + sid = sid_orig < CFF_STDSTR_MAX ? + sid_orig : cff_add_string(cffont, enc_vec[code], 0); + /* + * We use "unique = 0" because duplicate strings are impossible + * at this stage unless the original font already had duplicates. + */ + + /* + * Check if multiply-encoded glyph. + */ + for (j = 0; j < charset->num_entries; j++) { + if (sid == charset->data.glyphs[j]) { + /* Already have this glyph. */ + encoding->supp[encoding->num_supps].code = code; + encoding->supp[encoding->num_supps].glyph = sid; + usedchars[code] = 0; /* Used but multiply-encoded. */ + encoding->num_supps += 1; + break; + } + } + if (j < charset->num_entries) { + continue; /* Prevent duplication. */ + } + + /* This is new encoding entry. */ + gid = cff_charsets_lookup(cffont, sid_orig); /* FIXME */ + if (gid == 0) { + WARN("Glyph \"%s\" missing in font \"%s\".", enc_vec[code], fontname); + WARN("Maybe incorrect encoding specified."); + usedchars[code] = 0; /* Set unused for writing correct encoding */ + continue; + } + if (verbose > 2) { + MESG("/%s", enc_vec[code]); + } + + size = cs_idx->offset[gid+1] - cs_idx->offset[gid]; + if (size > CS_STR_LEN_MAX) { + ERROR("Charstring too long: gid=%u, %ld bytes", gid, size); + } + + if (charstring_len + CS_STR_LEN_MAX >= max_len) { + max_len = charstring_len + 2 * CS_STR_LEN_MAX; + charstrings->data = RENEW(charstrings->data, max_len, card8); + } + charstrings->offset[num_glyphs] = charstring_len + 1; + cff_seek(cffont, offset + cs_idx->offset[gid] - 1); + cff_read_data(data, size, cffont); + charstring_len += cs_copy_charstring(charstrings->data + charstring_len, + max_len - charstring_len, + data, size, + cffont->gsubr, cffont->subrs[0], + default_width, nominal_width, &ginfo); + widths[code] = ginfo.wx; + charset->data.glyphs[charset->num_entries] = sid; + charset->num_entries += 1; + num_glyphs++; + } + if (verbose > 2) { + MESG("]"); + } + RELEASE(data); + + /* + * Now we create encoding data. + */ + if (encoding->num_supps > 0) + encoding->format |= 0x80; /* Have supplemantary data. */ + else { + RELEASE(encoding->supp); /* FIXME */ + } + for (code = 0; code < 256; code++) { + if (!usedchars[code] || + !enc_vec[code] || !strcmp(enc_vec[code], ".notdef")) + continue; + encoding->data.range1[encoding->num_entries].first = code; + encoding->data.range1[encoding->num_entries].n_left = 0; + code++; + while (code < 256 && usedchars[code] && + enc_vec[code] && strcmp(enc_vec[code], ".notdef")) { + encoding->data.range1[encoding->num_entries].n_left += 1; + code++; + } + encoding->num_entries += 1; + /* The above while() loop stopped at unused char or code == 256. */ + } + + /* cleanup */ + if (encoding_id < 0 && enc_vec) { + for (code = 0; code < 256; code++) { + if (enc_vec[code]) { + RELEASE(enc_vec[code]); + } + } + RELEASE(enc_vec); + } + + cff_release_index(cs_idx); + + charstrings->offset[num_glyphs] = charstring_len + 1; + charstrings->count = num_glyphs; + charstring_len = cff_index_size(charstrings); + cffont->num_glyphs = num_glyphs; + + /* + * Discard old one, set new data. + */ + if (cffont->charsets) + cff_release_charsets(cffont->charsets); + cffont->charsets = charset; + if (cffont->encoding) + cff_release_encoding(cffont->encoding); + cffont->encoding = encoding; + /* + * We don't use subroutines at all. + */ + if (cffont->gsubr) + cff_release_index(cffont->gsubr); + cffont->gsubr = cff_new_index(0); + if (cffont->subrs[0]) + cff_release_index(cffont->subrs[0]); + cffont->subrs[0] = NULL; + + /* + * Flag must be reset since cff_pack_encoding(charset) does not write + * encoding(charset) if HAVE_STANDARD_ENCODING(CHARSET) is set. We are + * re-encoding font. + */ + cffont->flag = FONTTYPE_FONT; + + /* + * FIXME: + * Update String INDEX to delete unused strings. + */ + cff_dict_update(cffont->topdict, cffont); + if (cffont->private[0]) + cff_dict_update(cffont->private[0], cffont); + cff_update_string(cffont); + + /* + * Calculate sizes of Top DICT and Private DICT. + * All offset values in DICT are set to long (32-bit) integer + * in cff_dict_pack(), those values are updated later. + */ + topdict = cff_new_index(1); + + cff_dict_remove(cffont->topdict, "UniqueID"); + cff_dict_remove(cffont->topdict, "XUID"); + + /* + * Force existence of Encoding. + */ + if (!cff_dict_known(cffont->topdict, "Encoding")) + cff_dict_add(cffont->topdict, "Encoding", 1); + topdict->offset[1] = cff_dict_pack(cffont->topdict, + (card8 *) work_buffer, + WORK_BUFFER_SIZE) + 1; + private_size = 0; + if (cffont->private[0]) { + cff_dict_remove(cffont->private[0], "Subrs"); /* no Subrs */ + private_size = cff_dict_pack(cffont->private[0], + (card8 *) work_buffer, WORK_BUFFER_SIZE); + } + + /* + * Estimate total size of fontfile. + */ + stream_data_len = 4; /* header size */ + + stream_data_len += cff_set_name(cffont, fullname); + RELEASE(fullname); + + stream_data_len += cff_index_size(topdict); + stream_data_len += cff_index_size(cffont->string); + stream_data_len += cff_index_size(cffont->gsubr); + + /* We are using format 1 for Encoding and format 0 for charset. + * TODO: Should implement cff_xxx_size(). + */ + stream_data_len += 2 + (encoding->num_entries)*2 + 1 + (encoding->num_supps)*3; + stream_data_len += 1 + (charset->num_entries)*2; + stream_data_len += charstring_len; + stream_data_len += private_size; + + /* + * Now we create FontFile data. + */ + stream_data_ptr = NEW(stream_data_len, card8); + + /* + * Data Layout order as described in CFF spec., sec 2 "Data Layout". + */ + offset = 0; + /* Header */ + offset += cff_put_header(cffont, stream_data_ptr + offset, stream_data_len - offset); + /* Name */ + offset += cff_pack_index(cffont->name, stream_data_ptr + offset, stream_data_len - offset); + /* Top DICT */ + topdict_offset = offset; + offset += cff_index_size(topdict); + /* Strings */ + offset += cff_pack_index(cffont->string, + stream_data_ptr + offset, stream_data_len - offset); + /* Global Subrs */ + offset += cff_pack_index(cffont->gsubr, + stream_data_ptr + offset, stream_data_len - offset); + /* Encoding */ + cff_dict_set(cffont->topdict, "Encoding", 0, offset); + offset += cff_pack_encoding(cffont, + stream_data_ptr + offset, stream_data_len - offset); + /* charset */ + cff_dict_set(cffont->topdict, "charset", 0, offset); + offset += cff_pack_charsets(cffont, + stream_data_ptr + offset, stream_data_len - offset); + /* CharStrings */ + cff_dict_set(cffont->topdict, "CharStrings", 0, offset); + offset += cff_pack_index(charstrings, + stream_data_ptr + offset, charstring_len); + cff_release_index(charstrings); + /* Private */ + cff_dict_set(cffont->topdict, "Private", 1, offset); + if (cffont->private[0] && private_size > 0) + private_size = cff_dict_pack(cffont->private[0], + stream_data_ptr + offset, private_size); + cff_dict_set(cffont->topdict, "Private", 0, private_size); + offset += private_size; + + /* Finally Top DICT */ + topdict->data = NEW(topdict->offset[1] - 1, card8); + cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1); + cff_pack_index(topdict, + stream_data_ptr + topdict_offset, cff_index_size(topdict)); + cff_release_index(topdict); + + /* Copyright and Trademark Notice ommited. */ + + /* Handle Widths in fontdict. */ + add_SimpleMetrics(font, cffont, widths, num_glyphs); + + /* Close font */ + cff_close (cffont); + sfnt_close(sfont); + + if (fp) + DPXFCLOSE(fp); + + if (verbose > 1) { + MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, offset); + } + + /* + * CharSet might be recommended for subsetted font, but it is meaningful + * only for Type 1 font... + */ + + /* + * Write PDF FontFile data. + */ + fontfile = pdf_new_stream(STREAM_COMPRESS); + stream_dict = pdf_stream_dict(fontfile); + pdf_add_dict(descriptor, + pdf_new_name("FontFile3"), pdf_ref_obj (fontfile)); + pdf_add_dict(stream_dict, + pdf_new_name("Subtype"), pdf_new_name("Type1C")); + pdf_add_stream (fontfile, (void *) stream_data_ptr, offset); + pdf_release_obj(fontfile); + + RELEASE(stream_data_ptr); + + return 0; +} diff --git a/Build/source/texk/dvipdfm-x/vf.c b/Build/source/texk/dvipdfm-x/vf.c index b1f6b1d471b..a03c921cf68 100644 --- a/Build/source/texk/dvipdfm-x/vf.c +++ b/Build/source/texk/dvipdfm-x/vf.c @@ -38,6 +38,7 @@ #include "tfm.h" #include "dvi.h" #include "vf.h" +#include "dvipdfmx.h" #include "dvicodes.h" @@ -198,13 +199,6 @@ static void read_a_font_def(FILE *vf_file, signed long font_id, int thisfont) return; } -#ifdef XETEX -#define MAX_BITS 16 -#else -#define MAX_BITS 24 -#endif - - static void process_vf_file (FILE *vf_file, int thisfont) { int eof = 0, code; @@ -244,12 +238,12 @@ static void process_vf_file (FILE *vf_file, int thisfont) ch = get_unsigned_quad (vf_file); /* Skip over TFM width since we already know it */ get_unsigned_quad (vf_file); - if (ch < (1UL << MAX_BITS)) + if (ch < (is_xetex ? 0x10000UL : 0x1000000UL)) read_a_char_def (vf_file, thisfont, pkt_len, ch); else { fprintf (stderr, "char=%ld\n", ch); - ERROR ("Long character (>%d bits) in VF file.\nI can't handle long characters!\n", - MAX_BITS); + ERROR ("Long character (>%s bits) in VF file.\nI can't handle long characters!\n", + is_xetex ? "16" : "24"); } break; } @@ -462,13 +456,11 @@ static void vf_set2(unsigned char **start, unsigned char *end) return; } -#ifndef XETEX static void vf_set3(unsigned char **start, unsigned char *end) { vf_set (unsigned_triple(start, end)); return; } -#endif static void vf_putrule(unsigned char **start, unsigned char *end, spt_t ptsize) { @@ -506,13 +498,11 @@ static void vf_put2(unsigned char **start, unsigned char *end) return; } -#ifndef XETEX static void vf_put3(unsigned char **start, unsigned char *end) { dvi_put (unsigned_triple(start, end)); return; } -#endif static void vf_push(void) { @@ -874,13 +864,13 @@ void vf_set_char(SIGNED_QUAD ch, int vf_font) vf_set2(&start, end); break; case SET3: -#ifndef XETEX - vf_set3(&start, end); - break; -#endif + if (!is_xetex) { + vf_set3(&start, end); + break; + } case SET4: - ERROR ("Multibyte (>%d bits) character in VF packet.\nI can't handle this!", - MAX_BITS); + ERROR ("Multibyte (>%s bits) character in VF packet.\nI can't handle this!", + is_xetex ? "16" : "24"); break; case SET_RULE: vf_setrule(&start, end, ptsize); @@ -892,13 +882,13 @@ void vf_set_char(SIGNED_QUAD ch, int vf_font) vf_put2(&start, end); break; case PUT3: -#ifndef XETEX - vf_put3(&start, end); - break; -#endif + if (!is_xetex) { + vf_put3(&start, end); + break; + } case PUT4: - ERROR ("Multibyte (>%d bits) character in VF packet.\nI can't handle this!", - MAX_BITS); + ERROR ("Multibyte (>%s bits) character in VF packet.\nI can't handle this!", + is_xetex ? "16" : "24"); break; case PUT_RULE: vf_putrule(&start, end, ptsize); diff --git a/Build/source/texk/dvipdfm-x/xbb.c b/Build/source/texk/dvipdfm-x/xbb.c new file mode 100644 index 00000000000..411048a09f2 --- /dev/null +++ b/Build/source/texk/dvipdfm-x/xbb.c @@ -0,0 +1,461 @@ +/* + + This is extractbb, a bounding box extraction program. + + Copyright (C) 2008-2013 by Jin-Hwan Cho and Matthias Franz + + 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 +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "numbers.h" +#include "system.h" +#include "mem.h" +#include "error.h" +#include "mfileio.h" +#include "pdfobj.h" +#include "pdfdoc.h" +#include "pdfparse.h" + +#include "config.h" + +#include "jpegimage.h" +#include "pngimage.h" + +#include "dvipdfmx.h" + +#define XBB_PROGRAM "extractbb" +#define XBB_VERSION VERSION + +static void show_version(void) +{ + fprintf (stdout, "\nThis is " XBB_PROGRAM " Version " XBB_VERSION "\n"); + fprintf (stdout, "A bounding box extraction utility from PDF, PNG, and JPEG.\n"); + fprintf (stdout, "\nCopyright (C) 2008-2013 by Jin-Hwan Cho and Matthias Franz\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"); + fprintf (stdout, "(at your option) any later version.\n"); +} + +static void show_usage(void) +{ + fprintf (stdout, "\nUsage: " XBB_PROGRAM " [-q|-v] [-O] [-m|-x] file...\n"); + fprintf (stdout, " " XBB_PROGRAM " --help|--version\n"); + fprintf (stdout, "\nOptions:\n"); + fprintf (stdout, " -h | --help\tShow this help message and exit\n"); + fprintf (stdout, " --version\tOutput version information and exit\n"); + fprintf (stdout, " -q\t\tBe quiet\n"); + fprintf (stdout, " -v\t\tBe verbose\n"); + fprintf (stdout, " -O\t\tWrite output to stdout\n"); + fprintf (stdout, " -m\t\tOutput .bb file used in DVIPDFM%s\n", compat_mode ? " (default)" : ""); + fprintf (stdout, " -x\t\tOutput .xbb file used in DVIPDFMx%s\n", compat_mode ? "" : " (default)"); +} + +static void usage(void) +{ + fprintf(stdout, "\nTry \"" XBB_PROGRAM " --help\" for more information.\n"); + exit(1); +} + +static char verbose = 0; + +static void do_time(FILE *file) +{ + time_t current_time; + struct tm *bd_time; + + time(¤t_time); + bd_time = localtime(¤t_time); + fprintf(file, "%%%%CreationDate: %s\n", asctime(bd_time)); +} + +const char *extensions[] = { + ".jpeg", ".JPEG", ".jpg", ".JPG", ".pdf", ".PDF", ".png", ".PNG" +}; + +static int xbb_to_file = 1; + +static char *make_xbb_filename(const char *name) +{ + int i; + char *result; + + for (i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) { + if (strlen(extensions[i]) < strlen(name) && + strncmp(name+strlen(name)-strlen(extensions[i]), extensions[i], strlen(extensions[i])) == 0) + break; + } + if (i == sizeof(extensions) / sizeof(extensions[0])) { + WARN("%s: Filename does not end in a recognizable extension.\n", name); + result = NEW(strlen(name)+5, char); /* 5 = ".xbb" + trailing 0 */ + strcpy(result, name); + } else { /* Remove extension */ + result = NEW(strlen(name)-strlen(extensions[i])+5, char); /* 5 = ".xbb" + trailing 0 */ + strncpy(result, name, strlen(name)-strlen(extensions[i])); + result[strlen(name)-strlen(extensions[i])] = 0; + } + strcat(result, (compat_mode ? ".bb" : ".xbb")); + return result; +} + +static void write_xbb(char *fname, + double bbllx_f, double bblly_f, + double bburx_f, double bbury_f, + int pdf_version, long pagecount) +{ + char *outname = NULL; + FILE *fp; + + long bbllx = ROUND(bbllx_f, 1.0), bblly = ROUND(bblly_f, 1.0); + long bburx = ROUND(bburx_f, 1.0), bbury = ROUND(bbury_f, 1.0); + + if (xbb_to_file) { + outname = make_xbb_filename(fname); + if ((fp = MFOPEN(outname, FOPEN_W_MODE)) == NULL) { + ERROR("Unable to open output file: %s\n", outname); + } + } else { + fp = stdout; +#ifdef WIN32 + setmode(fileno(fp), _O_BINARY); +#endif + } + + if (verbose) { + MESG("Writing to %s: ", xbb_to_file ? outname : "stdout"); + MESG("Bounding box: %d %d %d %d\n", bbllx, bblly, bburx, bbury); + } + + fprintf(fp, "%%%%Title: %s\n", fname); + fprintf(fp, "%%%%Creator: %s %s\n", XBB_PROGRAM, XBB_VERSION); + fprintf(fp, "%%%%BoundingBox: %ld %ld %ld %ld\n", bbllx, bblly, bburx, bbury); + + if (!compat_mode) { + /* Note: + * According to Adobe Technical Note #5644, the arguments to + * "%%HiResBoundingBox:" must be of type real. And according + * to the PostScript Language Reference, a real number must + * be written with a decimal point (or an exponent). Hence + * it seems illegal to replace "0.0" by "0". + */ + fprintf(fp, "%%%%HiResBoundingBox: %f %f %f %f\n", + bbllx_f, bblly_f, bburx_f, bbury_f); + if (pdf_version >= 0) { + fprintf(fp, "%%%%PDFVersion: 1.%d\n", pdf_version); + fprintf(fp, "%%%%Pages: %ld\n", pagecount); + } + } + + do_time(fp); + + if (xbb_to_file) { + RELEASE(outname); + MFCLOSE(fp); + } +} + +static void do_jpeg (FILE *fp, char *filename) +{ + long width, height; + double xdensity, ydensity; + + if (jpeg_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { + WARN("%s does not look like a JPEG file...\n", filename); + return; + } + + write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); + return; +} + +#ifdef HAVE_LIBPNG +static void do_png (FILE *fp, char *filename) +{ + long width, height; + double xdensity, ydensity; + + if (png_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { + WARN("%s does not look like a PNG file...\n", filename); + return; + } + + write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); + return; +} +#endif /* HAVE_LIBPNG */ + +#ifdef XETEX +static int rect_equal (pdf_obj *rect1, pdf_obj *rect2) +{ + int i; + if (!rect1 || !rect2) return 0; + for (i = 0; i < 4; i++) { + if (pdf_number_value(pdf_get_array(rect1, i)) != pdf_number_value(pdf_get_array(rect2, i))) return 0; + } + return 1; +} + +static int pdf_get_info (FILE *image_file, char *filename, int *version, + double *llx, double *lly, double *urx, double *ury) +{ + pdf_obj *page_tree; + pdf_obj *bbox; + pdf_file *pf; + + page_tree = NULL; + { + pdf_obj *trailer, *catalog; + + pf = pdf_open(filename, image_file); + if (!pf) + return -1; + + trailer = pdf_file_get_trailer(pf); + + if (pdf_lookup_dict(trailer, "Encrypt")) { + WARN("This PDF document is encrypted."); + pdf_release_obj(trailer); + pdf_close(pf); + return -1; + } + catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); + if (!catalog) { + WARN("Catalog isn't where I expect it."); + pdf_close(pf); + return -1; + } + pdf_release_obj(trailer); + page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); + pdf_release_obj(catalog); + } + if (!page_tree) { + WARN("Page tree not found."); + pdf_close(pf); + return -1; + } + { + pdf_obj *kids_ref, *kids; + pdf_obj *crop_box; + 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; + + while ((kids_ref = pdf_lookup_dict(page_tree, "Kids")) != NULL) { + kids = pdf_deref_obj(kids_ref); + pdf_release_obj(page_tree); + page_tree = pdf_deref_obj(pdf_get_array(kids, 0)); + pdf_release_obj(kids); + + 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; + } else + pdf_release_obj(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; + } else + pdf_release_obj(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; + } else + pdf_release_obj(tmp); + } + if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { + if (crop_box) + pdf_release_obj(crop_box); + crop_box = tmp; + } + } + if (crop_box) { + pdf_release_obj(bbox); + bbox = crop_box; + } + } + pdf_release_obj(page_tree); + + if (!bbox) { + WARN("No BoundingBox information available."); + pdf_close(pf); + return -1; + } + + *version = pdf_file_get_version(pf); + + *llx = pdf_number_value(pdf_get_array(bbox, 0)); + *lly = pdf_number_value(pdf_get_array(bbox, 1)); + *urx = pdf_number_value(pdf_get_array(bbox, 2)); + *ury = pdf_number_value(pdf_get_array(bbox, 3)); + + pdf_release_obj(bbox); + + pdf_close(pf); + return 0; +} + +static void do_pdf (FILE *fp, char *filename) +{ + double llx, lly, urx, ury; + int version; + + if (pdf_get_info(fp, filename, &version, &llx, &lly, &urx, &ury) < 0) { + fprintf (stderr, "%s does not look like a PDF file...\n", filename); + return; + } + write_xbb(filename, llx, lly, urx, ury, version, 1); + return; +} +#else +static void do_pdf (FILE *fp, char *filename) +{ + pdf_obj *page; + pdf_file *pf; + long page_no = 1; + long count; + pdf_rect bbox; + + pf = pdf_open(filename, fp); + if (!pf) { + WARN("%s does not look like a PDF file...\n", filename); + return; + } + + page = pdf_doc_get_page(pf, page_no, &count, &bbox, NULL); + + pdf_close(pf); + + if (!page) + return; + + pdf_release_obj(page); + write_xbb(filename, bbox.llx, bbox.lly, bbox.urx, bbox.ury, + pdf_file_get_version(pf), count); +} +#endif + +int extractbb (int argc, char *argv[]) +{ + pdf_files_init(); + + pdf_set_version(5); + + argc -= 1; argv += 1; + + while (argc > 0 && *argv[0] == '-') { + char *flag; + + for (flag = argv[0] + 1; *flag != 0; flag++) { + switch (*flag) { + case '-': + if (flag == argv[0] + 1 && ++flag) { + if (!strcmp(flag, "help")) { + show_usage(); + exit(0); + } else if (!strcmp(flag, "version")) { + show_version(); + exit(0); + } + } + fprintf(stderr, "Unknown option \"%s\"", argv[0]); + usage(); + case 'O': + xbb_to_file = 0; + break; + case 'b': /* Ignored for backward compatibility */ + break; + case 'm': + compat_mode = 1; + break; + case 'x': + compat_mode = 0; + break; + case 'v': + verbose = 1; + break; + case 'h': + show_usage(); + exit (0); + default: + fprintf (stderr, "Unknown option in \"%s\"", argv[0]); + usage(); + } + } + argc -= 1; argv += 1; + } + + if (argc == 0) { + fprintf (stderr, "Missing filename argument\n"); + usage(); + } + + for (; argc > 0; argc--, argv++) { + FILE *infile = NULL; + char *kpse_file_name; + if (!(kpse_file_name = kpse_find_pict(argv[0])) || + (infile = MFOPEN(kpse_file_name, FOPEN_RBIN_MODE)) == NULL) { + WARN("Can't find file (%s)...skipping\n", argv[0]); + goto cont; + } + if (check_for_jpeg(infile)) { + do_jpeg(infile, kpse_file_name); + goto cont; + } + if (check_for_pdf(infile)) { + do_pdf(infile, kpse_file_name); + goto cont; + } +#ifdef HAVE_LIBPNG + if (check_for_png(infile)) { + do_png(infile, kpse_file_name); + goto cont; + } +#endif /* HAVE_LIBPNG */ + WARN("Can't handle file type for file named %s\n", argv[0]); + cont: + if (kpse_file_name) + RELEASE(kpse_file_name); + if (infile) + MFCLOSE(infile); + } + + pdf_files_close(); + + return 0; +} diff --git a/Build/source/texk/dvipdfm-x/xdvipdfm-bb.test b/Build/source/texk/dvipdfm-x/xdvipdfm-bb.test index 0914438d58f..77756d36931 100755 --- a/Build/source/texk/dvipdfm-x/xdvipdfm-bb.test +++ b/Build/source/texk/dvipdfm-x/xdvipdfm-bb.test @@ -17,8 +17,14 @@ for e in jpeg png pdf; do cp $testsrc/image.$e pic$e.$e done -./xdvipdfmx --ebb -h \ - && echo "ebb-help tests OK" \ +echo "*** xdvipdfmx --ebb --version" \ + && ./xdvipdfmx --ebb --version \ + && echo "ebb-version tests OK" && echo \ + || failed="$failed ebb-version" + +echo "*** xdvipdfmx --ebb --help" \ + && ./xdvipdfmx --ebb --help \ + && echo "ebb-help tests OK" && echo \ || failed="$failed ebb-help" for e in jpeg png pdf; do @@ -29,8 +35,14 @@ for e in jpeg png pdf; do || failed="$failed ebb-$e" done -./xdvipdfmx --xbb -h \ - && echo "xbb-help tests OK" \ +echo "*** xdvipdfmx --xbb --version" \ + && ./xdvipdfmx --xbb --version \ + && echo "xbb-version tests OK" && echo \ + || failed="$failed xbb-version" + +echo "*** xdvipdfmx --xbb --help" \ + && ./xdvipdfmx --xbb --help \ + && echo "xbb-help tests OK" && echo \ || failed="$failed xbb-help" for e in jpeg png pdf; do diff --git a/Build/source/texk/dvipdfm-x/xdvipdfmx.test b/Build/source/texk/dvipdfm-x/xdvipdfmx.test index d564977c2b4..0facea9c040 100755 --- a/Build/source/texk/dvipdfm-x/xdvipdfmx.test +++ b/Build/source/texk/dvipdfm-x/xdvipdfmx.test @@ -5,7 +5,23 @@ # Not really a test, just making sure the program executes. -TEXMFCNF=${srcdir}/../kpathsea \ - DVIPDFMXINPUTS=${srcdir}/tests:${srcdir}/data \ - ./xdvipdfmx -h || exit 1 +TEXMFCNF=${srcdir}/../kpathsea +DVIPDFMXINPUTS=${srcdir}/tests:${srcdir}/data +export TEXMFCNF DVIPDFMXINPUTS + +failed= + +echo "*** xdvipdfmx --version" \ + && ./xdvipdfmx --version \ + && echo "xdvipdfmx-version tests OK" && echo \ + || failed="$failed xdvipdfmx-version" + +echo "*** xdvipdfmx --help" \ + && ./xdvipdfmx --help \ + && echo "xdvipdfmx-help tests OK" && echo \ + || failed="$failed xdvipdfmx-help" + +test -z "$failed" && exit 0 +echo "failed tests:$failed" +exit 1 diff --git a/Build/source/texk/dvipdfm-x/xsrc/cidtype0.c b/Build/source/texk/dvipdfm-x/xsrc/cidtype0.c deleted file mode 100644 index de8f0deac34..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/cidtype0.c +++ /dev/null @@ -1,2076 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - 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. -*/ - -/* - * CID-Keyed Font support: - * - * Only CFF/OpenType CID-Keyed Font with Type 2 charstrings is supported. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "numbers.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfobj.h" -/* pseudo unique tag */ -#include "pdffont.h" - -/* Font info. from OpenType tables */ -#include "sfnt.h" -#include "tt_aux.h" -/* Metrics */ -#include "tt_table.h" - -#include "cff_types.h" -#include "cff_limits.h" -#include "cff.h" -#include "cff_dict.h" -#include "cs_type2.h" - -/* typedef CID in cmap.h */ -#include "cmap.h" -#include "type0.h" -#include "cid.h" -#include "cid_p.h" -#include "cidtype0.h" - -static int verbose = 0; -static long opt_flags = 0; - -void -CIDFont_type0_set_verbose (void) -{ - verbose++; -} - -void -CIDFont_type0_set_flags (long flags) -{ - opt_flags = flags; -} - -/* - * PDF Reference 3rd. ed., p.340, "Glyph Metrics in CID Fonts". - */ -#ifndef PDFUNIT -#define PDFUNIT(v) (ROUND((1000.0*(v))/(head->unitsPerEm),1)) -#endif - -static void -add_CIDHMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, - struct tt_maxp_table *maxp, - struct tt_head_table *head, struct tt_longMetrics *hmtx) -{ - pdf_obj *w_array, *an_array = NULL; - long cid, start = 0, prev = 0; - double defaultAdvanceWidth; - int empty = 1; - - defaultAdvanceWidth = PDFUNIT(hmtx[0].advance); - /* - * We alway use format: - * c [w_1 w_2 ... w_n] - */ - w_array = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - USHORT gid; - double advanceWidth; - gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; - if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) - continue; - advanceWidth = PDFUNIT(hmtx[gid].advance); - if (advanceWidth == defaultAdvanceWidth) { - if (an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - an_array = NULL; - empty = 0; - } - } else { - if (cid != prev + 1 && an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - an_array = NULL; - empty = 0; - } - if (an_array == NULL) { - an_array = pdf_new_array(); - start = cid; - } - pdf_add_array(an_array, pdf_new_number(advanceWidth)); - prev = cid; - } - } - - if (an_array) { - pdf_add_array(w_array, pdf_new_number(start)); - pdf_add_array(w_array, an_array); - empty = 0; - } - - /* - * We always write DW for older MacOS X's preview app. - * PDF Reference 2nd. ed, wrongly described default value of DW as 0, and - * MacOS X's (up to 10.2.8) preview app. implements this wrong description. - */ - pdf_add_dict(fontdict, - pdf_new_name("DW"), - pdf_new_number(defaultAdvanceWidth)); - if (!empty) { - pdf_add_dict(fontdict, - pdf_new_name("W"), - pdf_ref_obj(w_array)); - } - pdf_release_obj(w_array); - - return; -} - -static void -add_CIDVMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, - struct tt_maxp_table *maxp, - struct tt_head_table *head, struct tt_longMetrics *hmtx) -{ - pdf_obj *w2_array, *an_array = NULL; - long cid; -#if 0 - long prev = 0, start = 0; -#endif - struct tt_VORG_table *vorg; - struct tt_vhea_table *vhea = NULL; - struct tt_longMetrics *vmtx = NULL; - double defaultAdvanceHeight, defaultVertOriginY; - int empty = 1; - - /* - * No accurate vertical metrics can be obtained by simple way if the - * font does not have VORG table. Only CJK fonts may have VORG. - */ - if (sfnt_find_table_pos(sfont, "VORG") <= 0) - return; - - vorg = tt_read_VORG_table(sfont); - defaultVertOriginY = PDFUNIT(vorg->defaultVertOriginY); - if (sfnt_find_table_pos(sfont, "vhea") > 0) - 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, vhea->numOfExSideBearings); - } - - if (sfnt_find_table_pos(sfont, "OS/2") <= 0) { - struct tt_os2__table *os2; - /* OpenType font must have OS/2 table. */ - os2 = tt_read_os2__table(sfont); - defaultVertOriginY = PDFUNIT(os2->sTypoAscender); - defaultAdvanceHeight = PDFUNIT(os2->sTypoAscender - os2->sTypoDescender); - RELEASE(os2); - } else { - /* Some TrueType fonts used in Macintosh does not have OS/2 table. */ - defaultAdvanceHeight = 1000; - } - - w2_array = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - USHORT i, gid; - double advanceHeight, vertOriginX, vertOriginY; - gid = CIDToGIDMap ? ((CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]) : cid; - if (gid >= maxp->numGlyphs || (cid != 0 && gid == 0)) - continue; - advanceHeight = vmtx ? PDFUNIT(vmtx[gid].advance) : defaultAdvanceHeight; - vertOriginX = PDFUNIT(hmtx[gid].advance*0.5); - vertOriginY = defaultVertOriginY; - for (i = 0; - i < vorg->numVertOriginYMetrics && gid > vorg->vertOriginYMetrics[i].glyphIndex; - i++) { - if (gid == vorg->vertOriginYMetrics[i].glyphIndex) - vertOriginY = PDFUNIT(vorg->vertOriginYMetrics[i].vertOriginY); - } -#if 0 - /* - * c [w1_1y v_1x v_1y w1_2y v_2x v_2y ...] - * Not working... Why? - * Acrobat Reader: - * Wrong rendering, interpretation of position vector is wrong. - * Xpdf and gs: ignores W2? - */ - if (vertOriginY == defaultVertOriginY && - advanceHeight == defaultAdvanceHeight) { - if (an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - an_array = NULL; - empty = 0; - } - } else { - if (cid != prev + 1 && an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - an_array = NULL; - empty = 0; - } - if (an_array == NULL) { - an_array = pdf_new_array(); - start = cid; - } - pdf_add_array(an_array, pdf_new_number(-advanceHeight)); - pdf_add_array(an_array, pdf_new_number(vertOriginX)); - pdf_add_array(an_array, pdf_new_number(vertOriginY)); - prev = cid; - } -#else - /* - * c_first c_last w1_y v_x v_y - * This form may hit Acrobat's implementation limit of array element size, 8192. - * AFPL GhostScript 8.11 stops with rangecheck error with this. Maybe GS's bug? - */ - if (vertOriginY != defaultVertOriginY || - advanceHeight != defaultAdvanceHeight) { - pdf_add_array(w2_array, pdf_new_number(cid)); - pdf_add_array(w2_array, pdf_new_number(cid)); - pdf_add_array(w2_array, pdf_new_number(-advanceHeight)); - pdf_add_array(w2_array, pdf_new_number(vertOriginX)); - pdf_add_array(w2_array, pdf_new_number(vertOriginY)); - empty = 0; - } -#endif - } - -#if 0 - if (an_array) { - pdf_add_array(w2_array, pdf_new_number(start)); - pdf_add_array(w2_array, an_array); - empty = 0; - } -#endif - - if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) { - an_array = pdf_new_array(); - pdf_add_array(an_array, pdf_new_number(defaultVertOriginY)); - pdf_add_array(an_array, pdf_new_number(-defaultAdvanceHeight)); - pdf_add_dict(fontdict, pdf_new_name ("DW2"), an_array); - } - if (!empty) { - pdf_add_dict(fontdict, - pdf_new_name("W2"), pdf_ref_obj(w2_array)); - } - pdf_release_obj(w2_array); - - if (vorg->vertOriginYMetrics) - RELEASE(vorg->vertOriginYMetrics); - RELEASE(vorg); - - if (vmtx) - RELEASE(vmtx); - if (vhea) - RELEASE(vhea); - - return; -} - -static void -add_CIDMetrics (sfnt *sfont, pdf_obj *fontdict, - unsigned char *CIDToGIDMap, unsigned short last_cid, int need_vmetrics) -{ - struct tt_longMetrics *hmtx; - struct tt_head_table *head; - struct tt_hhea_table *hhea; - struct tt_maxp_table *maxp; - - /* - * Read head, hhea, maxp: - * - * unitsPerEm --> head - * numHMetrics --> hhea - * numGlyphs --> maxp - */ - head = tt_read_head_table(sfont); - maxp = tt_read_maxp_table(sfont); - hhea = tt_read_hhea_table(sfont); - - sfnt_locate_table(sfont, "hmtx"); - hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numOfLongHorMetrics, hhea->numOfExSideBearings); - - add_CIDHMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); - if (need_vmetrics) - add_CIDVMetrics(sfont, fontdict, CIDToGIDMap, last_cid, maxp, head, hmtx); - - RELEASE(hmtx); - RELEASE(hhea); - RELEASE(maxp); - RELEASE(head); - - return; -} - -/* - * Create an instance of embeddable font. - */ -static long -write_fontfile (CIDFont *font, cff_font *cffont) -{ - cff_index *topdict, *fdarray, *private; - unsigned char *dest; - long destlen = 0, i, size; - long offset, topdict_offset, fdarray_offset; - - /* DICT sizes (offset set to long int) */ - topdict = cff_new_index(1); - fdarray = cff_new_index(cffont->num_fds); - private = cff_new_index(cffont->num_fds); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */ - cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */ - - topdict->offset[1] = cff_dict_pack(cffont->topdict, - (card8 *) work_buffer, - WORK_BUFFER_SIZE) + 1; - for (i = 0;i < cffont->num_fds; i++) { - size = 0; - if (cffont->private && cffont->private[i]) { - size = cff_dict_pack(cffont->private[i], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - if (size < 1) { /* Private had contained only Subr */ - cff_dict_remove(cffont->fdarray[i], "Private"); - } - } - (private->offset)[i+1] = (private->offset)[i] + size; - (fdarray->offset)[i+1] = (fdarray->offset)[i] + - cff_dict_pack(cffont->fdarray[i], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - } - - destlen = 4; /* header size */ - destlen += cff_set_name(cffont, font->fontname); - destlen += cff_index_size(topdict); - destlen += cff_index_size(cffont->string); - destlen += cff_index_size(cffont->gsubr); - destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */ - destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */ - destlen += cff_index_size(cffont->cstrings); - destlen += cff_index_size(fdarray); - destlen += private->offset[private->count] - 1; /* Private is not INDEX */ - - dest = NEW(destlen, card8); - - offset = 0; - /* Header */ - offset += cff_put_header(cffont, dest + offset, destlen - offset); - /* Name */ - offset += cff_pack_index(cffont->name, dest + offset, destlen - offset); - /* Top DICT */ - topdict_offset = offset; - offset += cff_index_size(topdict); - /* Strings */ - offset += cff_pack_index(cffont->string, dest + offset, destlen - offset); - /* Global Subrs */ - offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset); - - /* charset */ - cff_dict_set(cffont->topdict, "charset", 0, offset); - offset += cff_pack_charsets(cffont, dest + offset, destlen - offset); - - /* FDSelect */ - cff_dict_set(cffont->topdict, "FDSelect", 0, offset); - offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset); - - /* CharStrings */ - cff_dict_set(cffont->topdict, "CharStrings", 0, offset); - offset += cff_pack_index(cffont->cstrings, - dest + offset, cff_index_size(cffont->cstrings)); - cff_release_index(cffont->cstrings); - cffont->cstrings = NULL; /* Charstrings cosumes huge memory */ - - /* FDArray and Private */ - cff_dict_set(cffont->topdict, "FDArray", 0, offset); - fdarray_offset = offset; - offset += cff_index_size(fdarray); - - fdarray->data = NEW(fdarray->offset[fdarray->count] - 1, card8); - for (i = 0; i < cffont->num_fds; i++) { - size = private->offset[i+1] - private->offset[i]; - if (cffont->private[i] && size > 0) { - cff_dict_pack(cffont->private[i], dest + offset, size); - cff_dict_set(cffont->fdarray[i], "Private", 0, size); - cff_dict_set(cffont->fdarray[i], "Private", 1, offset); - } - cff_dict_pack(cffont->fdarray[i], - fdarray->data + (fdarray->offset)[i] - 1, - fdarray->offset[fdarray->count] - 1); - offset += size; - } - - cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray)); - cff_release_index(fdarray); - cff_release_index(private); - - /* Finally Top DICT */ - topdict->data = NEW(topdict->offset[topdict->count] - 1, card8); - cff_dict_pack(cffont->topdict, - topdict->data, topdict->offset[topdict->count] - 1); - cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict)); - cff_release_index(topdict); - - /* - * FontFile - */ - { - pdf_obj *fontfile, *stream_dict; - - fontfile = pdf_new_stream(STREAM_COMPRESS); - stream_dict = pdf_stream_dict(fontfile); - pdf_add_dict(font->descriptor, - pdf_new_name("FontFile3"), - pdf_ref_obj (fontfile)); - pdf_add_dict(stream_dict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0C")); - pdf_add_stream(fontfile, (char *) dest, offset); - pdf_release_obj(fontfile); - RELEASE(dest); - } - - return destlen; -} - -void -CIDFont_type0_dofont (CIDFont *font) -{ - sfnt *sfont; - cff_font *cffont; - FILE *fp = NULL; - cff_index *charstrings, *idx; - cff_charsets *charset = NULL; - cff_fdselect *fdselect = NULL; - long charstring_len, max_len; - long destlen = 0; - long size, offset = 0; - card8 *data; - card16 num_glyphs, gid; - long cid, cid_count; - card16 cs_count, last_cid; - int fd, prev_fd, parent_id; - char *used_chars; - unsigned char *CIDToGIDMap = NULL; - - ASSERT(font); - - if (!font->indirect) - return; - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - if (CIDFont_is_BaseFont(font)) - return; - else if (!CIDFont_get_embedding(font) && - (opt_flags & CIDFONT_FORCE_FIXEDPITCH)) { - /* No metrics needed. */ - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(1000.0)); - return; - } - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); - if (!fp) - ERROR("Could not open OpenType font file: %s", font->ident); - sfont = sfnt_open(fp); -#endif - if (!sfont) - ERROR("Could not open OpenType font file: %s", font->ident); - - if (sfnt_read_table_directory(sfont, 0) < 0 || - sfont->type != SFNT_TYPE_POSTSCRIPT) - ERROR("Not a CFF/OpenType font ?"); - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) - ERROR("Not a CFF/OpenType font ?"); - - cffont = cff_open(sfont, offset, font->options->index); - if (!cffont) - ERROR("Could not open CFF font."); - if (!(cffont->flag & FONTTYPE_CIDFONT)) - ERROR("Not a CIDFont."); - - if (cff_dict_known(cffont->topdict, "CIDCount")) { - cid_count = (long) cff_dict_get(cffont->topdict, "CIDCount", 0); - } else { - cid_count = CID_MAX + 1; - } - - cff_read_charsets(cffont); - CIDToGIDMap = NEW(2*cid_count, unsigned char); - memset(CIDToGIDMap, 0, 2*cid_count); - add_to_used_chars2(used_chars, 0); /* .notdef */ - cid = 0; last_cid = 0; num_glyphs = 0; - for (cid = 0; cid <= CID_MAX; cid++) { - if (is_used_char2(used_chars, cid)) { - gid = cff_charsets_lookup(cffont, (card16)cid); - if (cid != 0 && gid == 0) { - WARN("Glyph for CID %u missing in font \"%s\".", (CID) cid, font->ident); - used_chars[cid/8] &= ~(1 << (7 - (cid % 8))); - continue; - } - CIDToGIDMap[2*cid] = (gid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = gid & 0xff; - last_cid = cid; - num_glyphs++; - } - } - - /* - * DW, W, DW2 and W2: - * Those values are obtained from OpenType table (not TFM). - */ - if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) { - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(1000.0)); - } else { - add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, - ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); - } - - if (!CIDFont_get_embedding(font)) { - RELEASE(CIDToGIDMap); - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return; - } - - /* - * Embed font subset. - */ - cff_read_fdselect(cffont); - cff_read_fdarray(cffont); - cff_read_private(cffont); - - cff_read_subrs(cffont); - - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - idx = cff_get_index_header(cffont); - /* offset is now absolute offset ... bad */ - offset = cffont->sfont->loc; - - if ((cs_count = idx->count) < 2) { - ERROR("No valid charstring data found."); - } - - /* New Charsets data */ - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = 0; - charset->data.glyphs = NEW(num_glyphs, s_SID); - - /* New FDSelect data */ - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 0; - fdselect->data.ranges = NEW(num_glyphs, cff_range3); - - /* New CharStrings INDEX */ - charstrings = cff_new_index((card16)(num_glyphs+1)); - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - /* - * TODO: Re-assign FD number. - */ - prev_fd = -1; gid = 0; - data = NEW(CS_STR_LEN_MAX, card8); - for (cid = 0; cid <= last_cid; cid++) { - unsigned short gid_org; - - if (!is_used_char2(used_chars, cid)) - continue; - - gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]); - if ((size = (idx->offset)[gid_org+1] - (idx->offset)[gid_org]) - > CS_STR_LEN_MAX) - ERROR("Charstring too long: gid=%u", gid_org); - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - (charstrings->offset)[gid] = charstring_len + 1; - sfnt_seek_set(cffont->sfont, offset + (idx->offset)[gid_org] - 1); - sfnt_read(data, size, cffont->sfont); - fd = cff_fdselect_lookup(cffont, gid_org); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, (cffont->subrs)[fd], 0, 0, NULL); - if (cid > 0 && gid_org > 0) { - charset->data.glyphs[charset->num_entries] = cid; - charset->num_entries += 1; - } - if (fd != prev_fd) { - fdselect->data.ranges[fdselect->num_entries].first = gid; - fdselect->data.ranges[fdselect->num_entries].fd = fd; - fdselect->num_entries += 1; - prev_fd = fd; - } - gid++; - } - if (gid != num_glyphs) - ERROR("Unexpeced error: ?????"); - RELEASE(data); - cff_release_index(idx); - - RELEASE(CIDToGIDMap); - - (charstrings->offset)[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - cffont->num_glyphs = num_glyphs; - cffont->cstrings = charstrings; - - /* discard old one, set new data */ - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - cff_release_fdselect(cffont->fdselect); - cffont->fdselect = fdselect; - - /* no Global subr */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - - for (fd = 0; fd < cffont->num_fds; fd++) { - if (cffont->subrs && cffont->subrs[fd]) { - cff_release_index(cffont->subrs[fd]); - cffont->subrs[fd] = NULL; - } - if (cffont->private && (cffont->private)[fd]) { - cff_dict_remove((cffont->private)[fd], "Subrs"); /* no Subrs */ - } - } - - destlen = write_fontfile(font, cffont); - - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) - MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, destlen); - - /* - * CIDSet: - * Length of CIDSet stream is not clear. Must be 8192 bytes long? - */ - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - return; -} - -int -CIDFont_type0_open (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - CIDSysInfo *csi; - char *fontname; - sfnt *sfont; - cff_font *cffont; - FILE *fp = NULL; - unsigned long offset = 0; - - ASSERT(font); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); - if (!sfont) { - ERROR("Not a CFF/OpenType font?"); - } -#endif - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0 || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font?"); - } - - cffont = cff_open(sfont, offset, opt->index); - if (!cffont) { - ERROR("Cannot read CFF font data"); - } - - if (!(cffont->flag & FONTTYPE_CIDFONT)) { - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - return -1; - } - - csi = NEW(1, CIDSysInfo); - csi->registry = - cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 0)); - csi->ordering = - cff_get_string(cffont, (s_SID)cff_dict_get(cffont->topdict, "ROS", 1)); - csi->supplement = (int)cff_dict_get(cffont->topdict, "ROS", 2); - - if (cmap_csi) { - if (strcmp(csi->registry, cmap_csi->registry) != 0 || - strcmp(csi->ordering, cmap_csi->ordering) != 0) { - MESG("\nCharacter collection mismatched:\n"); - MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); - MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); - ERROR("Inconsistent CMap specified for this font."); - } - if (csi->supplement < cmap_csi->supplement) { - WARN("CMap have higher supplmement number."); - WARN("Some characters may not be displayed or printed."); - } - } - - { - char *shortname; - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - /* - * Mangled name requires more 7 bytes. - * Style requires more 11 bytes. - */ - fontname = NEW(strlen(shortname)+19, char); - memset(fontname, 0, strlen(shortname)+19); - strcpy(fontname, shortname); - RELEASE(shortname); - } - cff_close(cffont); - - if (opt->embed && opt->style != FONT_STYLE_NONE) { - WARN("Embedding disabled due to style option for %s.", name); - opt->embed = 0; - } - switch (opt->style) { - case FONT_STYLE_BOLD: - strcat(fontname, ",Bold"); - break; - case FONT_STYLE_ITALIC: - strcat(fontname, ",Italic"); - break; - case FONT_STYLE_BOLDITALIC: - strcat(fontname, ",BoldItalic"); - break; - } - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = csi; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - /* getting font info. from TrueType tables */ - if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) - ERROR("Could not obtain necessary font info."); - - if (opt->embed) { - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - } - - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string(csi->registry, strlen(csi->registry))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string(csi->ordering, strlen(csi->ordering))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(csi->supplement)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), - pdf_new_number(1000)); /* not sure */ - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - -void -CIDFont_type0_t1cdofont (CIDFont *font) -{ - sfnt *sfont; - cff_font *cffont; - cff_index *charstrings, *idx; - long charstring_len, max_len; - long destlen = 0; - long size, offset = 0; - card8 *data; - card16 num_glyphs, gid, last_cid; - long i, cid; - int parent_id; - char *used_chars; - double default_width, nominal_width; - FILE *fp = NULL; - - ASSERT(font); - - if (!font->indirect) - return; - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_OTFONT); - if (!fp) - ERROR("Could not open OpenType font file: %s", font->ident); - - sfont = sfnt_open(fp); -#endif - if (!sfont) - ERROR("Could not open OpenType font file: %s", font->ident); - - if (sfnt_read_table_directory(sfont, 0) < 0 || - sfont->type != SFNT_TYPE_POSTSCRIPT) - ERROR("Not a CFF/OpenType font ?"); - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) - ERROR("Not a CFF/OpenType font ?"); - - cffont = cff_open(sfont, offset, font->options->index); - if (!cffont) - ERROR("Could not open CFF font."); - if (cffont->flag & FONTTYPE_CIDFONT) - ERROR("This is CIDFont..."); - - cff_read_private(cffont); - cff_read_subrs (cffont); - - if (cffont->private[0] && cff_dict_known(cffont->private[0], "StdVW")) { - double stemv; - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - pdf_add_dict(font->descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - } - if (cffont->private[0] && cff_dict_known(cffont->private[0], "defaultWidthX")) { - default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - default_width = CFF_DEFAULTWIDTHX_DEFAULT; - } - if (cffont->private[0] && cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominal_width = CFF_NOMINALWIDTHX_DEFAULT; - } - - num_glyphs = 0; last_cid = 0; - add_to_used_chars2(used_chars, 0); /* .notdef */ - for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { - int c, j; - - c = used_chars[i]; - for (j = 7; j >= 0; j--) { - if (c & (1 << j)) { - num_glyphs++; - last_cid = (i + 1) * 8 - j - 1; - } - } - } - - { - cff_fdselect *fdselect; - - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 1; - fdselect->data.ranges = NEW(1, cff_range3); - fdselect->data.ranges[0].first = 0; - fdselect->data.ranges[0].fd = 0; - cffont->fdselect = fdselect; - } - - { - cff_charsets *charset; - - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = num_glyphs-1; - charset->data.glyphs = NEW(num_glyphs-1, s_SID); - - for (gid = 0, cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - if (gid > 0) - charset->data.glyphs[gid-1] = cid; - gid++; - } - } - /* cff_release_charsets(cffont->charsets); */ - cffont->charsets = charset; - } - - cff_dict_add(cffont->topdict, "CIDCount", 1); - cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); - - cffont->fdarray = NEW(1, cff_dict *); - cffont->fdarray[0] = cff_new_dict(); - cff_dict_add(cffont->fdarray[0], "FontName", 1); - cff_dict_set(cffont->fdarray[0], "FontName", 0, - (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ - cff_dict_add(cffont->fdarray[0], "Private", 2); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - /* FDArray - index offset, not known yet */ - cff_dict_add(cffont->topdict, "FDArray", 1); - cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); - /* FDSelect - offset, not known yet */ - cff_dict_add(cffont->topdict, "FDSelect", 1); - cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - cff_dict_remove(cffont->topdict, "Private"); - cff_dict_remove(cffont->topdict, "Encoding"); - - - /* */ - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - idx = cff_get_index_header(cffont); - /* offset is now absolute offset ... bad */ - offset = cffont->sfont->loc; - - if (idx->count < 2) - ERROR("No valid charstring data found."); - - /* New CharStrings INDEX */ - charstrings = cff_new_index((card16)(num_glyphs+1)); - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - gid = 0; - data = NEW(CS_STR_LEN_MAX, card8); - for (cid = 0; cid <= last_cid; cid++) { - if (!is_used_char2(used_chars, cid)) - continue; - - if ((size = (idx->offset)[cid+1] - (idx->offset)[cid]) - > CS_STR_LEN_MAX) - ERROR("Charstring too long: gid=%u", cid); - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - (charstrings->offset)[gid] = charstring_len + 1; - sfnt_seek_set(cffont->sfont, offset + (idx->offset)[cid] - 1); - sfnt_read(data, size, cffont->sfont); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, (cffont->subrs)[0], - default_width, nominal_width, NULL); - gid++; - } - if (gid != num_glyphs) - ERROR("Unexpeced error: ?????"); - RELEASE(data); - cff_release_index(idx); - - (charstrings->offset)[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - cffont->num_glyphs = num_glyphs; - cffont->cstrings = charstrings; - - /* no Global subr */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - - if (cffont->subrs && cffont->subrs[0]) { - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - } - if (cffont->private && (cffont->private)[0]) { - cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */ - } - - cff_add_string(cffont, "Adobe", 1); - cff_add_string(cffont, "Identity", 1); - - cff_dict_update(cffont->topdict, cffont); - cff_dict_update(cffont->private[0], cffont); - cff_update_string(cffont); - - /* CFF code need to be rewrote... */ - cff_dict_add(cffont->topdict, "ROS", 3); - cff_dict_set(cffont->topdict, "ROS", 0, - (double) cff_get_sid(cffont, "Adobe")); - cff_dict_set(cffont->topdict, "ROS", 1, - (double) cff_get_sid(cffont, "Identity")); - cff_dict_set(cffont->topdict, "ROS", 2, 0.0); - - destlen = write_fontfile(font, cffont); - - cff_close(cffont); - - /* - * DW, W, DW2 and W2: - * Those values are obtained from OpenType table (not TFM). - */ - { - unsigned char *CIDToGIDMap; - - CIDToGIDMap = NEW(2 * (last_cid+1), unsigned char); - memset(CIDToGIDMap, 0, 2 * (last_cid + 1)); - for (cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - CIDToGIDMap[2*cid ] = (cid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = cid & 0xff; - } - } - add_CIDMetrics(sfont, font->fontdict, CIDToGIDMap, last_cid, - ((CIDFont_get_parent_id(font, 1) < 0) ? 0 : 1)); - RELEASE(CIDToGIDMap); - } - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) - MESG("[%u glyphs][%ld bytes]", num_glyphs, destlen); - - /* - * CIDSet: - * Length of CIDSet stream is not clear. Must be 8192 bytes long? - */ - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - return; -} - -int -CIDFont_type0_t1copen (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - CIDSysInfo *csi; - char *fontname; - sfnt *sfont; - cff_font *cffont; - unsigned long offset = 0; - FILE *fp = NULL; - - ASSERT(font); - -#ifdef XETEX - sfont = sfnt_open(font->ft_face, SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(name, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); -#endif - if (!sfont) { - ERROR("Not a CFF/OpenType font?"); - } - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0 || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font?"); - } - - cffont = cff_open(sfont, offset, opt->index); - if (!cffont) { - ERROR("Cannot read CFF font data"); - } - - if (cffont->flag & FONTTYPE_CIDFONT) { - cff_close(cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return -1; - } - - csi = NEW(1, CIDSysInfo); - csi->registry = NEW(strlen("Adobe")+1, char); - strcpy(csi->registry, "Adobe"); - csi->ordering = NEW(strlen("Identity")+1, char); - strcpy(csi->ordering, "Identity"); - csi->supplement = 0; - - if (cmap_csi) { - if (strcmp(csi->registry, cmap_csi->registry) != 0 || - strcmp(csi->ordering, cmap_csi->ordering) != 0) { - MESG("\nCharacter collection mismatched:\n"); - MESG("\tFont: %s-%s-%d\n", csi->registry, csi->ordering, csi->supplement); - MESG("\tCMap: %s-%s-%d\n", cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement); - ERROR("Inconsistent CMap specified for this font."); - } - if (csi->supplement < cmap_csi->supplement) { - WARN("CMap have higher supplmement number."); - WARN("Some characters may not be displayed or printed."); - } - } - - { - char *shortname; - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - /* Mangled name requires more 7 bytes. */ - - fontname = NEW(strlen(shortname) + 8, char); - memset(fontname, 0, strlen(shortname) + 8); - strcpy(fontname, shortname); - RELEASE(shortname); - } - cff_close(cffont); - - opt->embed = 1; - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = csi; - font->flags |= CIDFONT_FLAG_TYPE1C; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - /* getting font info. from TrueType tables */ - if ((font->descriptor - = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name)) == NULL) - ERROR("Could not obtain necessary font info."); - - if (opt->embed) { - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - } - - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string(csi->registry, strlen(csi->registry))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string(csi->ordering, strlen(csi->ordering))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(csi->supplement)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - - -/* Type1 --> CFF CIDFont */ -#include "unicode.h" -#include "t1_load.h" -#include "t1_char.h" - -#include "agl.h" - -#include "cmap.h" -#include "cmap_write.h" -#include "fontmap.h" - -static int -load_base_CMap (const char *font_name, int wmode, cff_font *cffont) -{ - int cmap_id = -1; - CMap *cmap; - char *cmap_name; - card16 gid; - unsigned char range_min[4] = {0x00, 0x00, 0x00, 0x00}; - unsigned char range_max[4] = {0x7f, 0xff, 0xff, 0xff}; - - cmap_name = NEW(strlen(font_name)+strlen("-UCS4-H")+1, char); - if (wmode) { - sprintf(cmap_name, "%s-UCS4-V", font_name); - } else { - sprintf(cmap_name, "%s-UCS4-H", font_name); - } - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id >= 0) { - RELEASE(cmap_name); - return cmap_id; - } - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - CMap_add_codespacerange(cmap, range_min, range_max, 4); - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - RELEASE(cmap_name); - - for (gid = 1; gid < cffont->num_glyphs; gid++) { - long ucv; - s_SID sid; - char *glyph, *name, *suffix; - unsigned char srcCode[4]; - - sid = cff_charsets_lookup_inverse(cffont, gid); - glyph = cff_get_string (cffont, sid); - - name = agl_chop_suffix(glyph, &suffix); - if (!name) { - if (suffix) - RELEASE(suffix); - RELEASE(glyph); - continue; - } - - if (suffix) { - RELEASE(name); - RELEASE(suffix); - RELEASE(glyph); - continue; - } - - if (agl_name_is_unicode(name)) { - ucv = agl_name_convert_unicode(name); - srcCode[0] = (ucv >> 24) & 0xff; - srcCode[1] = (ucv >> 16) & 0xff; - srcCode[2] = (ucv >> 8) & 0xff; - srcCode[3] = ucv & 0xff; - CMap_add_cidchar(cmap, srcCode, 4, gid); - } else { - agl_name *agln; - - agln = agl_lookup_list(name); - if (!agln) - WARN("Glyph \"%s\" inaccessible (no Unicode mapping)", glyph); - while (agln) { - if (agln->n_components > 1) { - WARN("Glyph \"%s\" inaccessible (composite character)", glyph); - } else if (agln->n_components == 1) { - ucv = agln->unicodes[0]; - srcCode[0] = (ucv >> 24) & 0xff; - srcCode[1] = (ucv >> 16) & 0xff; - srcCode[2] = (ucv >> 8) & 0xff; - srcCode[3] = ucv & 0xff; - CMap_add_cidchar(cmap, srcCode, 4, gid); - } - agln = agln->alternate; - } - } - RELEASE(name); - if (suffix) - RELEASE(suffix); - RELEASE(glyph); - } - cmap_id = CMap_cache_add(cmap); - - return cmap_id; -} - -int -t1_load_UnicodeCMap (const char *font_name, - const char *otl_tags, /* not supported yet */ - int wmode) -{ - int cmap_id = -1; - cff_font *cffont; - FILE *fp; - - if (!font_name) - return -1; - - fp = DPXFOPEN(font_name, DPX_RES_TYPE_T1FONT); - if (!fp) - return -1; - - cffont = t1_load_font(NULL, 1, fp); - DPXFCLOSE(fp); - if (!cffont) - return -1; - - cmap_id = load_base_CMap(font_name, wmode, cffont); - - cff_close(cffont); - - if (cmap_id < 0) { - ERROR("Failed to create Unicode charmap for font \"%s\".", font_name); - return -1; - } - - if (otl_tags) { - WARN("Glyph substitution not supported for Type1 font yet..."); - } - - return cmap_id; -} - - -/* - * ToUnicode CMap - */ - -static pdf_obj * -create_ToUnicode_stream (cff_font *cffont, - const char *font_name, const char *used_glyphs) -{ - pdf_obj *stream = NULL; - CMap *cmap; - CID cid; - card16 gid; - long glyph_count, total_fail_count; - char *cmap_name; -#define WBUF_SIZE 1024 - unsigned char wbuf[WBUF_SIZE]; - unsigned char *p, *endptr; - static unsigned char range_min[2] = {0x00, 0x00}; - static unsigned char range_max[2] = {0xff, 0xff}; - - if (!font_name || !used_glyphs) - return NULL; - - cmap = CMap_new(); - - cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+1, char); - strcpy(cmap_name, font_name); - strcat(cmap_name, "-UTF16"); - CMap_set_name (cmap, cmap_name); - RELEASE(cmap_name); - - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - - CMap_add_codespacerange(cmap, range_min, range_max, 2); - - glyph_count = total_fail_count = 0; - p = wbuf; - endptr = wbuf + WBUF_SIZE; - for (cid = 1; cid < cffont->num_glyphs; cid++) { /* Skip .notdef */ - if (is_used_char2(used_glyphs, cid)) { - char *glyph; - long len; - int fail_count; - - wbuf[0] = (cid >> 8) & 0xff; - wbuf[1] = (cid & 0xff); - - p = wbuf + 2; - gid = cff_charsets_lookup_inverse(cffont, cid); - if (gid == 0) - continue; - glyph = cff_get_string(cffont, gid); - if (glyph) { - len = agl_sput_UTF16BE(glyph, &p, endptr, &fail_count); - if (len < 1 || fail_count) { - total_fail_count += fail_count; - } else { - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); - } - RELEASE(glyph); - } - glyph_count++; - } - } - - if (total_fail_count != 0 && - total_fail_count >= glyph_count/10) { - WARN("%d glyph names (out of %d) missing Unicode mapping.", - total_fail_count, glyph_count); - WARN("ToUnicode CMap \"%s-UTF16\" removed.", font_name); - } else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - - -int -CIDFont_type0_t1open (CIDFont *font, const char *name, - CIDSysInfo *cmap_csi, cid_opt *opt) -{ - FILE *fp; - char *fontname, *shortname; - cff_font *cffont; - - ASSERT(font); - - if (cmap_csi && - (strcmp(cmap_csi->registry, "Adobe") != 0 || - strcmp(cmap_csi->ordering, "Identity") != 0)) { - return -1; - } - fp = DPXFOPEN(name, DPX_RES_TYPE_T1FONT); - if (!fp) - return -1; - - cffont = t1_load_font(NULL, 1, fp); - if (!cffont) { - DPXFCLOSE(fp); - return -1; - } - DPXFCLOSE(fp); - - shortname = cff_get_name(cffont); - if (!shortname) - ERROR("No valid FontName found."); - fontname = NEW(strlen(shortname) + 8, char); - memset(fontname, 0, strlen(shortname) + 8); - strcpy(fontname, shortname); - RELEASE(shortname); - -#ifdef XETEX - font->ft_to_gid = cff_get_ft_to_gid(cffont); - cffont->ft_to_gid = NULL; -#endif - - cff_close(cffont); - - if (opt->style != FONT_STYLE_NONE) { - WARN(",Bold, ,Italic, ... not supported for this type of font..."); - opt->style = FONT_STYLE_NONE; - } - - font->fontname = fontname; - font->subtype = CIDFONT_TYPE0; - font->csi = NEW(1, CIDSysInfo); - font->csi->registry = NEW(strlen("Adobe")+1, char); - strcpy(font->csi->registry, "Adobe"); - font->csi->ordering = NEW(strlen("Identity")+1, char); - strcpy(font->csi->ordering, "Identity"); - font->csi->supplement = 0; - font->flags |= CIDFONT_FLAG_TYPE1; - - font->fontdict = pdf_new_dict(); - pdf_add_dict(font->fontdict, - pdf_new_name("Type"), - pdf_new_name("Font")); - pdf_add_dict(font->fontdict, - pdf_new_name("Subtype"), - pdf_new_name("CIDFontType0")); - - memmove(fontname + 7, fontname, strlen(fontname) + 1); - pdf_font_make_uniqueTag(fontname); - fontname[6] = '+'; - - font->descriptor = pdf_new_dict(); - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), - pdf_new_name(fontname)); - pdf_add_dict(font->fontdict, - pdf_new_name("BaseFont"), - pdf_new_name(fontname)); - { - pdf_obj *csi_dict; - - csi_dict = pdf_new_dict(); - pdf_add_dict(csi_dict, - pdf_new_name("Registry"), - pdf_new_string("Adobe", strlen("Adobe"))); - pdf_add_dict(csi_dict, - pdf_new_name("Ordering"), - pdf_new_string("Identity", strlen("Identity"))); - pdf_add_dict(csi_dict, - pdf_new_name("Supplement"), - pdf_new_number(0.0)); - pdf_add_dict(font->fontdict, pdf_new_name("CIDSystemInfo"), csi_dict); - } - - - return 0; -} - -/* Duplicate from type1.c */ -#define TYPE1_NAME_LEN_MAX 127 - -#define FONT_FLAG_FIXEDPITCH (1 << 0) /* Fixed-width font */ -#define FONT_FLAG_SERIF (1 << 1) /* Serif font */ -#define FONT_FLAG_SYMBOLIC (1 << 2) /* Symbolic font */ -#define FONT_FLAG_SCRIPT (1 << 3) /* Script font */ -#define FONT_FLAG_STANDARD (1 << 5) /* Adobe Standard Character Set */ -#define FONT_FLAG_ITALIC (1 << 6) /* Italic */ -#define FONT_FLAG_ALLCAP (1 << 16) /* All-cap font */ -#define FONT_FLAG_SMALLCAP (1 << 17) /* Small-cap font */ -#define FONT_FLAG_FORCEBOLD (1 << 18) /* Force bold at small text sizes */ - -/* pdf_font --> CIDFont */ -static void -get_font_attr (CIDFont *font, cff_font *cffont) -{ - double capheight, ascent, descent; - double italicangle, stemv; - double defaultwidth, nominalwidth; - long flags = 0; - long gid; - int i; - static const char *L_c[] = { - "H", "P", "Pi", "Rho", NULL - }; - static const char *L_d[] = { - "p", "q", "mu", "eta", NULL - }; - static const char *L_a[] = { - "b", "h", "lambda", NULL - }; - t1_ginfo gm; - - defaultwidth = 500.0; - nominalwidth = 0.0; - - /* - * CapHeight, Ascent, and Descent is meaningfull only for Latin/Greek/Cyrillic. - * The BlueValues and OtherBlues also have those information. - */ - if (cff_dict_known(cffont->topdict, "FontBBox")) { - /* Default values */ - capheight = ascent = cff_dict_get(cffont->topdict, "FontBBox", 3); - descent = cff_dict_get(cffont->topdict, "FontBBox", 1); - } else { - capheight = 680.0; - ascent = 690.0; - descent = -190.0; - } - if (cff_dict_known(cffont->private[0], "StdVW")) { - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - } else { - /* - * We may use the following values for StemV: - * Thin - ExtraLight: <= 50 - * Light: 71 - * Regular(Normal): 88 - * Medium: 109 - * SemiBold(DemiBold): 135 - * Bold - Heavy: >= 166 - */ - stemv = 88.0; - } - if (cff_dict_known(cffont->topdict, "ItalicAngle")) { - italicangle = cff_dict_get(cffont->topdict, "ItalicAngle", 0); - if (italicangle != 0.0) - flags |= FONT_FLAG_ITALIC; - } else { - italicangle = 0.0; - } - - /* - * Use "space", "H", "p", and "b" for various values. - * Those characters should not "seac". (no accent) - */ - gid = cff_glyph_lookup(cffont, "space"); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - defaultwidth = gm.wx; - } - - for (i = 0; L_c[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_c[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - capheight = gm.bbox.ury; - break; - } - } - - for (i = 0; L_d[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_d[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - descent = gm.bbox.lly; - break; - } - } - - for (i = 0; L_a[i] != NULL; i++) { - gid = cff_glyph_lookup(cffont, L_a[i]); - if (gid >= 0 && gid < cffont->cstrings->count) { - t1char_get_metrics(cffont->cstrings->data + cffont->cstrings->offset[gid] - 1, - cffont->cstrings->offset[gid+1] - cffont->cstrings->offset[gid], - cffont->subrs[0], &gm); - ascent = gm.bbox.ury; - break; - } - } - - if (defaultwidth != 0.0) { - cff_dict_add(cffont->private[0], "defaultWidthX", 1); - cff_dict_set(cffont->private[0], "defaultWidthX", 0, defaultwidth); - } - if (nominalwidth != 0.0) { - cff_dict_add(cffont->private[0], "nominalWidthX", 1); - cff_dict_set(cffont->private[0], "nominalWidthX", 0, nominalwidth); - } - if (cff_dict_known(cffont->private[0], "ForceBold") && - cff_dict_get(cffont->private[0], "ForceBold", 0)) { - flags |= FONT_FLAG_FORCEBOLD; - } - if (cff_dict_known(cffont->private[0], "IsFixedPitch") && - cff_dict_get(cffont->private[0], "IsFixedPitch", 0)) { - flags |= FONT_FLAG_FIXEDPITCH; - } - if (font->fontname && - !strstr(font->fontname, "Sans")) { - flags |= FONT_FLAG_SERIF; - } - flags |= FONT_FLAG_SYMBOLIC; - - pdf_add_dict(font->descriptor, - pdf_new_name("CapHeight"), pdf_new_number(capheight)); - pdf_add_dict(font->descriptor, - pdf_new_name("Ascent"), pdf_new_number(ascent)); - pdf_add_dict(font->descriptor, - pdf_new_name("Descent"), pdf_new_number(descent)); - pdf_add_dict(font->descriptor, - pdf_new_name("ItalicAngle"), pdf_new_number(italicangle)); - pdf_add_dict(font->descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - pdf_add_dict(font->descriptor, - pdf_new_name("Flags"), pdf_new_number(flags)); -} - -static void -add_metrics (CIDFont *font, cff_font *cffont, - unsigned char *CIDToGIDMap, - double *widths, double default_width, CID last_cid) -{ - pdf_obj *tmp; - double val; - card16 cid, gid; - char *used_chars; - int i, parent_id; - - /* - * The original FontBBox of the font is preserved, instead - * of replacing it with tight bounding box calculated from - * charstrings, to prevent Acrobat 4 from greeking text as - * much as possible. - */ - if (!cff_dict_known(cffont->topdict, "FontBBox")) { - ERROR("No FontBBox?"); - } - tmp = pdf_new_array(); - for (i = 0; i < 4; i++) { - val = cff_dict_get(cffont->topdict, "FontBBox", i); - pdf_add_array(tmp, pdf_new_number(ROUND(val, 1.0))); - } - pdf_add_dict(font->descriptor, pdf_new_name("FontBBox"), tmp); - - if ((parent_id = CIDFont_get_parent_id(font, 0)) < 0 && - (parent_id = CIDFont_get_parent_id(font, 1)) < 0) - ERROR("No parent Type 0 font !"); - - used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id)); - if (!used_chars) { - ERROR("Unexpected error: Font not actually used???"); - } - - /* FIXME: - * This writes "CID CID width". - * I think it's better to handle each 8 char block - * and to use "CID_start [ w0 w1 ...]". - */ - tmp = pdf_new_array(); - for (cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - gid = (CIDToGIDMap[2*cid] << 8)|CIDToGIDMap[2*cid+1]; - if (widths[gid] != default_width) { - pdf_add_array(tmp, pdf_new_number(cid)); - pdf_add_array(tmp, pdf_new_number(cid)); - pdf_add_array(tmp, pdf_new_number(ROUND(widths[gid], 1.0))); - } - } - } - pdf_add_dict(font->fontdict, - pdf_new_name("DW"), pdf_new_number(default_width)); - if (pdf_array_length(tmp) > 0) { - pdf_add_dict(font->fontdict, pdf_new_name("W"), pdf_ref_obj(tmp)); - } - pdf_release_obj(tmp); -} - -void -CIDFont_type0_t1dofont (CIDFont *font) -{ - cff_font *cffont; - double defaultwidth, nominalwidth; - long num_glyphs = 0; - FILE *fp; - long i, offset; - char *used_chars = NULL; - card16 last_cid, gid, cid; - unsigned char *CIDToGIDMap; - - ASSERT(font); - - if (!font->indirect) { - return; - } - - pdf_add_dict(font->fontdict, - pdf_new_name("FontDescriptor"), - pdf_ref_obj (font->descriptor)); - - fp = DPXFOPEN(font->ident, DPX_RES_TYPE_T1FONT); - if (!fp) { - ERROR("Type1: Could not open Type1 font."); - } - - cffont = t1_load_font(NULL, 0, fp); - if (!cffont) - ERROR("Could not read Type 1 font..."); - DPXFCLOSE(fp); - - if (!font->fontname) - ERROR("Fontname undefined..."); - - { - Type0Font *hparent, *vparent; - pdf_obj *tounicode; - int vparent_id, hparent_id; - - hparent_id = CIDFont_get_parent_id(font, 0); - vparent_id = CIDFont_get_parent_id(font, 1); - if (hparent_id < 0 && vparent_id < 0) - ERROR("No parent Type 0 font !"); - - /* usedchars is same for h and v */ - if (hparent_id < 0) - hparent = NULL; - else { - hparent = Type0Font_cache_get(hparent_id); - used_chars = Type0Font_get_usedchars(hparent); - } - if (vparent_id < 0) - vparent = NULL; - else { - vparent = Type0Font_cache_get(vparent_id); - used_chars = Type0Font_get_usedchars(vparent); - } - if (!used_chars) - ERROR("Unexpected error: Font not actually used???"); - - tounicode = create_ToUnicode_stream(cffont, font->fontname, used_chars); - - if (hparent) - Type0Font_set_ToUnicode(hparent, pdf_ref_obj(tounicode)); - if (vparent) - Type0Font_set_ToUnicode(vparent, pdf_ref_obj(tounicode)); - pdf_release_obj(tounicode); - } - - cff_set_name(cffont, font->fontname); - - /* defaultWidthX, CapHeight, etc. */ - get_font_attr(font, cffont); - if (cff_dict_known(cffont->private[0], "defaultWidthX")) { - defaultwidth = cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - defaultwidth = 0.0; - } - if (cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominalwidth = cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominalwidth = 0.0; - } - - num_glyphs = 0; last_cid = 0; - add_to_used_chars2(used_chars, 0); /* .notdef */ - for (i = 0; i < (cffont->num_glyphs + 7)/8; i++) { - int c, j; - - c = used_chars[i]; - for (j = 7; j >= 0; j--) { - if (c & (1 << j)) { - num_glyphs++; - last_cid = (i + 1) * 8 - j - 1; - } - } - } - - { - cff_fdselect *fdselect; - - fdselect = NEW(1, cff_fdselect); - fdselect->format = 3; - fdselect->num_entries = 1; - fdselect->data.ranges = NEW(1, cff_range3); - fdselect->data.ranges[0].first = 0; - fdselect->data.ranges[0].fd = 0; - cffont->fdselect = fdselect; - } - - CIDToGIDMap = NEW(2*(last_cid+1), unsigned char); - memset(CIDToGIDMap, 0, 2*(last_cid+1)); - { - cff_charsets *charset; - - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = num_glyphs-1; - charset->data.glyphs = NEW(num_glyphs-1, s_SID); - - for (gid = 0, cid = 0; cid <= last_cid; cid++) { - if (is_used_char2(used_chars, cid)) { - if (gid > 0) - charset->data.glyphs[gid-1] = cid; - CIDToGIDMap[2*cid ] = (gid >> 8) & 0xff; - CIDToGIDMap[2*cid+1] = gid & 0xff; - gid++; - } - } - - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - } - - cff_dict_add(cffont->topdict, "CIDCount", 1); - cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1); - - cffont->fdarray = NEW(1, cff_dict *); - cffont->fdarray[0] = cff_new_dict(); - cff_dict_add(cffont->fdarray[0], "FontName", 1); - cff_dict_set(cffont->fdarray[0], "FontName", 0, - (double) cff_add_string(cffont, font->fontname + 7, 1)); /* FIXME: Skip XXXXXX+ */ - cff_dict_add(cffont->fdarray[0], "Private", 2); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0); - - /* FDArray - index offset, not known yet */ - cff_dict_add(cffont->topdict, "FDArray", 1); - cff_dict_set(cffont->topdict, "FDArray", 0, 0.0); - /* FDSelect - offset, not known yet */ - cff_dict_add(cffont->topdict, "FDSelect", 1); - cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0); - - cff_dict_add(cffont->topdict, "charset", 1); - cff_dict_set(cffont->topdict, "charset", 0, 0.0); - - cff_dict_add(cffont->topdict, "CharStrings", 1); - cff_dict_set(cffont->topdict, "CharStrings", 0, 0.0); - - { - cff_index *cstring; - t1_ginfo gm; - long max = 0; - double *widths; - int w_stat[1001], max_count, dw; - - widths = NEW(num_glyphs, double); - memset(w_stat, 0, sizeof(int)*1001); - offset = 0L; - cstring = cff_new_index((card16)num_glyphs); - cstring->data = NULL; - cstring->offset[0] = 1; - gid = 0; - for (cid = 0; cid <= last_cid; cid++) { - if (!is_used_char2(used_chars, cid)) - continue; - - if (offset + CS_STR_LEN_MAX >= max) { - max += CS_STR_LEN_MAX*2; - cstring->data = RENEW(cstring->data, max, card8); - } - offset += t1char_convert_charstring(cstring->data + cstring->offset[gid] - 1, CS_STR_LEN_MAX, - cffont->cstrings->data + cffont->cstrings->offset[cid] - 1, - cffont->cstrings->offset[cid+1] - cffont->cstrings->offset[cid], - cffont->subrs[0], defaultwidth, nominalwidth, &gm); - cstring->offset[gid+1] = offset + 1; - if (gm.use_seac) { - ERROR("This font using the \"seac\" command for accented characters..."); - } - widths[gid] = gm.wx; - if (gm.wx >= 0.0 && gm.wx <= 1000.0) { - w_stat[((int) gm.wx)] += 1; - } - gid++; - } - - cff_release_index(cffont->cstrings); - cffont->cstrings = cstring; - - max_count = 0; dw = -1; - for (i = 0; i <= 1000; i++) { - if (w_stat[i] > max_count) { - dw = i; - max_count = w_stat[i]; - } - } - if (dw >= 0) { - add_metrics(font, cffont, CIDToGIDMap, widths, dw, last_cid); - } else { - add_metrics(font, cffont, CIDToGIDMap, widths, defaultwidth, last_cid); - } - RELEASE(widths); - } - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - - RELEASE(CIDToGIDMap); - - cff_add_string(cffont, "Adobe", 1); - cff_add_string(cffont, "Identity", 1); - - cff_dict_update(cffont->topdict, cffont); - cff_dict_update(cffont->private[0], cffont); - - cff_update_string(cffont); - - /* CFF code need to be rewrote... */ - cff_dict_add(cffont->topdict, "ROS", 3); - cff_dict_set(cffont->topdict, "ROS", 0, - (double) cff_get_sid(cffont, "Adobe")); - cff_dict_set(cffont->topdict, "ROS", 1, - (double) cff_get_sid(cffont, "Identity")); - cff_dict_set(cffont->topdict, "ROS", 2, 0.0); - - cffont->num_glyphs = num_glyphs; - offset = write_fontfile(font, cffont); - - cff_close(cffont); - - { - pdf_obj *cidset; - - cidset = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(cidset, used_chars, (last_cid/8)+1); - pdf_add_dict(font->descriptor, - pdf_new_name("CIDSet"), pdf_ref_obj(cidset)); - pdf_release_obj(cidset); - } - - - return; -} - -void -CIDFont_type0_release(CIDFont *font) -{ -#ifdef XETEX - if (font->ft_to_gid) - RELEASE(font->ft_to_gid); -#endif - return; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/dvi.c b/Build/source/texk/dvipdfm-x/xsrc/dvi.c deleted file mode 100644 index 3e7f5e3cdd0..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/dvi.c +++ /dev/null @@ -1,2754 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "numbers.h" - -#include "pdfdev.h" -#include "pdfdoc.h" -#include "pdfparse.h" -#include "pdfencrypt.h" - -#include "fontmap.h" - -#include "dvicodes.h" -#include "tfm.h" -#include "vf.h" -#include "subfont.h" - -#include "spc_util.h" -#include "specials.h" - -#include "dvi.h" - -#ifdef XETEX -#include "pdfximage.h" -#include FT_ADVANCES_H -#endif - -#define DVI_STACK_DEPTH_MAX 256u -#define TEX_FONTS_ALLOC_SIZE 16u -#define VF_NESTING_MAX 16u - -/* Interal Variables */ -static FILE *dvi_file = NULL; -static char linear = 0; /* set to 1 for strict linear processing of the input */ - -static unsigned long *page_loc = NULL; -static unsigned long num_pages = 0; - -static unsigned long dvi_file_size = 0; - -static struct dvi_header -{ - UNSIGNED_QUAD unit_num; - UNSIGNED_QUAD unit_den; - UNSIGNED_QUAD mag; - UNSIGNED_QUAD media_width, media_height; - UNSIGNED_PAIR stackdepth; - char comment[257]; -} dvi_info = { - 25400000 , /* num */ - 473628672, /* den */ - 1000, /* mag */ - 0, 0, /* media width and height */ - 0, /* stackdepth */ - {'\0'} /* comment */ -}; - -static double dev_origin_x = 72.0, dev_origin_y = 770.0; - -#ifdef XETEX -double get_origin (int x) -{ - return x ? dev_origin_x : dev_origin_y; -} -#endif - -#define PHYSICAL 1 -#define VIRTUAL 2 -#define SUBFONT 3 -#define NATIVE 4 -#define DVI 1 -#define VF 2 - -static struct loaded_font -{ - int type; /* Type is physical or virtual */ - int font_id; /* id returned by dev (for PHYSICAL fonts) - * or by vf module for (VIRTUAL fonts) - */ - int subfont_id; /* id returned by subfont_locate_font() */ - int tfm_id; - spt_t size; - int source; /* Source is either DVI or VF */ -#ifdef XETEX - unsigned long rgba_color; - FT_Face ft_face; - int layout_dir; - float extend; - float slant; - float embolden; -#endif -} *loaded_fonts = NULL; -static int num_loaded_fonts = 0, max_loaded_fonts = 0; - -static void -need_more_fonts (unsigned n) -{ - if (num_loaded_fonts + n > max_loaded_fonts) { - max_loaded_fonts += TEX_FONTS_ALLOC_SIZE; - loaded_fonts = RENEW (loaded_fonts, max_loaded_fonts, struct loaded_font); - } -} - -static struct font_def -{ - long tex_id; - spt_t point_size; - spt_t design_size; - char *font_name; - int font_id; /* index of _loaded_ font in loaded_fonts array */ - int used; -#ifdef XETEX - int native; /* boolean */ - 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; - -#ifdef XETEX -#define XDV_FLAG_VERTICAL 0x0100 -#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; -static int compute_boxes = 0, link_annot = 1; -static int verbose = 0; - -#ifdef XETEX -#define DVI_PAGE_BUF_CHUNK 0x10000UL /* 64K should be plenty for most pages */ - -static unsigned char* dvi_page_buffer; -static unsigned long dvi_page_buf_size; -static unsigned long dvi_page_buf_index; - -/* functions to read numbers from the dvi file and store them in dvi_page_buffer */ -static UNSIGNED_BYTE get_and_buffer_unsigned_byte (FILE *file) -{ - int ch; - if ((ch = fgetc (file)) < 0) - ERROR ("File ended prematurely\n"); - if (dvi_page_buf_index >= dvi_page_buf_size) { - dvi_page_buf_size += DVI_PAGE_BUF_CHUNK; - dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); - } - dvi_page_buffer[dvi_page_buf_index++] = ch; - return (UNSIGNED_BYTE) ch; -} - -#if 0 -/* Not used */ -static SIGNED_BYTE get_and_buffer_signed_byte (FILE *file) -{ - int byte; - byte = get_and_buffer_unsigned_byte(file); - if (byte >= 0x80) - byte -= 0x100; - return (SIGNED_BYTE) byte; -} -#endif - -static UNSIGNED_PAIR get_and_buffer_unsigned_pair (FILE *file) -{ - int i; - UNSIGNED_BYTE byte; - UNSIGNED_PAIR pair = 0; - for (i=0; i<2; i++) { - byte = get_and_buffer_unsigned_byte(file); - pair = pair*0x100u + byte; - } - return pair; -} - -static SIGNED_PAIR get_and_buffer_signed_pair (FILE *file) -{ - int i; - long pair = 0; - for (i=0; i<2; i++) { - pair = pair*0x100 + get_and_buffer_unsigned_byte(file); - } - if (pair >= 0x8000) { - pair -= 0x10000l; - } - return (SIGNED_PAIR) pair; -} - -static UNSIGNED_TRIPLE get_and_buffer_unsigned_triple(FILE *file) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100u + get_and_buffer_unsigned_byte(file); - } - return (UNSIGNED_TRIPLE) triple; -} - -static SIGNED_TRIPLE get_and_buffer_signed_triple(FILE *file) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100 + get_and_buffer_unsigned_byte(file); - } - if (triple >= 0x800000l) - triple -= 0x1000000l; - return (SIGNED_TRIPLE) triple; -} - -static SIGNED_QUAD get_and_buffer_signed_quad(FILE *file) -{ - int byte, i; - long quad = 0; - - /* Check sign on first byte before reading others */ - byte = get_and_buffer_unsigned_byte(file); - quad = byte; - if (quad >= 0x80) - quad = byte - 0x100; - for (i=0; i<3; i++) { - quad = quad*0x100 + get_and_buffer_unsigned_byte(file); - } - return (SIGNED_QUAD) quad; -} - -static UNSIGNED_QUAD get_and_buffer_unsigned_quad(FILE *file) -{ - int i; - unsigned long quad = 0; - for (i=0; i<4; i++) { - quad = quad*0x100u + get_and_buffer_unsigned_byte(file); - } - return (UNSIGNED_QUAD) quad; -} - -static void get_and_buffer_bytes(FILE *file, unsigned int count) -{ - if (dvi_page_buf_index + count >= dvi_page_buf_size) { - dvi_page_buf_size = dvi_page_buf_index + count + DVI_PAGE_BUF_CHUNK; - dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); - } - if (fread(dvi_page_buffer + dvi_page_buf_index, 1, count, file) != count) - ERROR ("File ended prematurely\n"); - dvi_page_buf_index += count; -} - -/* functions to fetch values from dvi_page_buffer */ - -static UNSIGNED_BYTE get_buffered_unsigned_byte (void) -{ - return dvi_page_buffer[dvi_page_buf_index++]; -} - -static SIGNED_BYTE get_buffered_signed_byte (void) -{ - int byte; - byte = dvi_page_buffer[dvi_page_buf_index++]; - if (byte >= 0x80) - byte -= 0x100; - return (SIGNED_BYTE) byte; -} - -static UNSIGNED_PAIR get_buffered_unsigned_pair (void) -{ - int i; - UNSIGNED_BYTE byte; - UNSIGNED_PAIR pair = 0; - for (i=0; i<2; i++) { - byte = dvi_page_buffer[dvi_page_buf_index++]; - pair = pair*0x100u + byte; - } - return pair; -} - -static SIGNED_PAIR get_buffered_signed_pair (void) -{ - int i; - long pair = 0; - for (i=0; i<2; i++) { - pair = pair*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - if (pair >= 0x8000) { - pair -= 0x10000l; - } - return (SIGNED_PAIR) pair; -} - -static UNSIGNED_TRIPLE get_buffered_unsigned_triple(void) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100u + dvi_page_buffer[dvi_page_buf_index++]; - } - return (UNSIGNED_TRIPLE) triple; -} - -static SIGNED_TRIPLE get_buffered_signed_triple(void) -{ - int i; - long triple = 0; - for (i=0; i<3; i++) { - triple = triple*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - if (triple >= 0x800000l) - triple -= 0x1000000l; - return (SIGNED_TRIPLE) triple; -} - -static SIGNED_QUAD get_buffered_signed_quad(void) -{ - int byte, i; - long quad = 0; - - /* Check sign on first byte before reading others */ - byte = dvi_page_buffer[dvi_page_buf_index++]; - quad = byte; - if (quad >= 0x80) - quad = byte - 0x100; - for (i=0; i<3; i++) { - quad = quad*0x100 + dvi_page_buffer[dvi_page_buf_index++]; - } - return (SIGNED_QUAD) quad; -} - -static UNSIGNED_QUAD get_buffered_unsigned_quad(void) -{ - int i; - unsigned long quad = 0; - for (i=0; i<4; i++) { - quad = quad*0x100u + dvi_page_buffer[dvi_page_buf_index++]; - } - return (UNSIGNED_QUAD) quad; -} -#else -#define get_and_buffer_unsigned_byte(fp) get_unsigned_byte(fp) -#if 0 -#define get_and_buffer_signed_byte(fp) get_signed_byte(fp) -#endif -#define get_and_buffer_unsigned_pair(fp) get_unsigned_pair(fp) -#define get_and_buffer_signed_pair(fp) get_signed_pair(fp) -#define get_and_buffer_unsigned_triple(fp) get_unsigned_triple(fp) -#define get_and_buffer_signed_triple(fp) get_signed_triple(fp) -#define get_and_buffer_signed_quad(fp) get_unsigned_quad(fp) -#define get_and_buffer_unsigned_quad(fp) get_unsigned_quad(fp) -#define get_and_buffer_bytes(fp, ct) seek_relative(fp, ct) - -#define get_buffered_unsigned_byte() get_unsigned_byte(dvi_file) -#define get_buffered_signed_byte() get_signed_byte(dvi_file) -#define get_buffered_unsigned_pair() get_unsigned_pair(dvi_file) -#define get_buffered_signed_pair() get_signed_pair(dvi_file) -#define get_buffered_unsigned_triple() get_unsigned_triple(dvi_file) -#define get_buffered_signed_triple() get_signed_triple(dvi_file) -#define get_buffered_signed_quad() get_signed_quad(dvi_file) -#define get_buffered_unsigned_quad() get_unsigned_quad(dvi_file) -#endif - -void -dvi_set_verbose (void) -{ - verbose++; - subfont_set_verbose(); - tfm_set_verbose(); - vf_set_verbose (); - spc_set_verbose(); -} - -unsigned -dvi_npages (void) -{ - return num_pages; -} - -static const char invalid_signature[] = -"Something is wrong. Are you sure this is a DVI file?"; - -#define range_check_loc(loc) \ - if ((loc) > dvi_file_size) {\ - ERROR(invalid_signature); \ - } - -static long -find_post (void) -{ - long current; - int ch; - - /* First find end of file */ - dvi_file_size = file_size(dvi_file); - current = dvi_file_size; - - /* Scan backwards through PADDING */ - do { - current--; - seek_absolute(dvi_file, current); - } while ((ch = fgetc(dvi_file)) == PADDING && - current > 0); - - /* file_position now points to last non padding character or - * beginning of file */ - if (dvi_file_size - current < 4 || current == 0 || -#ifdef XETEX - !(ch == DVI_ID || ch == DVIV_ID || ch == XDVI_ID)) { -#else - !(ch == DVI_ID || ch == DVIV_ID)) { -#endif - MESG("DVI ID = %d\n", ch); - ERROR(invalid_signature); - } - - /* Make sure post_post is really there */ - current = current - 5; - seek_absolute(dvi_file, current); - if ((ch = fgetc(dvi_file)) != POST_POST) { - MESG("Found %d where post_post opcode should be\n", ch); - ERROR(invalid_signature); - } - current = get_signed_quad(dvi_file); - seek_absolute(dvi_file, current); - if ((ch = fgetc(dvi_file)) != POST) { - MESG("Found %d where post_post opcode should be\n", ch); - ERROR(invalid_signature); - } - - return current; -} - -static void -get_page_info (long post_location) -{ - int i; - - seek_absolute(dvi_file, post_location + 27); - num_pages = get_unsigned_pair(dvi_file); - if (num_pages == 0) { - ERROR("Page count is 0!"); - } - if (verbose > 2) { - MESG("Page count:\t %4d\n", num_pages); - } - - page_loc = NEW(num_pages, unsigned long); - - seek_absolute(dvi_file, post_location + 1); - page_loc[num_pages-1] = get_unsigned_quad(dvi_file); - range_check_loc(page_loc[num_pages-1] + 41); - for (i = num_pages - 2; i >= 0; i--) { - seek_absolute(dvi_file, page_loc[i+1] + 41); - page_loc[i] = get_unsigned_quad(dvi_file); - range_check_loc(page_loc[num_pages-1] + 41); - } -} - -/* Following are computed "constants" used for unit conversion */ -static double dvi2pts = 1.52018, total_mag = 1.0; - -double -dvi_tell_mag (void) -{ - return total_mag; -} - -static void -do_scales (double mag) -{ - total_mag = (double) dvi_info.mag / 1000.0 * mag; - dvi2pts = (double) dvi_info.unit_num / (double) dvi_info.unit_den; - dvi2pts *= (72.0 / 254000.0); -} - -static void -get_dvi_info (long post_location) -{ - seek_absolute(dvi_file, post_location + 5); - - dvi_info.unit_num = get_unsigned_quad(dvi_file); - dvi_info.unit_den = get_unsigned_quad(dvi_file); - dvi_info.mag = get_unsigned_quad(dvi_file); - - dvi_info.media_height = get_unsigned_quad(dvi_file); - dvi_info.media_width = get_unsigned_quad(dvi_file); - - dvi_info.stackdepth = get_unsigned_pair(dvi_file); - - if (dvi_info.stackdepth > DVI_STACK_DEPTH_MAX) { - WARN("DVI need stack depth of %d,", dvi_info.stackdepth); - WARN("but DVI_STACK_DEPTH_MAX is %d.", DVI_STACK_DEPTH_MAX); - ERROR("Capacity exceeded."); - } - - if (verbose > 2) { - MESG("DVI File Info\n"); - MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den); - MESG("Magnification: %ld\n", dvi_info.mag); - MESG("Media Height: %ld\n", dvi_info.media_height); - MESG("Media Width: %ld\n", dvi_info.media_width); - MESG("Stack Depth: %d\n", dvi_info.stackdepth); - } -} - -static void -get_preamble_dvi_info (void) -{ - UNSIGNED_BYTE ch; - - ch = get_unsigned_byte(dvi_file); - if (ch != PRE) { - MESG("Found %d where PRE was expected\n", ch); - ERROR(invalid_signature); - } - - ch = get_unsigned_byte(dvi_file); -#ifdef XETEX - if (!(ch == DVI_ID || ch == DVIV_ID || ch == XDVI_ID)) { -#else - if (!(ch == DVI_ID || ch == DVIV_ID)) { -#endif - MESG("DVI ID = %d\n", ch); - ERROR(invalid_signature); - } - - dvi_info.unit_num = get_unsigned_quad(dvi_file); - dvi_info.unit_den = get_unsigned_quad(dvi_file); - dvi_info.mag = get_unsigned_quad(dvi_file); - - ch = get_unsigned_byte(dvi_file); - if (fread(dvi_info.comment, - 1, ch, dvi_file) != ch) { - ERROR(invalid_signature); - } - dvi_info.comment[ch] = '\0'; - - if (verbose > 2) { - MESG("DVI File Info\n"); - MESG("Unit: %ld / %ld\n", dvi_info.unit_num, dvi_info.unit_den); - MESG("Magnification: %ld\n", dvi_info.mag); - } - - if (verbose) { - MESG("DVI Comment: %s\n", dvi_info.comment); - } - - num_pages = 0x7FFFFFFUL; /* for linear processing: we just keep going! */ -} - -const char * -dvi_comment (void) -{ - return dvi_info.comment; -} - -static void -read_font_record (SIGNED_QUAD tex_id) -{ - UNSIGNED_BYTE dir_length, name_length; - UNSIGNED_QUAD point_size, design_size; - char *directory, *font_name; - - if (num_def_fonts >= max_def_fonts) { - max_def_fonts += TEX_FONTS_ALLOC_SIZE; - def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def); - } - get_unsigned_quad(dvi_file); - point_size = get_unsigned_quad(dvi_file); - design_size = get_unsigned_quad(dvi_file); - dir_length = get_unsigned_byte(dvi_file); - name_length = get_unsigned_byte(dvi_file); - - directory = NEW(dir_length + 1, char); - if (fread(directory, 1, dir_length, dvi_file) != dir_length) { - ERROR(invalid_signature); - } - directory[dir_length] = '\0'; - RELEASE(directory); /* unused */ - - font_name = NEW(name_length + 1, char); - if (fread(font_name, 1, name_length, dvi_file) != name_length) { - ERROR(invalid_signature); - } - font_name[name_length] = '\0'; - def_fonts[num_def_fonts].tex_id = tex_id; - def_fonts[num_def_fonts].font_name = font_name; - def_fonts[num_def_fonts].point_size = point_size; - def_fonts[num_def_fonts].design_size = design_size; - def_fonts[num_def_fonts].used = 0; -#ifdef XETEX - def_fonts[num_def_fonts].native = 0; - 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++; - - return; -} - -#ifdef XETEX -static void -read_native_font_record (SIGNED_QUAD tex_id) -{ - UNSIGNED_PAIR flags; - UNSIGNED_QUAD point_size; - char *font_name; - int plen, flen, slen, i; - - if (num_def_fonts >= max_def_fonts) { - max_def_fonts += TEX_FONTS_ALLOC_SIZE; - def_fonts = RENEW (def_fonts, max_def_fonts, struct font_def); - } - point_size = get_unsigned_quad(dvi_file); - flags = get_unsigned_pair(dvi_file); - - plen = (int) get_unsigned_byte(dvi_file); /* PS name length */ - flen = (int) get_unsigned_byte(dvi_file); /* family name length */ - slen = (int) get_unsigned_byte(dvi_file); /* style name length */ - font_name = NEW(plen + 1, char); - if (fread(font_name, 1, plen, dvi_file) != plen) { - ERROR(invalid_signature); - } - font_name[plen] = '\0'; - - /* ignore family and style names */ - for (i = 0; i < flen + slen; ++i) - get_unsigned_byte(dvi_file); - - def_fonts[num_def_fonts].tex_id = tex_id; - def_fonts[num_def_fonts].font_name = font_name; - def_fonts[num_def_fonts].point_size = point_size; - def_fonts[num_def_fonts].design_size = 655360; /* hard-code as 10pt for now, not used anyway */ - def_fonts[num_def_fonts].used = 0; - def_fonts[num_def_fonts].native = 1; - - def_fonts[num_def_fonts].layout_dir = 0; - def_fonts[num_def_fonts].rgba_color = 0xffffffff; - def_fonts[num_def_fonts].extend = 0x00010000; - def_fonts[num_def_fonts].slant = 0; - def_fonts[num_def_fonts].embolden = 0; - - if (flags & XDV_FLAG_VERTICAL) - def_fonts[num_def_fonts].layout_dir = 1; - - if (flags & XDV_FLAG_COLORED) - def_fonts[num_def_fonts].rgba_color = get_unsigned_quad(dvi_file); - - if (flags & XDV_FLAG_EXTEND) - def_fonts[num_def_fonts].extend = get_signed_quad(dvi_file); - - if (flags & XDV_FLAG_SLANT) - def_fonts[num_def_fonts].slant = get_signed_quad(dvi_file); - - if (flags & XDV_FLAG_EMBOLDEN) - def_fonts[num_def_fonts].embolden = get_signed_quad(dvi_file); - - if (flags & XDV_FLAG_VARIATIONS) { - int v, nvars = get_unsigned_pair(dvi_file); - for (v = 0; v < nvars * 2; ++v) - (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); - } - - num_def_fonts++; - - return; -} -#endif - -static void -get_dvi_fonts (long post_location) -{ - UNSIGNED_BYTE code; - SIGNED_QUAD tex_id = 0; - - seek_absolute(dvi_file, post_location + 29); - while ((code = get_unsigned_byte(dvi_file)) != POST_POST) { - switch (code) { - case FNT_DEF1: - tex_id = get_unsigned_byte(dvi_file); - break; - case FNT_DEF2: - tex_id = get_unsigned_pair(dvi_file); - break; - case FNT_DEF3: - tex_id = get_unsigned_triple(dvi_file); - break; - case FNT_DEF4: -#ifdef XETEX - case XDV_NATIVE_FONT_DEF: -#endif - tex_id = get_signed_quad(dvi_file); - break; - default: - MESG("Unexpected op code: %3d\n", code); - ERROR(invalid_signature); - } -#ifdef XETEX - if (code == XDV_NATIVE_FONT_DEF) - read_native_font_record(tex_id); - else -#endif - read_font_record(tex_id); - } - if (verbose > 2) { - unsigned i; - - MESG("\n"); - MESG("DVI file font info\n"); - for (i = 0; i < num_def_fonts; i++) { - MESG("TeX Font: %10s loaded at ID=%5ld, ", - def_fonts[i].font_name, def_fonts[i].tex_id); - MESG("size=%5.2fpt (scaled %4.1f%%)", - def_fonts[i].point_size * dvi2pts, - 100.0 * ((double) def_fonts[i].point_size / def_fonts[i].design_size)); - MESG("\n"); - } - } -} - -static void get_comment (void) -{ - UNSIGNED_BYTE length; - - seek_absolute(dvi_file, 14); - length = get_unsigned_byte(dvi_file); - if (fread(dvi_info.comment, - 1, length, dvi_file) != length) { - ERROR(invalid_signature); - } - dvi_info.comment[length] = '\0'; - if (verbose) { - MESG("DVI Comment: %s\n", dvi_info.comment); - } -} - -/* - * The section below this line deals with the actual processing of the - * dvi file. - * - * The dvi file processor state is contained in the following variables: - */ - -struct dvi_registers -{ - SIGNED_QUAD h, v, w, x, y, z, d; -}; - -static struct dvi_registers dvi_state; -static struct dvi_registers dvi_stack[DVI_STACK_DEPTH_MAX]; -static unsigned dvi_stack_depth = 0 ; -static int current_font = -1; -static int processing_page = 0 ; - -static void -clear_state (void) -{ - dvi_state.h = 0; dvi_state.v = 0; dvi_state.w = 0; - dvi_state.x = 0; dvi_state.y = 0; dvi_state.z = 0; - dvi_state.d = 0; /* direction */ - dvi_stack_depth = 0; - current_font = -1; -} - -/* Migrated from pdfdev.c: - * The following codes are originally put into pdfdev.c. - * But they are moved to here to make PDF output independent - * from DVI input. - * pdfdoc, pdfspecial and htex are also modified. pdfspecial - * and htex does tag/untag depth. pdfdev and pdfdoc now does - * not care about line-breaking at all. - */ -static unsigned marked_depth = 0; -static int tagged_depth = -1; - -static void -dvi_mark_depth (void) -{ - /* If decreasing below tagged_depth */ - if (link_annot && - marked_depth == tagged_depth && - dvi_stack_depth == tagged_depth - 1) { - /* - * See if this appears to be the end of a "logical unit" - * that's been broken. If so, flush the logical unit. - */ - pdf_doc_break_annot(); - } - marked_depth = dvi_stack_depth; -} - -/* - * The following routines setup and tear down a callback at a - * certain stack depth. This is used to handle broken (linewise) - * links. - */ -void -dvi_tag_depth (void) -{ - tagged_depth = marked_depth; - dvi_compute_boxes(1); -} - -void -dvi_untag_depth (void) -{ - tagged_depth = -1; - dvi_compute_boxes(0); -} - -void -dvi_compute_boxes (int flag) -{ - compute_boxes = flag; -} - -void -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) -{ - double x_user, y_user, mag; - const char *p; - - if (size > 0x7fffffffUL) { - WARN("Special more than %ul bytes???", size); - return; - } - - graphics_mode(); - - p = (const char *) buffer; - - x_user = dvi_state.h * dvi2pts; - y_user = -dvi_state.v * dvi2pts; - mag = dvi_tell_mag(); - - if (spc_exec_special(p, (long) size, x_user, y_user, mag) < 0) { - if (verbose) { - dump(p, p + size); - } - } - - return; -} - -double -dvi_unit_size (void) -{ - return dvi2pts; -} - - -int -dvi_locate_font (const char *tfm_name, spt_t ptsize) -{ - int cur_id = -1; - const char *name = tfm_name; - int subfont_id = -1, font_id; /* VF or device font ID */ - fontmap_rec *mrec; - - if (verbose) - MESG("<%s@%.2fpt", tfm_name, ptsize * dvi2pts); - - need_more_fonts(1); - - /* This routine needs to be recursive/reentrant. Load current high water - * mark into an automatic variable. - */ - cur_id = num_loaded_fonts++; - - mrec = pdf_lookup_fontmap_record(tfm_name); - /* Load subfont mapping table */ - if (mrec && mrec->charmap.sfd_name && mrec->charmap.subfont_id) { - subfont_id = sfd_load_record(mrec->charmap.sfd_name, mrec->charmap.subfont_id); - } - - /* TFM must exist here. */ - loaded_fonts[cur_id].tfm_id = tfm_open(tfm_name, 1); - loaded_fonts[cur_id].subfont_id = subfont_id; - loaded_fonts[cur_id].size = ptsize; - /* This will be reset later if it was really generated by the dvi file. */ - loaded_fonts[cur_id].source = VF; - - /* The order of searching fonts is as follows: - * - * 1. If mrec is null, that is, there is no map entry matching - * with tfm_name, then search a virtual font matching with - * tfm_name at first. If no virtual font is found, search a - * PK font matching with tfm_name. - * - * 2. If mrec is non-null, search a physical scalable font. - * - * 3. Notice that every subfont gets non-null mrec. In this case, - * enc_name corresponding to mrec will be used instead of mrec. - * That is enc_name is NULL, search a virtual font for Omega (.ovf) - * matching with the base name of the subfont. If no virtual font - * for Omega is found, it is a fatal error because there is no PK font - * for Omega. - */ - if (!mrec) { - font_id = vf_locate_font(tfm_name, ptsize); - if (font_id >= 0) { - loaded_fonts[cur_id].type = VIRTUAL; - loaded_fonts[cur_id].font_id = font_id; - if (verbose) - MESG("(VF)>"); - return cur_id; - } - } -#if 1 - /* Sorry, I don't understand this well... Please fix. - * The purpose of this seems to be: - * - * Map 8-bit char codes in subfont to 16-bit code with SFD mapping - * and map subfonts to single OVF font. - * - * But it apparently only does TFM -> OVF mapping but no character - * code mapping. Please see dvi_set(), you can't have both font->type - * VIRTUAL and font->subfont_id >= 0. Am I missing something? - */ - else if (subfont_id >= 0 && mrec->map_name) - { - fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); - /* enc_name=NULL should be used only for 'built-in' encoding. - * Please fix this! - */ - if (mrec1 && !mrec1->enc_name) { - font_id = vf_locate_font(mrec1->font_name, ptsize); - if (font_id < 0) - WARN("Could not locate Omega Virtual Font \"%s\" for \"%s\".", - mrec1->font_name, tfm_name); - else { - loaded_fonts[cur_id].type = VIRTUAL; - loaded_fonts[cur_id].font_id = font_id; - if (verbose) - MESG("(OVF)>"); - return cur_id; - } - } - } -#endif /* 1 */ - - /* Failed to load a virtual font so we try to load a physical font. */ - - /* If mrec->map_name is not NULL, font name identified in PDF output - * is different than tfm_name, this can happen for subfonts grouped - * into a single "intermediate" font foo@SFD@. - * This is necessary for optimal output; to avoid unnecessary creation - * of multiple instances of a same font, to avoid frequent font selection - * and break of string_mode. - */ - if (mrec && mrec->map_name) { - name = mrec->map_name; - } else { - name = tfm_name; - } - - /* We need ptsize for PK font creation. */ - font_id = pdf_dev_locate_font(name, ptsize); - if (font_id < 0) { - WARN("Could not locate a virtual/physical font for TFM \"%s\".", tfm_name); - if (mrec && mrec->map_name) { /* has map_name */ - fontmap_rec *mrec1 = pdf_lookup_fontmap_record(mrec->map_name); - WARN(">> This font is mapped to an intermediate 16-bit font \"%s\" with SFD charmap=<%s,%s>,", - mrec->map_name, mrec->charmap.sfd_name, mrec->charmap.subfont_id); - if (!mrec1) - WARN(">> but I couldn't find font mapping for \"%s\".", mrec->map_name); - else { - WARN(">> and then mapped to a physical font \"%s\" by fontmap.", mrec1->font_name); - WARN(">> Please check if kpathsea library can find this font: %s", mrec1->font_name); - } - } else if (mrec && !mrec->map_name) { - WARN(">> This font is mapped to a physical font \"%s\".", mrec->font_name); - WARN(">> Please check if kpathsea library can find this font: %s", mrec->font_name); - } else { - WARN(">> There are no valid font mapping entry for this font."); - WARN(">> Font file name \"%s\" was assumed but failed to locate that font.", tfm_name); - } - ERROR("Cannot proceed without .vf or \"physical\" font for PDF output..."); - } - loaded_fonts[cur_id].type = PHYSICAL; - loaded_fonts[cur_id].font_id = font_id; - - if (verbose) - MESG(">"); - - return cur_id; -} - -#ifdef XETEX -static int -dvi_locate_native_font (const char *ps_name, - spt_t ptsize, int layout_dir, int extend, int slant, int embolden) -{ - int cur_id = -1; - fontmap_rec *mrec; - char *fontmap_key = malloc(strlen(ps_name) + 40); // CHECK this is enough - - if (verbose) - MESG("<%s@%.2fpt", ps_name, ptsize * dvi2pts); - - need_more_fonts(1); - - cur_id = num_loaded_fonts++; - - 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, layout_dir, extend, slant, embolden) == -1) { - ERROR("Cannot proceed without the \"native\" font: %s", ps_name); - } - mrec = pdf_lookup_fontmap_record(fontmap_key); - /* FIXME: would be more efficient if pdf_load_native_font returned the mrec ptr (or NULL for error) - so we could avoid doing a second lookup for the item we just inserted */ - } - loaded_fonts[cur_id].font_id = pdf_dev_locate_font(fontmap_key, ptsize); - loaded_fonts[cur_id].size = ptsize; - loaded_fonts[cur_id].type = NATIVE; - free(fontmap_key); - - loaded_fonts[cur_id].ft_face = mrec->opt.ft_face; - 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(">"); - - return cur_id; -} -#endif - -double -dvi_dev_xpos (void) -{ - return dvi_state.h * dvi2pts; -} - -double -dvi_dev_ypos (void) -{ - return -(dvi_state.v * dvi2pts); -} - -static void do_moveto (SIGNED_QUAD x, SIGNED_QUAD y) -{ - dvi_state.h = x; - dvi_state.v = y; -} - -void dvi_right (SIGNED_QUAD x) -{ - if (!dvi_state.d) { - dvi_state.h += x; - } else { - dvi_state.v += x; - } -} - -void dvi_down (SIGNED_QUAD y) -{ - if (!dvi_state.d) { - dvi_state.v += y; - } else { - dvi_state.h -= y; - } -} - -/* Please remove this. - * Optimization for 8-bit encodings. - */ -static void -do_string (unsigned char *s, int len) -{ - struct loaded_font *font; - spt_t width, height, depth; - int i; - - if (current_font < 0) - ERROR("No font selected!"); - - font = &loaded_fonts[current_font]; - - width = tfm_string_width(font->tfm_id, s, len); - width = sqxfw(font->size, width); - - switch (font->type) { - case PHYSICAL: - if (font->subfont_id < 0) { - pdf_dev_set_string(dvi_state.h, -dvi_state.v, s, len, - width, font->font_id, 1); - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_string_height(font->tfm_id, s, len); - depth = tfm_string_depth (font->tfm_id, s, len); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - } else { /* Subfonts */ - dvi_push(); - for (i = 0; i < len; i++) { - dvi_set(s[i]); - } - dvi_pop(); - } - break; - case VIRTUAL: - dvi_push(); - for (i = 0; i < len; i++) { - dvi_set(s[i]); - } - dvi_pop(); - } - if (!dvi_state.d) { - dvi_state.h += width; - } else { - dvi_state.v += width; - } -} - -/* _FIXME_ - * CMap decoder wants multibyte strings as input but - * how DVI char codes are converted to multibyte sting - * is not clear. - */ -void -dvi_set (SIGNED_QUAD ch) -{ - struct loaded_font *font; - spt_t width, height, depth; - unsigned char wbuf[2]; - - if (current_font < 0) { - ERROR("No font selected!"); - } - /* The division by dvi2pts seems strange since we actually know the - * "dvi" size of the fonts contained in the DVI file. In other - * words, we converted from DVI units to pts and back again! - * The problem comes from fonts defined in VF files where we don't know - * the DVI size. It's keeping me sane to keep *point sizes* of *all* - * fonts in the dev.c file and convert them back if necessary. - */ - font = &loaded_fonts[current_font]; - - width = tfm_get_fw_width(font->tfm_id, ch); - width = sqxfw(font->size, width); - - switch (font->type) { - case PHYSICAL: - if (ch > 255) { /* _FIXME_ */ - wbuf[0] = (ch >> 8) & 0xff; - wbuf[1] = ch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else if (font->subfont_id >= 0) { - unsigned short uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); - wbuf[0] = (uch >> 8) & 0xff; - wbuf[1] = uch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else { - wbuf[0] = (unsigned char) ch; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, - width, font->font_id, 1); - } - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_get_fw_height(font->tfm_id, ch); - depth = tfm_get_fw_depth (font->tfm_id, ch); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - break; - case VIRTUAL: -#if 0 - /* See comment in locate_font() */ - if (font->subfont_id >= 0) - ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); -#endif /* 0 */ - vf_set_char(ch, font->font_id); /* push/pop invoked */ - break; - } - - if (!dvi_state.d) { - dvi_state.h += width; - } else { - dvi_state.v += width; - } -} - -void -dvi_put (SIGNED_QUAD ch) -{ - struct loaded_font *font; - spt_t width, height, depth; - unsigned char wbuf[2]; - - if (current_font < 0) { - ERROR("No font selected!"); - } - - font = &loaded_fonts[current_font]; - - switch (font->type) { - case PHYSICAL: - width = tfm_get_fw_width(font->tfm_id, ch); - width = sqxfw(font->size, width); - - /* Treat a single character as a one byte string and use the - * string routine. - */ - if (ch > 255) { /* _FIXME_ */ - wbuf[0] = (ch >> 8) & 0xff; - wbuf[1] = ch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else if (font->subfont_id >= 0) { - unsigned int uch; - - uch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); - wbuf[0] = (uch >> 8) & 0xff; - wbuf[1] = uch & 0xff; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 2, - width, font->font_id, 2); - } else { - wbuf[0] = (unsigned char) ch; - pdf_dev_set_string(dvi_state.h, -dvi_state.v, wbuf, 1, - width, font->font_id, 1); - } - if (compute_boxes && link_annot && - marked_depth >= tagged_depth) { - pdf_rect rect; - - height = tfm_get_fw_height(font->tfm_id, ch); - depth = tfm_get_fw_depth (font->tfm_id, ch); - height = sqxfw(font->size, height); - depth = sqxfw(font->size, depth); - - pdf_dev_set_rect (&rect, dvi_state.h, -dvi_state.v, - width, height, depth); - pdf_doc_expand_box(&rect); - } - break; - case VIRTUAL: -#if 0 - /* See comment in locate_font() */ - if (font->subfont_id >= 0) - ch = lookup_sfd_record(font->subfont_id, (unsigned char) ch); -#endif /* 0 */ - vf_set_char(ch, font->font_id); - break; - } - - return; -} - - -void -dvi_rule (SIGNED_QUAD width, SIGNED_QUAD height) -{ - do_moveto(dvi_state.h, dvi_state.v); - - if (!dvi_state.d) { - pdf_dev_set_rule(dvi_state.h, -dvi_state.v, width, height); - } else { /* right ? */ - pdf_dev_set_rule(dvi_state.h, -dvi_state.v - width, height, width); - } -} - -void -dvi_dir (UNSIGNED_BYTE dir) -{ - dvi_state.d = dir ? 1 : 0; - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - -static void -do_set1 (void) -{ - dvi_set(get_buffered_unsigned_byte()); -} - -static void -do_set2 (void) -{ - dvi_set(get_buffered_unsigned_pair()); -} - -static void -do_setrule (void) -{ - SIGNED_QUAD width, height; - - height = get_buffered_signed_quad(); - width = get_buffered_signed_quad(); - if (width > 0 && height > 0) { - dvi_rule(width, height); - } - dvi_right(width); -} - -static void -do_putrule (void) -{ - SIGNED_QUAD width, height; - - height = get_buffered_signed_quad (); - width = get_buffered_signed_quad (); - if (width > 0 && height > 0) { - dvi_rule(width, height); - } -} - -static void -do_put1 (void) -{ - dvi_put(get_buffered_unsigned_byte()); -} - -static void -do_put2 (void) -{ - dvi_put(get_buffered_unsigned_pair()); -} - -void -dvi_push (void) -{ - if (dvi_stack_depth >= DVI_STACK_DEPTH_MAX) - ERROR("DVI stack exceeded limit."); - - dvi_stack[dvi_stack_depth++] = dvi_state; -} - -void -dvi_pop (void) -{ - if (dvi_stack_depth <= 0) - ERROR ("Tried to pop an empty stack."); - - dvi_state = dvi_stack[--dvi_stack_depth]; - do_moveto(dvi_state.h, dvi_state.v); - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - - -static void -do_right1 (void) -{ - dvi_right(get_buffered_signed_byte()); -} - -static void -do_right2 (void) -{ - dvi_right(get_buffered_signed_pair()); -} - -static void -do_right3 (void) -{ - dvi_right(get_buffered_signed_triple()); -} - -static void -do_right4 (void) -{ - dvi_right(get_buffered_signed_quad()); -} - -void -dvi_w (SIGNED_QUAD ch) -{ - dvi_state.w = ch; - dvi_right(ch); -} - -void -dvi_w0 (void) -{ - dvi_right(dvi_state.w); -} - -static void -do_w1 (void) -{ - dvi_w(get_buffered_signed_byte()); -} - -static void -do_w2 (void) -{ - dvi_w(get_buffered_signed_pair()); -} - -static void -do_w3 (void) -{ - dvi_w(get_buffered_signed_triple()); -} - -static void -do_w4 (void) -{ - dvi_w(get_buffered_signed_quad()); -} - -void -dvi_x (SIGNED_QUAD ch) -{ - dvi_state.x = ch; - dvi_right(ch); -} - -void -dvi_x0 (void) -{ - dvi_right(dvi_state.x); -} - -static void -do_x1 (void) -{ - dvi_x(get_buffered_signed_byte()); -} - -static void -do_x2 (void) -{ - dvi_x(get_buffered_signed_pair()); -} - -static void -do_x3 (void) -{ - dvi_x(get_buffered_signed_triple()); -} - -static void -do_x4 (void) -{ - dvi_x(get_buffered_signed_quad()); -} - -static void -do_down1 (void) -{ - dvi_down(get_buffered_signed_byte()); -} - -static void -do_down2 (void) -{ - dvi_down(get_buffered_signed_pair()); -} - -static void -do_down3 (void) -{ - dvi_down(get_buffered_signed_triple()); -} - -static void -do_down4 (void) -{ - dvi_down(get_buffered_signed_quad()); -} - -void -dvi_y (SIGNED_QUAD ch) -{ - dvi_state.y = ch; - dvi_down(ch); -} - -void -dvi_y0 (void) -{ - dvi_down(dvi_state.y); -} - -static -void do_y1 (void) -{ - dvi_y(get_buffered_signed_byte()); -} - -static -void do_y2 (void) -{ - dvi_y(get_buffered_signed_pair()); -} - -static -void do_y3 (void) -{ - dvi_y(get_buffered_signed_triple()); -} - -static -void do_y4 (void) -{ - dvi_y(get_buffered_signed_quad()); -} - -void -dvi_z (SIGNED_QUAD ch) -{ - dvi_state.z = ch; - dvi_down(ch); -} - -void -dvi_z0 (void) -{ - dvi_down(dvi_state.z); -} - -static void -do_z1 (void) -{ - dvi_z(get_buffered_signed_byte()); -} - -static void -do_z2 (void) -{ - dvi_z(get_buffered_signed_pair()); -} - -static void -do_z3 (void) -{ - dvi_z(get_buffered_signed_triple()); -} - -static void -do_z4 (void) -{ - dvi_z(get_buffered_signed_quad()); -} - -static void -skip_fntdef (void) -{ - int area_len, name_len, i; - - get_signed_quad(dvi_file); - get_signed_quad(dvi_file); - get_signed_quad(dvi_file); - area_len = get_unsigned_byte(dvi_file); - name_len = get_unsigned_byte(dvi_file); - for (i = 0; i < area_len + name_len; i++) { - get_unsigned_byte(dvi_file); - } -} - -static void -do_fntdef1 (int scanning) -{ - if (scanning) { - /* when pre-scanning the page, we process fntdef and don't buffer it */ - SIGNED_QUAD tex_id = get_unsigned_byte(dvi_file); - if (linear) { - read_font_record(tex_id); - } - else { - skip_fntdef(); - } - --dvi_page_buf_index; /* remove the fntdef opcode from the buffer */ - } -} - -static void -do_fntdef2 (int scanning) -{ - if (scanning) { - SIGNED_QUAD tex_id = get_unsigned_pair(dvi_file); - if (linear) { - read_font_record(tex_id); - } - else { - skip_fntdef(); - } - --dvi_page_buf_index; - } -} - -static void -do_fntdef3 (int scanning) -{ - if (scanning) { - SIGNED_QUAD tex_id = get_unsigned_triple(dvi_file); - if (linear) { - read_font_record(tex_id); - } - else { - skip_fntdef(); - } - --dvi_page_buf_index; - } -} - -static void -do_fntdef4 (int scanning) -{ - if (scanning) { - SIGNED_QUAD tex_id = get_signed_quad(dvi_file); - if (linear) { - read_font_record(tex_id); - } - else { - skip_fntdef(); - } - --dvi_page_buf_index; - } -} - -void -dvi_set_font (int font_id) -{ - current_font = font_id; -} - -static void -do_fnt (SIGNED_QUAD tex_id) -{ - int i; - - for (i = 0; i < num_def_fonts; i++) { - if (def_fonts[i].tex_id == tex_id) - break; - } - - if (i == num_def_fonts) { - ERROR("Tried to select a font that hasn't been defined: id=%ld", tex_id); - } - - if (!def_fonts[i].used) { - int font_id; - -#ifdef XETEX - if (def_fonts[i].native) { - font_id = dvi_locate_native_font(def_fonts[i].font_name, - def_fonts[i].point_size, - 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); - } - loaded_fonts[font_id].rgba_color = def_fonts[i].rgba_color; -#else - font_id = dvi_locate_font(def_fonts[i].font_name, def_fonts[i].point_size); -#endif - loaded_fonts[font_id].source = DVI; - def_fonts[i].used = 1; - def_fonts[i].font_id = font_id; - } - current_font = def_fonts[i].font_id; -} - -static void -do_fnt1 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_byte(); - do_fnt(tex_id); -} - -static void -do_fnt2 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_pair(); - do_fnt(tex_id); -} - -static void -do_fnt3 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_unsigned_triple(); - do_fnt(tex_id); -} - -static void -do_fnt4 (void) -{ - SIGNED_QUAD tex_id; - - tex_id = get_buffered_signed_quad(); - do_fnt(tex_id); -} - -static void -do_xxx (UNSIGNED_QUAD size) -{ -#ifdef XETEX - dvi_do_special(dvi_page_buffer + dvi_page_buf_index, size); - dvi_page_buf_index += size; -#else - UNSIGNED_QUAD i; - Ubyte *buffer; - - buffer = NEW(size+1, Ubyte); - for (i = 0; i < size; i++) { - buffer[i] = get_buffered_unsigned_byte(); - } - dvi_do_special(buffer, size); - RELEASE(buffer); -#endif -} - -static void -do_xxx1 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_byte(); - do_xxx(size); -} - -static void -do_xxx2 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_pair(); - do_xxx(size); -} - -static void -do_xxx3 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_triple(); - do_xxx(size); -} - -static void -do_xxx4 (void) -{ - SIGNED_QUAD size; - - size = get_buffered_unsigned_quad(); - do_xxx(size); -} - -static void -do_bop (void) -{ - int i; - - if (processing_page) - ERROR("Got a bop in the middle of a page!"); - - /* For now, ignore TeX's count registers */ - for (i = 0; i < 10; i++) { - get_buffered_signed_quad(); - } - /* Ignore previous page pointer since we have already - * saved this information - */ - get_buffered_signed_quad(); - clear_state(); - processing_page = 1; - - pdf_doc_begin_page(dvi_tell_mag(), dev_origin_x, dev_origin_y); - spc_exec_at_begin_page(); - - return; -} - -static void -do_eop (void) -{ - processing_page = 0; - - if (dvi_stack_depth != 0) { - ERROR("DVI stack depth is not zero at end of page"); - } - spc_exec_at_end_page(); - - pdf_doc_end_page(); - - return; -} - -static void -do_dir (void) -{ - dvi_state.d = get_buffered_unsigned_byte() ? 1 : 0; - pdf_dev_set_dirmode(dvi_state.d); /* 0: horizontal, 1: vertical */ -} - -#ifdef XETEX -static void -do_native_font_def (int scanning) -{ - if (scanning) { - SIGNED_QUAD tex_id = get_signed_quad(dvi_file); - if (linear) { - read_native_font_record(tex_id); - } else { - UNSIGNED_PAIR flags; - int name_length, nvars, i; - - get_unsigned_quad(dvi_file); /* skip point size */ - flags = get_unsigned_pair(dvi_file); - name_length = (int) get_unsigned_byte(dvi_file); - name_length += (int) get_unsigned_byte(dvi_file); - name_length += (int) get_unsigned_byte(dvi_file); - for (i = 0; i < name_length; ++i) - get_unsigned_byte(dvi_file); - if (flags & XDV_FLAG_COLORED) { - get_unsigned_quad(dvi_file); - } - if (flags & XDV_FLAG_VARIATIONS) { - nvars = get_unsigned_pair(dvi_file); - for (i = 0; i < nvars * 2; ++i) - get_unsigned_quad(dvi_file); /* skip axis and value for each variation setting */ - } - } - --dvi_page_buf_index; /* don't buffer the opcode */ - } -} - -static void -do_glyph_array (int yLocsPresent) -{ - struct loaded_font *font; - spt_t width, height, depth, *xloc, *yloc, glyph_width = 0; - unsigned char wbuf[2]; - unsigned int i, glyph_id, slen = 0; - - if (current_font < 0) - ERROR("No font selected!"); - - font = &loaded_fonts[current_font]; - - width = get_buffered_signed_quad(); - - slen = (unsigned int) get_buffered_unsigned_pair(); - xloc = NEW(slen, spt_t); - yloc = NEW(slen, spt_t); - for (i = 0; i < slen; i++) { - xloc[i] = get_buffered_signed_quad(); - yloc[i] = yLocsPresent ? get_buffered_signed_quad() : 0; - } - - if (font->rgba_color != 0xffffffff) { - pdf_color color; - 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_color_push(&color, &color); - } - - for (i = 0; i < slen; i++) { - glyph_id = get_buffered_unsigned_pair(); /* freetype glyph index */ - if (glyph_id < font->ft_face->num_glyphs) { - FT_Error error; - FT_Fixed advance; - int flags = FT_LOAD_NO_SCALE; - - if (font->layout_dir == 1) - flags |= FT_LOAD_VERTICAL_LAYOUT; - - error = FT_Get_Advance(font->ft_face, glyph_id, flags, &advance); - if (error) - advance = 0; - - glyph_width = (double)font->size * (double)advance / (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; - depth = (double)font->size * -(double)font->ft_face->descender / (double)font->ft_face->units_per_EM; - pdf_dev_set_rect(&rect, dvi_state.h + xloc[i], -dvi_state.v - yloc[i], glyph_width, height, depth); - pdf_doc_expand_box(&rect); - } - } - - wbuf[0] = glyph_id >> 8; - wbuf[1] = glyph_id & 0xff; - pdf_dev_set_string(dvi_state.h + xloc[i], -dvi_state.v - yloc[i], wbuf, 2, - glyph_width, font->font_id, -1); - } - - if (font->rgba_color != 0xffffffff) { - pdf_color_pop(); - } - RELEASE(xloc); - RELEASE(yloc); - - if (!dvi_state.d) { - dvi_state.h += width; - } else { - dvi_state.v += width; - } - - return; -} - -static void -do_pic_file(void) - /* parameters for XDV_PIC_FILE opcode: pdf_box[1] t[4][6] p[2] len[2] path[l] */ -{ - int page_no; - UNSIGNED_PAIR len; - char *path; - int i; - int xobj_id; - transform_info ti; - - transform_info_clear(&ti); - - /* pdf_box = */ get_buffered_unsigned_byte(); - - ti.matrix.a = get_buffered_signed_quad() / 65536.0; /* convert 16.16 Fixed to floating-point */ - ti.matrix.b = get_buffered_signed_quad() / 65536.0; - ti.matrix.c = get_buffered_signed_quad() / 65536.0; - ti.matrix.d = get_buffered_signed_quad() / 65536.0; - ti.matrix.e = get_buffered_signed_quad() / 65536.0; - ti.matrix.f = get_buffered_signed_quad() / 65536.0; - - page_no = get_buffered_signed_pair(); - len = get_buffered_unsigned_pair(); - path = NEW(len + 1, char); - for (i = 0; i < len; ++i) - path[i] = get_buffered_unsigned_byte(); - path[len] = 0; - - /* - now we need to place page /page_no/ of the graphic file from /path/, applying /transform/ - if pdf_box=0 the file is a raster image (.jpg, .png, .tif, etc; need to determine format - by examining the file) - else it is a PDF document, pdf_box tells which PDF box (media, trim, crop, etc) to use - page_no is currently only used with PDF documents, though in theory could be used - with multi-page TIFFs, etc - transform is a 3x2 affine transform matrix expressed in fixed-point values - */ - - xobj_id = pdf_ximage_findresource(path, page_no, NULL); - 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, - not just assume the "original" size is 100dpi - */ - pdf_dev_put_image(xobj_id, &ti, dvi_dev_xpos(), dvi_dev_ypos()); - } - - RELEASE(path); -} -#endif - -/* Note to be absolutely certain that the string escape buffer doesn't - * hit its limit, FORMAT_BUF_SIZE should set to 4 times S_BUFFER_SIZE - * in pdfobj.c. Is there any application that genenerate words with - * 1k characters? - */ - -#define SBUF_SIZE 1024 - -/* Most of the work of actually interpreting - * the dvi file is here. - */ -void -dvi_do_page (long n, - double paper_width, double paper_height, - double hmargin, double vmargin) -{ - unsigned char opcode; - unsigned char sbuf[SBUF_SIZE]; - unsigned int slen = 0; - - /* before this is called, we have scanned the page for papersize specials - and the complete DVI data is now in dvi_page_buffer */ - dvi_page_buf_index = 0; - - /* DVI coordinate */ - dev_origin_x = hmargin; - dev_origin_y = paper_height - vmargin; - - dvi_stack_depth = 0; - for (;;) { - /* The most likely opcodes are individual setchars. - * These are buffered for speed. */ - slen = 0; - while ((opcode = get_buffered_unsigned_byte()) <= SET_CHAR_127 && - slen < SBUF_SIZE) { - sbuf[slen++] = opcode; - } - if (slen > 0) { - do_string(sbuf, slen); - } - if (slen == SBUF_SIZE) - continue; - - /* If we are here, we have an opcode that is something - * other than SET_CHAR. - */ - if (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63) { - do_fnt(opcode - FNT_NUM_0); - continue; - } - - switch (opcode) { - case SET1: do_set1(); break; - case SET2: do_set2(); break; - case SET3: case SET4: - ERROR("Multibyte (>16 bits) character not supported!"); - break; - - case SET_RULE: - do_setrule(); - break; - - case PUT1: do_put1(); break; - case PUT2: do_put2(); break; - case PUT3: case PUT4: - ERROR ("Multibyte character (>16 bits) not supported!"); - break; - - case PUT_RULE: - do_putrule(); - break; - - case NOP: - break; - - case BOP: - do_bop(); - MESG("[%d", n+1); - break; - case EOP: - do_eop(); - MESG("]"); - return; - break; - - case PUSH: - dvi_push(); - /* The following line needs to go here instead of in - * dvi_push() since logical structure of document is - * oblivous to virtual fonts. For example the last line on a - * page could be at stack level 3 and the page footer should - * be at stack level 3. However, if the page footer contains - * virtual fonts (or other nested constructions), it could - * fool the link breaker into thinking it was a continuation - * of the link */ - dvi_mark_depth(); - break; - case POP: - dvi_pop(); - /* Above explanation holds for following line too */ - dvi_mark_depth(); - break; - - case RIGHT1: do_right1(); break; - case RIGHT2: do_right2(); break; - case RIGHT3: do_right3(); break; - case RIGHT4: do_right4(); break; - - case W0: dvi_w0(); break; - case W1: do_w1 (); break; - case W2: do_w2 (); break; - case W3: do_w3 (); break; - case W4: do_w4 (); break; - - case X0: dvi_x0(); break; - case X1: do_x1 (); break; - case X2: do_x2 (); break; - case X3: do_x3 (); break; - case X4: do_x4 (); break; - - case DOWN1: do_down1(); break; - case DOWN2: do_down2(); break; - case DOWN3: do_down3(); break; - case DOWN4: do_down4(); break; - - case Y0: dvi_y0(); break; - case Y1: do_y1 (); break; - case Y2: do_y2 (); break; - case Y3: do_y3 (); break; - case Y4: do_y4 (); break; - - case Z0: dvi_z0(); break; - case Z1: do_z1 (); break; - case Z2: do_z2 (); break; - case Z3: do_z3 (); break; - case Z4: do_z4 (); break; - - case FNT1: do_fnt1(); break; - case FNT2: do_fnt2(); break; - case FNT3: do_fnt3(); break; - case FNT4: do_fnt4(); break; - - /* Specials */ - case XXX1: do_xxx1(); break; - case XXX2: do_xxx2(); break; - case XXX3: do_xxx3(); break; - case XXX4: do_xxx4(); break; - - /* Font definition - skipped except in linear mode. */ - /* actually, these should not occur! */ - case FNT_DEF1: do_fntdef1(0); break; - case FNT_DEF2: do_fntdef2(0); break; - case FNT_DEF3: do_fntdef3(0); break; - case FNT_DEF4: do_fntdef4(0); break; - - /* pTeX extension */ - case PTEXDIR: - do_dir(); - break; - -#ifdef XETEX - /* XeTeX extension */ - case XDV_GLYPH_STRING: - do_glyph_array(0); - break; - case XDV_GLYPH_ARRAY: - do_glyph_array(1); - break; - case XDV_NATIVE_FONT_DEF: - do_native_font_def(0); /* should not occur - processed during pre-scanning */ - break; - case XDV_PIC_FILE: - do_pic_file(); - break; -#endif - - case POST: -#ifdef XETEX - if (linear && !processing_page) { - /* for linear processing, this means there are no more pages */ - num_pages = 0; /* force loop to terminate */ - return; - } - /* else fall through to error case */ -#endif - case PRE: case POST_POST: - ERROR("Unexpected preamble or postamble in dvi file"); - break; - default: - ERROR("Unexpected opcode or DVI file ended prematurely"); - } - } -} - -double -dvi_init (char *dvi_filename, double mag) -{ - long post_location; - - if (dvi_filename == NULL) { /* no filename: reading from stdin, probably a pipe */ -#ifdef WIN32 - setmode(fileno(stdin), _O_BINARY); -#endif - dvi_file = stdin; - linear = 1; - - get_preamble_dvi_info(); - do_scales(mag); - } - else { - dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); - if (!dvi_file) { - char *p; - p = strrchr(dvi_filename, '.'); -#ifdef XETEX - if (p == NULL || (!FILESTRCASEEQ(p, ".dvi") && !FILESTRCASEEQ(p, ".xdv"))) { -#else - if (p == NULL || !FILESTRCASEEQ(p, ".dvi")) { -#endif -#ifdef XETEX - strcat(dvi_filename, ".xdv"); - dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); - if (!dvi_file) { - dvi_filename[strlen(dvi_filename) - 4] = '\0'; -#endif - strcat(dvi_filename, ".dvi"); - dvi_file = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); -#ifdef XETEX - } -#endif - } - } - if (!dvi_file) { -#ifdef XETEX - ERROR("Could not open specified DVI (or XDV) file: %s", dvi_filename); -#else - ERROR("Could not open specified DVI file: %s", dvi_filename); -#endif - return 0.0; - } - - /* DVI files are most easily read backwards by - * searching for post_post and then post opcode. - */ - post_location = find_post(); - get_dvi_info(post_location); - do_scales(mag); - get_page_info(post_location); - get_comment(); - get_dvi_fonts(post_location); - } - - clear_state(); - - dvi_page_buf_size = DVI_PAGE_BUF_CHUNK; - dvi_page_buffer = NEW(dvi_page_buf_size, unsigned char); - - return dvi2pts; -} - -void -dvi_close (void) -{ - int i; - - if (linear) { - /* probably reading a pipe from xetex; consume any remaining data */ - while (fgetc(dvi_file) != EOF) - ; - } - - /* We add comment in dvi_close instead of dvi_init so user - * has a change to overwrite it. The docinfo dictionary is - * treated as a write-once record. - */ - - /* Do some house cleaning */ - MFCLOSE(dvi_file); - dvi_file = NULL; - - if (def_fonts) { - for (i = 0; i < num_def_fonts; i++) { - if (def_fonts[i].font_name) - RELEASE(def_fonts[i].font_name); - def_fonts[i].font_name = NULL; - } - RELEASE(def_fonts); - } - def_fonts = NULL; - - if (page_loc) - RELEASE(page_loc); - page_loc = NULL; - num_pages = 0; - - if (loaded_fonts) - RELEASE(loaded_fonts); - loaded_fonts = NULL; - num_loaded_fonts = 0; - - vf_close_all_fonts(); - tfm_close_all (); - - if (dvi_page_buffer) { - RELEASE(dvi_page_buffer); - dvi_page_buffer = NULL; - dvi_page_buf_size = 0; - } -} - -/* The following are need to implement virtual fonts - According to documentation, the vf "subroutine" - must have state pushed and must have - w,v,y, and z set to zero. The current font - is determined by the virtual font header, which - may be undefined */ - -static int saved_dvi_font[VF_NESTING_MAX]; -static int num_saved_fonts = 0; - -void -dvi_vf_init (int dev_font_id) -{ - dvi_push(); - - dvi_state.w = 0; dvi_state.x = 0; - dvi_state.y = 0; dvi_state.z = 0; - - /* do not reset dvi_state.d. */ - if (num_saved_fonts < VF_NESTING_MAX) { - saved_dvi_font[num_saved_fonts++] = current_font; - } else - ERROR("Virtual fonts nested too deeply!"); - current_font = dev_font_id; -} - -/* After VF subroutine is finished, we simply pop the DVI stack */ -void -dvi_vf_finish (void) -{ - dvi_pop(); - if (num_saved_fonts > 0) - current_font = saved_dvi_font[--num_saved_fonts]; - else { - ERROR("Tried to pop an empty font stack"); - } -} - - -/* Scan various specials */ -#include "dpxutil.h" - -/* This need to allow 'true' prefix for unit and - * length value must be divided by current magnification. - */ -static int -read_length (double *vp, double mag, const char **pp, const char *endptr) -{ - char *q; - const char *p = *pp; - double v, u = 1.0; - const char *_ukeys[] = { -#define K_UNIT__PT 0 -#define K_UNIT__IN 1 -#define K_UNIT__CM 2 -#define K_UNIT__MM 3 -#define K_UNIT__BP 4 - "pt", "in", "cm", "mm", "bp", - NULL - }; - int k, error = 0; - - q = parse_float_decimal(&p, endptr); - if (!q) { - *vp = 0.0; *pp = p; - return -1; - } - - v = atof(q); - RELEASE(q); - - skip_white(&p, endptr); - q = parse_c_ident(&p, endptr); - if (q) { - 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"); - } - 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; - } - } - - *vp = v * u; *pp = p; - return error; -} - - -static int -scan_special (double *wd, double *ht, double *xo, double *yo, char *lm, - unsigned *minorversion, - int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw, - const char *buf, UNSIGNED_QUAD size) -{ - char *q; - const char *p = buf, *endptr; - int ns_pdf = 0, error = 0; - double tmp; - - endptr = p + size; - - skip_white(&p, endptr); - - q = parse_c_ident(&p, endptr); - if (q && !strcmp(q, "pdf")) { - skip_white(&p, endptr); - if (p < endptr && *p == ':') { - p++; - skip_white(&p, endptr); - RELEASE(q); - 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); - } - } - skip_white(&p, endptr); - - if (q) { - if (!strcmp(q, "landscape")) { - *lm = 1; - } else if (ns_pdf && !strcmp(q, "pagesize")) { - while (!error && p < endptr) { - char *kp = parse_c_ident(&p, endptr); - if (!kp) - break; - else { - skip_white(&p, endptr); - if (!strcmp(kp, "width")) { - error = read_length(&tmp, dvi_tell_mag(), &p, endptr); - if (!error) - *wd = tmp * dvi_tell_mag(); - } else if (!strcmp(kp, "height")) { - error = read_length(&tmp, dvi_tell_mag(), &p, endptr); - if (!error) - *ht = tmp * dvi_tell_mag(); - } else if (!strcmp(kp, "xoffset")) { - error = read_length(&tmp, dvi_tell_mag(), &p, endptr); - if (!error) - *xo = tmp * dvi_tell_mag(); - } else if (!strcmp(kp, "yoffset")) { - error = read_length(&tmp, dvi_tell_mag(), &p, endptr); - if (!error) - *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); - } - skip_white(&p, endptr); - } - } else if (!strcmp(q, "papersize")) { - char qchr = 0; - if (*p == '=') p++; - skip_white(&p, endptr); - if (p < endptr && (*p == '\'' || *p == '\"')) { - qchr = *p; p++; - skip_white(&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(&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; - } - } else if (minorversion && ns_pdf && !strcmp(q, "minorversion")) { - char *kv; - if (*p == '=') p++; - skip_white(&p, endptr); - kv = parse_float_decimal(&p, endptr); - if (kv) { - *minorversion = (unsigned)strtol(kv, NULL, 10); - RELEASE(kv); - } - } else if (ns_pdf && !strcmp(q, "encrypt") && do_enc) { - *do_enc = 1; - *owner_pw = *user_pw = 0; - while (!error && p < endptr) { - char *kp = parse_c_ident(&p, endptr); - if (!kp) - break; - else { - pdf_obj *obj; - skip_white(&p, endptr); - if (!strcmp(kp, "ownerpw")) { - if ((obj = parse_pdf_string(&p, endptr))) { - strncpy(owner_pw, pdf_string_value(obj), MAX_PWD_LEN); - pdf_release_obj(obj); - } else - error = -1; - } else if (!strcmp(kp, "userpw")) { - if ((obj = parse_pdf_string(&p, endptr))) { - strncpy(user_pw, pdf_string_value(obj), MAX_PWD_LEN); - pdf_release_obj(obj); - } else - error = -1; - } else if (!strcmp(kp, "length")) { - if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { - *key_bits = (unsigned) pdf_number_value(obj); - } else - error = -1; - if (obj) - pdf_release_obj(obj); - } else if (!strcmp(kp, "perm")) { - if ((obj = parse_pdf_number(&p, endptr)) && PDF_OBJ_NUMBERTYPE(obj)) { - *permission = (unsigned) pdf_number_value(obj); - } else - error = -1; - if (obj) - pdf_release_obj(obj); - } else - error = -1; - RELEASE(kp); - } - skip_white(&p, endptr); - } - } - RELEASE(q); - } - - return error; -} - - -void -dvi_scan_specials (long page_no, - double *page_width, double *page_height, - double *x_offset, double *y_offset, char *landscape, - unsigned *minorversion, - int *do_enc, unsigned *key_bits, unsigned *permission, char *owner_pw, char *user_pw) -{ - FILE *fp = dvi_file; - long offset; - unsigned char opcode; - static long buffered_page = -1; - - if (page_no == buffered_page) - return; /* because dvipdfmx wants to scan first page twice! */ - buffered_page = page_no; - - dvi_page_buf_index = 0; - - if (!linear) { - if (page_no >= num_pages) - ERROR("Invalid page number: %u", page_no); - offset = page_loc[page_no]; - - seek_absolute(fp, offset); - } - - while ((opcode = get_and_buffer_unsigned_byte(fp)) != EOP) { - if (opcode <= SET_CHAR_127 || - (opcode >= FNT_NUM_0 && opcode <= FNT_NUM_63)) - continue; - else if (opcode == XXX1 || opcode == XXX2 || - opcode == XXX3 || opcode == XXX4) { - UNSIGNED_QUAD size = 0UL; - switch (opcode) { - case XXX1: size = get_and_buffer_unsigned_byte(fp); break; - case XXX2: size = get_and_buffer_unsigned_pair(fp); break; - case XXX3: size = get_and_buffer_unsigned_triple(fp); break; - case XXX4: size = get_and_buffer_unsigned_quad(fp); break; - } - if (dvi_page_buf_index + size >= dvi_page_buf_size) { - dvi_page_buf_size = (dvi_page_buf_index + size + DVI_PAGE_BUF_CHUNK); - dvi_page_buffer = RENEW(dvi_page_buffer, dvi_page_buf_size, unsigned char); - } - if (fread(dvi_page_buffer + dvi_page_buf_index, sizeof(char), size, fp) != size) - ERROR("Reading DVI file failed!"); - if (scan_special(page_width, page_height, x_offset, y_offset, landscape, minorversion, - do_enc, key_bits, permission, owner_pw, user_pw, - (char*)dvi_page_buffer + dvi_page_buf_index, size)) - WARN("Reading special command failed: \"%.*s\"", size, (char*)dvi_page_buffer + dvi_page_buf_index); - dvi_page_buf_index += size; - continue; - } - - /* Skipping... */ - switch (opcode) { - case BOP: - get_and_buffer_bytes(fp, 44); - break; - case NOP: case PUSH: case POP: - case W0: case X0: case Y0: case Z0: - break; - case SET1: case PUT1: case RIGHT1: case DOWN1: - case W1: case X1: case Y1: case Z1: case FNT1: - get_and_buffer_unsigned_byte(fp); - break; - - case SET2: case PUT2: case RIGHT2: case DOWN2: - case W2: case X2: case Y2: case Z2: case FNT2: - get_and_buffer_signed_pair(fp); - break; - - case SET3: case PUT3: case RIGHT3: case DOWN3: - case W3: case X3: case Y3: case Z3: case FNT3: - get_and_buffer_signed_triple(fp); - break; - - case SET4: case PUT4: case RIGHT4: case DOWN4: - case W4: case X4: case Y4: case Z4: case FNT4: - get_and_buffer_signed_quad(fp); - break; - - case SET_RULE: case PUT_RULE: - get_and_buffer_bytes(fp, 8); - break; - - case FNT_DEF1: do_fntdef1(1); break; - case FNT_DEF2: do_fntdef2(1); break; - case FNT_DEF3: do_fntdef3(1); break; - case FNT_DEF4: do_fntdef4(1); break; - -#ifdef XETEX - case XDV_GLYPH_STRING: - { - UNSIGNED_PAIR count; - get_and_buffer_unsigned_quad(fp); /* width */ - count = get_and_buffer_unsigned_pair(fp); /* glyph count */ - get_and_buffer_bytes(fp, count * 6); /* 2 bytes ID + 4 bytes x-location per glyph */ - } - break; - case XDV_GLYPH_ARRAY: - { - UNSIGNED_PAIR count; - get_and_buffer_unsigned_quad(fp); /* width */ - count = get_and_buffer_unsigned_pair(fp); /* glyph count */ - get_and_buffer_bytes(fp, count * 10); /* 2 bytes ID + 8 bytes x,y-location per glyph */ - } - break; - case XDV_NATIVE_FONT_DEF: - do_native_font_def(1); - break; - case XDV_PIC_FILE: - /* params: flags[1] t[4][6] p[2] len[2] path[l] */ - { - UNSIGNED_PAIR len; - get_and_buffer_bytes(fp, 1 + 4 * 6 + 2); - len = get_and_buffer_unsigned_pair(fp); /* length of pathname */ - get_and_buffer_bytes(fp, len); - } - break; -#endif - - case PTEXDIR: - get_and_buffer_unsigned_byte(fp); - break; - - case POST: -#ifdef XETEX - if (linear && dvi_page_buf_index == 1) { - /* this is actually an indication that we've reached the end of the input */ - return; - } - /* else fall through to error case */ -#endif - default: /* case PRE: case POST_POST: and others */ - ERROR("Unexpected opcode %d at pos=0x%x", opcode, tell_position(fp)); - break; - } - } - - return; -} - diff --git a/Build/source/texk/dvipdfm-x/xsrc/dvipdfmx.c b/Build/source/texk/dvipdfm-x/xsrc/dvipdfmx.c deleted file mode 100644 index 65c79e929b2..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/dvipdfmx.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - - This is xdvipdfmx, an extended version of... - - DVIPDFMx, an eXtended-2013 version of DVIPDFM by Mark A. Wicks. - - Copyright (c) 2006 SIL. (xdvipdfmx extensions for XeTeX support) - - Copyright (C) 2002-2013 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "system.h" -#include "mem.h" - -#include "dpxconf.h" -#include "dpxfile.h" -#include "dpxutil.h" - -#include "dvi.h" - -#include "pdflimits.h" -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfparse.h" -#include "pdfencrypt.h" - -#include "spc_tpic.h" -#include "specials.h" - -#include "mpost.h" - -#include "fontmap.h" -#include "pdffont.h" -#include "pdfximage.h" -#include "cid.h" - -#include "dvipdfmx.h" - -#include "error.h" - -#ifdef XETEX -#include "tt_aux.h" -#endif - -int compat_mode = 0; /* 0 = dvipdfmx, 1 = dvipdfm */ - -static int verbose = 0; - -static int mp_mode = 0; - -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) - -static char ignore_colors = 0; -static double annot_grow = 0.0; -static int bookmark_open = 0; -static double mag = 1.0; -static int font_dpi = 600; -static int really_quiet = 0; -/* - * Precision is essentially limited to 0.01pt. - * See, dev_set_string() in pdfdev.c. - */ -static int pdfdecimaldigits = 2; - -/* Image cache life in hours */ -/* 0 means erase all old images and leave new images */ -/* -1 means erase all old images and also erase new images */ -/* -2 means ignore image cache (default) */ -static int image_cache_life = -2; - -/* Encryption */ -static int do_encryption = 0; -static unsigned key_bits = 40; -static unsigned permission = 0x003C; - -/* Page device */ -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; - -int always_embed = 0; /* always embed fonts, regardless of licensing flags */ - -char *dvi_filename = NULL, *pdf_filename = NULL; - -static void -read_config_file (const char *config); - -static void -set_default_pdf_filename(void) -{ - const char *dvi_base; - - dvi_base = xbasename(dvi_filename); - if (mp_mode && - strlen(dvi_base) > 4 && - FILESTRCASEEQ(".mps", dvi_base + strlen(dvi_base) - 4)) { - pdf_filename = NEW(strlen(dvi_base)+1, char); - strncpy(pdf_filename, dvi_base, strlen(dvi_base) - 4); - pdf_filename[strlen(dvi_base)-4] = '\0'; - } else if (strlen(dvi_base) > 4 && - (FILESTRCASEEQ(".dvi", dvi_base+strlen(dvi_base)-4) -#ifdef XETEX - || FILESTRCASEEQ(".xdv", dvi_base+strlen(dvi_base)-4) -#endif - )) { - pdf_filename = NEW(strlen(dvi_base)+1, char); - strncpy(pdf_filename, dvi_base, strlen(dvi_base)-4); - pdf_filename[strlen(dvi_base)-4] = '\0'; - } else { - pdf_filename = NEW(strlen(dvi_base)+5, char); - strcpy(pdf_filename, dvi_base); - } - - strcat (pdf_filename, ".pdf"); -} - -static void -show_version (void) -{ - fprintf (stdout, "\nThis is xdvipdfmx-%s by Jonathan Kew and Jin-Hwan Cho,\n", VERSION); - fprintf (stdout, "modified for TeX Live,\n"); - 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-2013 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"); - fprintf (stdout, "(at your option) any later version.\n"); -} - -static void -show_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, "-f filename\tSet font map file name [cid-x.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"); - fprintf (stdout, "-t \t\tEmbed thumbnail images of PNG format [dvifile.1] \n"); - 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 \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\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\tPositive values are always ORed with previously given flags.\n"); - fprintf (stdout, "\t\tAnd negative values replace old values.\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, "-I number\tImage cache life in hours [-2]\n"); - fprintf (stdout, " \t 0: erase all old images and leave new images\n"); - fprintf (stdout, " \t-1: erase all old images and also erase new images\n"); - fprintf (stdout, " \t-2: ignore image cache\n"); - fprintf (stdout, "-K number\tEncryption key length [40]\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 \t\tEnable PDF encryption\n"); - 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"); -} - -static void -usage (int exit_code) -{ - show_version(); - show_usage(); - exit(exit_code); -} - - -static int -read_length (double *vp, const char **pp, const char *endptr) -{ - char *q; - const char *p = *pp; - double v, u = 1.0; - const char *_ukeys[] = { -#define K_UNIT__PT 0 -#define K_UNIT__IN 1 -#define K_UNIT__CM 2 -#define K_UNIT__MM 3 -#define K_UNIT__BP 4 - "pt", "in", "cm", "mm", "bp", - NULL - }; - int k, error = 0; - - q = parse_float_decimal(&p, endptr); - if (!q) { - *vp = 0.0; *pp = p; - return -1; - } - - v = atof(q); - RELEASE(q); - - skip_white(&p, endptr); - q = parse_c_ident(&p, endptr); - if (q) { - char *qq = q; - if (strlen(q) >= strlen("true") && - !memcmp(q, "true", strlen("true"))) { - q += strlen("true"); /* just skip "true" */ - } - 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; - } - } - - *vp = v * u; *pp = p; - return error; -} - -static void -select_paper (const char *paperspec) -{ - const struct paper *pi; - int error = 0; - - pi = paperinfo(paperspec); - if (pi && papername(pi)) { - paper_width = paperpswidth (pi); - paper_height = paperpsheight(pi); - } else { - const char *p = paperspec, *endptr, *comma; - comma = strchr(p, ','); - endptr = p + strlen(p); - if (!comma) - ERROR("Unrecognized paper format: %s", paperspec); - error = read_length(&paper_width, &p, comma); - p = comma + 1; - error = read_length(&paper_height, &p, endptr); - } - if (error || paper_width <= 0.0 || paper_height <= 0.0) - ERROR("Invalid paper size: %s (%.2fx%.2f)", paperspec, paper_width, paper_height); -} - -struct page_range -{ - long first, last; -} *page_ranges = NULL; - -int num_page_ranges = 0; -int max_page_ranges = 0; - -static void -select_pages (const char *pagespec) -{ - char *q; - const char *p = pagespec; - - while (*p != '\0') { - /* Enlarge page range table if necessary */ - if (num_page_ranges >= max_page_ranges) { - max_page_ranges += 4; - page_ranges = RENEW(page_ranges, max_page_ranges, struct page_range); - } - - page_ranges[num_page_ranges].first = 0; - page_ranges[num_page_ranges].last = 0; - - for ( ; *p && isspace(*p); p++); - q = parse_unsigned(&p, p + strlen(p)); /* Can't be signed. */ - if (q) { /* '-' is allowed here */ - page_ranges[num_page_ranges].first = atoi(q) - 1; - page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; - RELEASE(q); - } - for ( ; *p && isspace(*p); p++); - - if (*p == '-') { - for (++p; *p && isspace(*p); p++); - page_ranges[num_page_ranges].last = -1; - if (*p) { - q = parse_unsigned(&p, p + strlen(p)); - if (q) { - page_ranges[num_page_ranges].last = atoi(q) - 1; - RELEASE(q); - } - for ( ; *p && isspace(*p); p++); - } - } else { - page_ranges[num_page_ranges].last = page_ranges[num_page_ranges].first; - } - - num_page_ranges++; - - if (*p == ',') - p++; - else { - for ( ; *p && isspace(*p); p++); - if (*p) - ERROR("Bad page range specification: %s", p); - } - } - return; -} - -#define POP_ARG() {argv += 1; argc -= 1;} -/* 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(1);\ -} - -static void -set_verbose (int argc, char *argv[]) -{ - while (argc > 0 && *argv[0] == '-') { - char *flag; - - for (flag = argv[0] + 1; *flag != 0; flag++) { - if (*flag == 'q') - really_quiet++; - if (*flag == 'v') - verbose++; - } - POP_ARG(); - } - - if (!really_quiet) { - int i; - - for (i = 0; i < verbose; i++) { - dvi_set_verbose(); - pdf_dev_set_verbose(); - pdf_doc_set_verbose(); - pdf_enc_set_verbose(); - pdf_obj_set_verbose(); - pdf_fontmap_set_verbose(); - dpx_file_set_verbose(); - } - } -} - - -static void -do_args (int argc, char *argv[]) -{ - while (argc > 0 && *argv[0] == '-') { - char *flag, *nextptr; - const char *nnextptr; - - for (flag = argv[0] + 1; *flag != 0; flag++) { - switch (*flag) { - case 'D': - CHECK_ARG(1, "PS->PDF conversion command line template"); - set_distiller_template(argv[1]); - POP_ARG(); - break; - case 'r': - CHECK_ARG(1, "bitmap font dpi"); - font_dpi = atoi(argv[1]); - if (font_dpi <= 0) - ERROR("Invalid bitmap font dpi specified: %s", argv[1]); - POP_ARG(); - break; - case 'm': - CHECK_ARG(1, "magnification value"); - mag = strtod(argv[1], &nextptr); - if (mag < 0.0 || nextptr == argv[1]) - ERROR("Invalid magnification specifiied: %s", argv[1]); - POP_ARG(); - break; - case 'g': - CHECK_ARG(1, "annotation \"grow\" amount"); - nnextptr = nextptr = argv[1]; - read_length(&annot_grow, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'x': - CHECK_ARG(1, "horizontal offset value"); - nnextptr = nextptr = argv[1]; - read_length(&x_offset, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'y': - CHECK_ARG(1, "vertical offset value"); - nnextptr = nextptr = argv[1]; - read_length(&y_offset, &nnextptr, nextptr + strlen(nextptr)); - POP_ARG(); - break; - case 'o': - CHECK_ARG(1, "output file name"); - pdf_filename = NEW (strlen(argv[1])+1,char); - strcpy(pdf_filename, argv[1]); - POP_ARG(); - break; - case 's': - CHECK_ARG(1, "page selection specification"); - select_pages(argv[1]); - POP_ARG(); - break; - case 't': - pdf_doc_enable_manual_thumbnails(); - break; - case 'p': - CHECK_ARG(1, "paper format/size"); - select_paper(argv[1]); - POP_ARG(); - break; - case 'c': - ignore_colors = 1; - break; - case 'l': - landscape_mode = 1; - break; - case 'f': - CHECK_ARG(1, "fontmap file name"); - if (opt_flags & OPT_FONTMAP_FIRST_MATCH) - pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_APPEND); - else - pdf_load_fontmap_file(argv[1], FONTMAP_RMODE_REPLACE); - POP_ARG(); - break; - case 'i': - CHECK_ARG(1, "subsidiary config file"); - read_config_file(argv[1]); - POP_ARG(); - break; - case 'e': - WARN("dvipdfm \"-e\" option not supported."); - break; - case 'q': case 'v': - break; - case 'V': - { - int ver_minor; - - if (isdigit(*(flag+1))) { - flag++; - ver_minor = atoi(flag); - } else { - CHECK_ARG(1, "PDF minor version number"); - ver_minor = atoi(argv[1]); - POP_ARG(); - } - if (ver_minor < PDF_VERSION_MIN) { - WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", - ver_minor, PDF_VERSION_MIN); - ver_minor = PDF_VERSION_MIN; - } else if (ver_minor > PDF_VERSION_MAX) { - WARN("PDF version 1.%d not supported. Using PDF 1.%d instead.", - ver_minor, PDF_VERSION_MAX); - ver_minor = PDF_VERSION_MAX; - } - pdf_set_version((unsigned) ver_minor); - } - break; - case 'z': - { - int level; - - if (isdigit(*(flag+1))) { - flag++; - level = atoi(flag); - } else { - CHECK_ARG(1, "compression level"); - level = atoi(argv[1]); - POP_ARG(); - } - pdf_set_compression(level); - } - break; - case 'd': - if (isdigit(*(flag+1))) { - flag++; - pdfdecimaldigits = atoi(flag); - } else { - CHECK_ARG(1, "number of fractional digits"); - pdfdecimaldigits = atoi(argv[1]); - POP_ARG(); - } - break; - case 'I': - CHECK_ARG(1, "image cache life in hours"); - image_cache_life = atoi(argv[1]); - POP_ARG(); - break; - case 'S': - do_encryption = 1; - break; - case 'K': - CHECK_ARG(1, "encryption key length"); - key_bits = (unsigned) atoi(argv[1]); - if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) - ERROR("Invalid encryption key length specified: %s", argv[1]); - POP_ARG(); - break; - case 'P': - CHECK_ARG(1, "encryption permission flag"); - permission = (unsigned) strtoul(argv[1], &nextptr, 0); - if (nextptr == argv[1]) - ERROR("Invalid encryption permission flag: %s", argv[1]); - POP_ARG(); - break; - case 'O': - /* Bookmark open level */ - CHECK_ARG(1, "bookmark open level"); - bookmark_open = atoi(argv[1]); - POP_ARG(); - break; - case 'M': - mp_mode = 1; - break; - case 'C': - CHECK_ARG(1, "a number"); - { - long flags; - - flags = (unsigned) strtol(argv[1], &nextptr, 0); - if (nextptr == argv[1]) - ERROR("Invalid flag: %s", argv[1]); - if (flags < 0) - opt_flags = -flags; - else - opt_flags |= flags; - } - POP_ARG(); - break; - case 'E': - always_embed = 1; - break; - case 'h': - usage(0); - break; - default: - fprintf (stderr, "Unknown option in \"%s\"", flag); - usage(1); - break; - } - } - POP_ARG(); - } - - if (argc > 1) { - fprintf(stderr, "Multiple dvi filenames?"); - usage(1); - } else if (argc > 0) { - /* - * The only legitimate way to have argc == 0 here is - * do_args was called from config file. In that case, there is - * no dvi file name. Check for that case . - */ - dvi_filename = NEW(strlen(argv[0]) + 5, char); /* space to append .dvi */ - strcpy(dvi_filename, argv[0]); - } -} - -static void -cleanup (void) -{ - if (dvi_filename) - RELEASE(dvi_filename); - if (pdf_filename) - RELEASE(pdf_filename); - if (page_ranges) - RELEASE(page_ranges); -} - -static void -read_config_file (const char *config) -{ - const char *start, *end; - char *option; - FILE *fp; - - fp = DPXFOPEN(config, DPX_RES_TYPE_TEXT); - if (!fp) { - WARN("Could not open config file \"%s\".", config); - return; - } - while ((start = mfgets (work_buffer, WORK_BUFFER_SIZE, fp)) != NULL) { - char *argv[2]; - int argc; - - argc = 0; - end = work_buffer + strlen(work_buffer); - skip_white (&start, end); - if (start >= end) - continue; - /* Build up an argument list as if it were passed on the command - line */ - if ((option = parse_ident (&start, end))) { - argc = 1; - argv[0] = NEW (strlen(option)+2, char); - strcpy (argv[0]+1, option); - RELEASE (option); - *argv[0] = '-'; - skip_white (&start, end); - if (start < end) { - argc += 1; - if (*start == '"') { - argv[1] = parse_c_string (&start, end); - } - else - argv[1] = parse_ident (&start, end); - } - } - do_args (argc, argv); - while (argc > 0) { - RELEASE (argv[--argc]); - } - } - if (fp) - MFCLOSE(fp); -} - -static void -system_default (void) -{ - if (systempapername() != NULL) { - select_paper(systempapername()); - } else if (defaultpapername() != NULL) { - select_paper(defaultpapername()); - } -} - -void -error_cleanup (void) -{ - pdf_error_cleanup(); - if (pdf_filename) { - remove(pdf_filename); - fprintf(stderr, "\nOutput file removed.\n"); - } -} - -#define SWAP(v1,v2) do {\ - double _tmp = (v1);\ - (v1) = (v2);\ - (v2) = _tmp;\ - } while (0) - -static void -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(); - - if (num_page_ranges == 0) { - if (!page_ranges) { - page_ranges = NEW(1, struct page_range); - max_page_ranges = 1; - } - page_ranges[0].first = 0; - page_ranges[0].last = -1; /* last page */ - num_page_ranges = 1; - } - - init_paper_width = page_width = paper_width; - init_paper_height = page_height = paper_height; - page_count = 0; - - mediabox.llx = 0.0; - mediabox.lly = 0.0; - mediabox.urx = paper_width; - mediabox.ury = paper_height; - - pdf_doc_set_mediabox(0, &mediabox); /* Root node */ - - for (i = 0; i < num_page_ranges && dvi_npages() > 0; i++) { - if (page_ranges[i].last < 0) - page_ranges[i].last += dvi_npages(); - - step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; - page_no = page_ranges[i].first; - while (dvi_npages() > 0) { - if (page_no < dvi_npages()) { - double w, h, xo, yo; - 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_specials(page_no, &w, &h, &xo, &yo, &lm, NULL, NULL, NULL, NULL, NULL, NULL); - if (lm != landscape_mode) { - SWAP(w, h); - landscape_mode = lm; - } - if (page_width != w || page_height != h) { - page_width = w; - page_height = h; - } - if (x_offset != xo || y_offset != yo) { - x_offset = xo; - y_offset = yo; - } - if (page_width != init_paper_width || - page_height != init_paper_height) { - mediabox.llx = 0.0; - mediabox.lly = 0.0; - mediabox.urx = page_width; - mediabox.ury = page_height; - pdf_doc_set_mediabox(page_count+1, &mediabox); - } - dvi_do_page(page_no, - page_width, page_height, x_offset, y_offset); - page_count++; - } - - if (step > 0 && - page_no >= page_ranges[i].last) - break; - else if (step < 0 && - page_no <= page_ranges[i].last) - break; - else { - page_no += step; - } - } - } - - if (page_count < 1) { - ERROR("No pages fall in range!"); - } - - spc_exec_at_end_document(); -} - -static void -do_mps_pages (void) -{ - FILE *fp; - - /* _FIXME_ */ - fp = MFOPEN(dvi_filename, FOPEN_RBIN_MODE); - if (fp) { - mps_do_page(fp); - MFCLOSE(fp); - } else { - long i, page_no, step, page_count = 0; - char *filename; - /* Process filename.1, filename.2,... */ - filename = NEW(strlen(dvi_filename) + 16 + 1, char); - for (i = 0; i < num_page_ranges; i++) { - if (page_ranges[i].last < 0) - ERROR("Invalid page number for MPS input: -1"); - - step = (page_ranges[i].first <= page_ranges[i].last) ? 1 : -1; - page_no = page_ranges[i].first; - for (;;) { - sprintf(filename, "%s.%ld", dvi_filename, page_no + 1); - fp = MFOPEN(filename, FOPEN_RBIN_MODE); - if (fp) { - MESG("[%ld<%s>", page_no + 1, filename); - mps_do_page(fp); - page_count++; - MESG("]"); - MFCLOSE(fp); - } - if (step > 0 && - page_no >= page_ranges[i].last) - break; - else if (step < 0 && - page_no <= page_ranges[i].last) - break; - else { - page_no += step; - } - } - } - RELEASE(filename); - if (page_count == 0) - ERROR("No page output for \"%s\".", dvi_filename); - } -} - - -/* TODO: MetaPost mode */ -#if defined(MIKTEX) -# define main Main -#endif -int CDECL -main (int argc, char *argv[]) -{ - double dvi2pts; - char *base; - -#ifdef MIKTEX - miktex_initialize(); -#else - kpse_set_program_name(argv[0], "dvipdfmx"); /* we pretend to be dvipdfmx for kpse purposes */ -#ifdef WIN32 - texlive_gs_init (); -#endif -#endif - - if (argc > 1 && - (STREQ (argv[1], "--xbb") || -#ifndef XETEX - STREQ (argv[1], "--dvipdfm") || -#endif - STREQ (argv[1], "--ebb"))) { - argc--; - base = argv++[1]+2; - } else - base = kpse_program_basename (argv[0]); - - if (FILESTRCASEEQ (base, "extractbb") || FILESTRCASEEQ (base, "xbb")) - return extractbb (argc, argv); - if (FILESTRCASEEQ (base, "ebb")) { - compat_mode = 1; - return extractbb (argc, argv); - } - -#ifndef XETEX - if (FILESTRCASEEQ (base, "dvipdfm")) - compat_mode = 1; - else -#endif - free (base); - - paperinit(); - system_default(); - - argv+=1; - argc-=1; - - set_verbose(argc, argv); - - pdf_init_fontmaps(); /* This must come before parsing options... */ - - read_config_file(DPX_CONFIG_FILE); - - do_args (argc, argv); - - if (really_quiet) - shut_up(really_quiet); - -#ifndef MIKTEX - kpse_init_prog("", font_dpi, NULL, NULL); - kpse_set_program_enabled(kpse_pk_format, true, kpse_src_texmf_cnf); -#endif - pdf_font_set_dpi(font_dpi); - dpx_delete_old_cache(image_cache_life); - - if (dvi_filename == NULL) { - if (verbose) - MESG("No dvi filename specified, reading standard input.\n"); - if (pdf_filename == NULL) - if (verbose) - MESG("No pdf filename specified, writing to standard output.\n"); - } - - if (pdf_filename == NULL && dvi_filename != NULL) - set_default_pdf_filename(); - - pdf_enc_compute_id_string(dvi_filename, pdf_filename); - if (do_encryption) { - pdf_enc_set_passwd(key_bits, permission, NULL, NULL); - if (key_bits > 40 && pdf_get_version() < 4) - pdf_set_version(4); - } - - if (mp_mode) { - x_offset = 0.0; - y_offset = 0.0; - dvi2pts = 0.01; /* dvi2pts controls accuracy. */ - } else { - unsigned ver_minor = 0; - char owner_pw[MAX_PWD_LEN], user_pw[MAX_PWD_LEN]; - /* Dependency between DVI and PDF side is rather complicated... */ - dvi2pts = dvi_init(dvi_filename, mag); - if (dvi2pts == 0.0) - ERROR("dvi_init() failed!"); - - pdf_doc_set_creator(dvi_comment()); - - if (do_encryption) - /* command line takes precedence */ - dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, - &ver_minor, NULL, NULL, NULL, NULL, NULL); - else { - dvi_scan_specials(0, &paper_width, &paper_height, &x_offset, &y_offset, &landscape_mode, - &ver_minor, &do_encryption, &key_bits, &permission, owner_pw, user_pw); - if (do_encryption) { - if (key_bits < 40 || key_bits > 128 || (key_bits & 0x7)) - ERROR("Invalid encryption key length specified: %u", key_bits); - else if (key_bits > 40 && pdf_get_version() < 4) - ERROR("Chosen key length requires at least PDF 1.4. " - "Use \"-V 4\" to change."); - do_encryption = 1; - pdf_enc_set_passwd(key_bits, permission, owner_pw, user_pw); - } - } - if (ver_minor >= PDF_VERSION_MIN && ver_minor <= PDF_VERSION_MAX) { - pdf_set_version(ver_minor); - } - if (landscape_mode) { - SWAP(paper_width, paper_height); - } - } - - MESG("%s -> %s\n", dvi_filename == NULL ? "stdin" : dvi_filename, - pdf_filename == NULL ? "stdout" : pdf_filename); - - pdf_files_init(); - - /* 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, do_encryption, - paper_width, paper_height, annot_grow, bookmark_open, - 0); - - /* Ignore_colors placed here since - * they are considered as device's capacity. - */ - pdf_init_device(dvi2pts, pdfdecimaldigits, ignore_colors); - - if (opt_flags & OPT_CIDFONT_FIXEDPITCH) - CIDFont_set_flags(CIDFONT_FORCE_FIXEDPITCH); - - /* Please move this to spc_init_specials(). */ - if (opt_flags & OPT_TPIC_TRANSPARENT_FILL) - tpic_set_fill_mode(1); - - if (mp_mode) { - do_mps_pages(); - } else { - do_dvi_pages(); - } - - pdf_files_close(); - - /* Order of close... */ - pdf_close_device (); - /* pdf_close_document flushes XObject (image) and other resources. */ - pdf_close_document(); - - pdf_close_fontmaps(); /* pdf_font may depend on fontmap. */ - - if (!mp_mode) - dvi_close(); - - MESG("\n"); - cleanup(); - - paperdone(); -#ifdef MIKTEX - miktex_uninitialize (); -#endif - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/epdf.c b/Build/source/texk/dvipdfm-x/xsrc/epdf.c deleted file mode 100644 index 58a8c527e04..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/epdf.c +++ /dev/null @@ -1,915 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -/* - * Concatinating content streams are only supported for streams that only uses - * single FlateDecode filter, i.e., - * - * /Filter /FlateDecode or /Filter [/FlateDecode] - * - * TrimBox, BleedBox, ArtBox, Rotate ... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "mfileio.h" -#include "error.h" -#include "dvipdfmx.h" - -#include "pdfobj.h" -#include "pdfdev.h" -#include "pdfdoc.h" - -#ifdef XETEX -#include "pdfdraw.h" -#include "pdfparse.h" -#endif - -#include "pdfximage.h" - -#include "epdf.h" - -#ifdef XETEX -#if HAVE_ZLIB -#include -static int add_stream_flate (pdf_obj *dst, const void *data, long len); -#endif -static int rect_equal (pdf_obj *rect1, pdf_obj *rect2); - -static int concat_stream (pdf_obj *dst, pdf_obj *src); - -/* - * From PDFReference15_v6.pdf (p.119 and p.834) - * - * MediaBox rectangle (Required; inheritable) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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 -rect_equal (pdf_obj *rect1, pdf_obj *rect2) -{ - int i; - - if (!rect1 || !rect2) - return 0; - for (i = 0; i < 4; i++) { - if (pdf_number_value(pdf_get_array(rect1, i)) != - pdf_number_value(pdf_get_array(rect2, i))) - return 0; - } - - return 1; -} - -static pdf_obj* -pdf_get_page_obj (pdf_file *pf, long page_no, - pdf_obj **ret_bbox, pdf_obj **ret_resources) -{ - pdf_obj *page_tree; - pdf_obj *bbox = NULL, *resources = NULL, *rotate = NULL; - long page_idx; - - /* - * Get Page Tree. - */ - page_tree = NULL; - { - pdf_obj *trailer, *catalog; - pdf_obj *markinfo, *tmp; - - trailer = pdf_file_get_trailer(pf); - - if (pdf_lookup_dict(trailer, "Encrypt")) { - WARN("This PDF document is encrypted."); - pdf_release_obj(trailer); - return NULL; - } - - catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); - 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); - - markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo")); - if (markinfo) { - tmp = pdf_lookup_dict(markinfo, "Marked"); - if (PDF_OBJ_BOOLEANTYPE(tmp) && pdf_boolean_value(tmp)) - WARN("File contains tagged PDF. Ignoring tags."); - pdf_release_obj(markinfo); - } - - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - pdf_release_obj(catalog); - } - if (!page_tree) { - WARN("Page tree not found."); - return NULL; - } - - /* - * 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); - pdf_release_obj(page_tree); - return NULL; - } - page_no = page_idx+1; - } - - /* - * Seek correct page. Get Media/Crop Box. - * Media box and resources can be inherited. - */ - { - pdf_obj *kids_ref, *kids; - pdf_obj *crop_box = NULL; - pdf_obj *tmp; - - tmp = pdf_lookup_dict(page_tree, "Resources"); - resources = tmp ? pdf_deref_obj(tmp) : pdf_new_dict(); - - 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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(tmp); - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { - if (rotate) - pdf_release_obj(rotate); - rotate = tmp; - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { -#if 0 - pdf_merge_dict(tmp, resources); -#endif - if (resources) - 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); - 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; - } - - if (ret_bbox != NULL) - *ret_bbox = bbox; - if (ret_resources != NULL) - *ret_resources = resources; - - 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; - 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++; - } - 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; - } - /* 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; - } - pdf_release_obj(contents); - contents = content_new; - } - - return contents; -} -#endif - -int -pdf_include_page (pdf_ximage *ximage, FILE *image_file, const char *filename) -{ - xform_info info; - pdf_obj *contents, *contents_dict; - pdf_obj *page_tree; - pdf_obj *matrix; - pdf_obj *bbox = NULL, *resources = NULL; - long page_no; - pdf_file *pf; - char *ident = pdf_ximage_get_ident(ximage); - - pdf_ximage_init_form_info(&info); - - pf = pdf_open(ident, image_file); - if (!pf) - return -1; - - /* - * Get Page Tree. - */ - page_no = pdf_ximage_get_page(ximage); - if (page_no == 0) - page_no = 1; - - page_tree = pdf_get_page_obj(pf, page_no, &bbox, &resources); - if (page_tree == NULL) { - pdf_close(pf); - 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); - } - - /* - * Handle page content stream. - * page_tree is now set to the correct page. - */ - contents = pdf_get_page_content(page_tree); - pdf_release_obj(page_tree); - if (contents == NULL) { - pdf_close(pf); - return -1; - } - - { - pdf_obj *tmp; - - tmp = pdf_import_object(resources); - pdf_release_obj(resources); - resources = tmp; - tmp = pdf_import_object(bbox); - pdf_release_obj(bbox); - bbox = tmp; - } - - pdf_close(pf); - - { - contents_dict = pdf_stream_dict(contents); - pdf_add_dict(contents_dict, - pdf_new_name("Type"), - pdf_new_name("XObject")); - pdf_add_dict(contents_dict, - pdf_new_name("Subtype"), - pdf_new_name("Form")); - pdf_add_dict(contents_dict, - pdf_new_name("FormType"), - pdf_new_number(1.0)); - - pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox); - - matrix = pdf_new_array(); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(1.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - pdf_add_array(matrix, pdf_new_number(0.0)); - - pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix); - - pdf_add_dict(contents_dict, pdf_new_name("Resources"), resources); - } - - pdf_ximage_set_form(ximage, &info, contents); - - return 0; -} - -#ifdef XETEX -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; - const char *clip_path, *end_path; - char *save_path, *temp; - pdf_tmatrix M; - double stack[6]; - pdf_file *pf; - - pf = pdf_open(NULL, image_file); - if (!pf) - return -1; - - pdf_dev_currentmatrix(&M); - pdf_invertmatrix(&M); - M.e += x_user; M.f += y_user; - page_tree = pdf_get_page_obj (pf, pageNo, NULL, NULL); - if (!page_tree) { - pdf_close(pf); - return -1; - } - - contents = pdf_get_page_content(page_tree); - pdf_release_obj(page_tree); - if (!contents) { - pdf_close(pf); - return -1; - } - - pdf_doc_add_page_content(" ", 1); - - save_path = malloc(pdf_stream_length(contents) + 1); - strncpy(save_path, (const char *) pdf_stream_dataptr(contents), pdf_stream_length(contents)); - clip_path = save_path; - end_path = clip_path + pdf_stream_length(contents); - depth = 0; - - for (; clip_path < end_path; clip_path++) { - int color_dimen = 0; /* silence uninitialized warning */ - 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, pf); - 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; - } - } - } - free(save_path); - - pdf_release_obj(contents); - pdf_close(pf); - - return 0; -} - -#define WBUF_SIZE 4096 -#if HAVE_ZLIB -static int -add_stream_flate (pdf_obj *dst, const void *data, long len) -{ - z_stream z; - Bytef wbuf[WBUF_SIZE]; - - z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - z.next_in = (Bytef *) data; z.avail_in = len; - z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; - - if (inflateInit(&z) != Z_OK) { - WARN("inflateInit() failed."); - return -1; - } - - for (;;) { - int status; - status = inflate(&z, Z_NO_FLUSH); - if (status == Z_STREAM_END) - break; - else if (status != Z_OK) { - WARN("inflate() failed. Broken PDF file?"); - inflateEnd(&z); - return -1; - } - - if (z.avail_out == 0) { - pdf_add_stream(dst, wbuf, WBUF_SIZE); - z.next_out = wbuf; - z.avail_out = WBUF_SIZE; - } - } - - if (WBUF_SIZE - z.avail_out > 0) - pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); - - return (inflateEnd(&z) == Z_OK ? 0 : -1); -} -#endif - -static int -concat_stream (pdf_obj *dst, pdf_obj *src) -{ - const char *stream_data; - long stream_length; - pdf_obj *stream_dict; - pdf_obj *filter; - - if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) - ERROR("Invalid type."); - - stream_data = pdf_stream_dataptr(src); - stream_length = pdf_stream_length (src); - stream_dict = pdf_stream_dict (src); - - if (pdf_lookup_dict(stream_dict, "DecodeParms")) { - WARN("DecodeParams not supported."); - return -1; - } - - filter = pdf_lookup_dict(stream_dict, "Filter"); - if (!filter) { - pdf_add_stream(dst, stream_data, stream_length); - return 0; -#if HAVE_ZLIB - } else { - char *filter_name; - if (PDF_OBJ_NAMETYPE(filter)) { - filter_name = pdf_name_value(filter); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } else if (PDF_OBJ_ARRAYTYPE(filter)) { - if (pdf_array_length(filter) > 1) { - WARN("Multiple DecodeFilter not supported."); - return -1; - } else { - filter_name = pdf_name_value(pdf_get_array(filter, 0)); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } - } else - ERROR("Broken PDF file?"); -#endif /* HAVE_ZLIB */ - } - - return -1; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/xsrc/jpegimage.c b/Build/source/texk/dvipdfm-x/xsrc/jpegimage.c deleted file mode 100644 index d1b31c214d0..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/jpegimage.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* - * JPEG SUPPORT - * - * Accroding to Libjpeg document: - * - * CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK - * JPEG files: 0 represents 100% ink coverage, rather than 0% ink as you'd - * expect.... - * - * To wrok with this problem, we must detect whether CMYK JPEG file is - * created by Photoshop. But there are no reliable way to determine this. - * - * According to Adobe Technical Note #5516, - * "Supporting the DCT Filters in PostScript Level 2", Section 18, p.27. - * - * DCTDecode ignores and skips any APPE marker segment does not begin with - * the `Adobe' 5-character string. - * - * PDF Reference Manual 4th ed., p.61-62. - * - * The JPEG filter implementation in Adobe Acrobat products does not - * support features of the JPEG standard that are irrelevant to images. - * In addition, certain choices have been made regarding reserved marker - * codes and other optional features of the standard. For details, see - * Adobe Technical Note #5116, Supporting the DCT Filters in PostScript - * Level 2. - */ - -#include "system.h" -#include "error.h" -#include "mem.h" - -#include "mfileio.h" -#include "numbers.h" - -#include "dvipdfmx.h" - -#include "pdfobj.h" - -#include "jpegimage.h" -#include "pdfcolor.h" - -#include "pdfximage.h" - -#define JPEG_DEBUG_STR "JPEG" -#define JPEG_DEBUG 3 - -#ifdef HAVE_LIBJPEG -#include -#endif /* HAVE_LIBJPEG */ - -/* JPEG Markers */ -typedef enum { - JM_SOF0 = 0xc0, - JM_SOF1 = 0xc1, - JM_SOF2 = 0xc2, - JM_SOF3 = 0xc3, - JM_SOF5 = 0xc5, - JM_DHT = 0xc4, - JM_SOF6 = 0xc6, - JM_SOF7 = 0xc7, - JM_SOF9 = 0xc9, - JM_SOF10 = 0xca, - JM_SOF11 = 0xcb, - JM_DAC = 0xcc, - JM_SOF13 = 0xcd, - JM_SOF14 = 0xce, - JM_SOF15 = 0xcf, - - JM_RST0 = 0xd0, - JM_RST1 = 0xd1, - JM_RST2 = 0xd2, - JM_RST3 = 0xd3, - JM_RST4 = 0xd4, - JM_RST5 = 0xd5, - JM_RST6 = 0xd6, - JM_RST7 = 0xd7, - - JM_SOI = 0xd8, - JM_EOI = 0xd9, - JM_SOS = 0xda, - JM_DQT = 0xdb, - JM_DNL = 0xdc, - JM_DRI = 0xdd, - JM_DHP = 0xde, - JM_EXP = 0xdf, - - JM_APP0 = 0xe0, - JM_APP1 = 0xe1, - JM_APP2 = 0xe2, - JM_APP14 = 0xee, - JM_APP15 = 0xef, - - JM_COM = 0xfe -} JPEG_marker; - -typedef enum { - JS_APPn_JFIF, - JS_APPn_ADOBE, - JS_APPn_ICC -} JPEG_APPn_sig; - -struct JPEG_APPn_JFIF /* APP0 */ -{ - unsigned short version; - unsigned char units; /* 0: only aspect ratio - * 1: dots per inch - * 2: dots per cm - */ - unsigned short Xdensity; - unsigned short Ydensity; - unsigned char Xthumbnail; - unsigned char Ythumbnail; - unsigned char *thumbnail; /* Thumbnail data. */ -}; - -struct JPEG_APPn_ICC /* APP2 */ -{ - unsigned char seq_id; - unsigned char num_chunks; - unsigned char *chunk; - - /* Length of ICC profile data in this chunk. */ - unsigned short length; -}; - -struct JPEG_APPn_Adobe /* APP14 */ -{ - unsigned short version; - unsigned short flag0; - unsigned short flag1; - unsigned char transform; /* color transform code */ -}; - -struct JPEG_ext -{ - JPEG_marker marker; - JPEG_APPn_sig app_sig; - void *app_data; -}; - -#define MAX_COUNT 1024 -struct JPEG_info -{ - unsigned short height; - unsigned short width; - - unsigned char bits_per_component; - unsigned char num_components; - - double xdpi; - double ydpi; - - /* Application specific extensions */ - int flags; - int num_appn, max_appn; - struct JPEG_ext *appn; - - /* Skip chunks not necessary. */ - char skipbits[MAX_COUNT / 8 + 1]; -}; - -#define HAVE_APPn_JFIF (1 << 0) -#define HAVE_APPn_ADOBE (1 << 1) -#define HAVE_APPn_ICC (1 << 2) -#define HAVE_APPn_Exif (1 << 3) - -static int JPEG_scan_file (struct JPEG_info *j_info, FILE *fp); -static int JPEG_copy_stream (struct JPEG_info *j_info, - pdf_obj *stream, FILE *fp, int flags); /* flags unused yet */ - -static void JPEG_info_init (struct JPEG_info *j_info); -static void JPEG_info_clear (struct JPEG_info *j_info); -static pdf_obj *JPEG_get_iccp (struct JPEG_info *j_info); -static void jpeg_get_density (struct JPEG_info *j_info, - double *xdensity, double *ydensity); - -int -check_for_jpeg (FILE *fp) -{ - unsigned char jpeg_sig[2]; - - rewind(fp); - if (fread(jpeg_sig, sizeof(unsigned char), 2, fp) != 2) - return 0; - else if (jpeg_sig[0] != 0xff || jpeg_sig[1] != JM_SOI) - return 0; - - return 1; -} - -int -jpeg_include_image (pdf_ximage *ximage, FILE *fp) -{ - pdf_obj *stream; - pdf_obj *stream_dict; - pdf_obj *colorspace; - int colortype; - ximage_info info; - struct JPEG_info j_info; - - if (!check_for_jpeg(fp)) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - rewind(fp); - return -1; - } - /* File position is 2 here... */ - - pdf_ximage_init_image_info(&info); - - JPEG_info_init(&j_info); - - if (JPEG_scan_file(&j_info, fp) < 0) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - JPEG_info_clear(&j_info); - return -1; - } - - switch (j_info.num_components) { - case 1: - colortype = PDF_COLORSPACE_TYPE_GRAY; - break; - case 3: - colortype = PDF_COLORSPACE_TYPE_RGB; - break; - case 4: - colortype = PDF_COLORSPACE_TYPE_CMYK; - break; - default: - WARN("%s: Unknown color space (num components: %d)", - JPEG_DEBUG_STR, info.num_components); - JPEG_info_clear(&j_info); - return -1; - } - - /* JPEG image use DCTDecode. */ - stream = pdf_new_stream (0); - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, - pdf_new_name("Filter"), pdf_new_name("DCTDecode")); - - colorspace = NULL; - if (j_info.flags & HAVE_APPn_ICC) { - pdf_obj *icc_stream, *intent; - - icc_stream = JPEG_get_iccp(&j_info); - - if (!icc_stream) - colorspace = NULL; - else { - int cspc_id; - - if (iccp_check_colorspace(colortype, - pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)) < 0) - colorspace = NULL; - else { - cspc_id = iccp_load_profile(NULL, /* noname */ - pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)); - if (cspc_id < 0) - colorspace = NULL; - else { - colorspace = pdf_get_colorspace_reference(cspc_id); - intent = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream), - pdf_stream_length (icc_stream)); - if (intent) - pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); - } - } - pdf_release_obj(icc_stream); - } - } - - /* No ICC or invalid ICC profile. */ - if (!colorspace) { - switch (colortype) { - case PDF_COLORSPACE_TYPE_GRAY: - colorspace = pdf_new_name("DeviceGray"); - break; - case PDF_COLORSPACE_TYPE_RGB: - colorspace = pdf_new_name("DeviceRGB"); - break; - case PDF_COLORSPACE_TYPE_CMYK: - colorspace = pdf_new_name("DeviceCMYK"); - break; - } - } - pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); - -#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4) - - if (IS_ADOBE_CMYK(j_info)) { - pdf_obj *decode; - int i; - - WARN("Adobe CMYK JPEG: Inverted color assumed."); - decode = pdf_new_array(); - for (i = 0; i < j_info.num_components; i++) { - pdf_add_array(decode, pdf_new_number(1.0)); - pdf_add_array(decode, pdf_new_number(0.0)); - } - pdf_add_dict(stream_dict, pdf_new_name("Decode"), decode); - } - - /* Copy file */ - JPEG_copy_stream(&j_info, stream, fp, 0); - - info.width = j_info.width; - info.height = j_info.height; - info.bits_per_component = j_info.bits_per_component; - info.num_components = j_info.num_components; - - if (j_info.flags & HAVE_APPn_Exif) { - /* resolution data from EXIF is handled here, takes precedence over JFIF */ - info.xdensity = 72.0 / j_info.xdpi; - info.ydensity = 72.0 / j_info.ydpi; - } - else if (j_info.flags & HAVE_APPn_JFIF) { - 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; - } - } - } - - pdf_ximage_set_image(ximage, &info, stream); - JPEG_info_clear(&j_info); - - return 0; -} - -static void -jpeg_get_density (struct JPEG_info *j_info, - double *xdensity, double *ydensity) -{ - if (compat_mode) { - *xdensity = *ydensity = 72.0 / 100.0; - return; - } - - *xdensity = *ydensity = 1.0; - - if (j_info->flags & HAVE_APPn_JFIF) { - struct JPEG_APPn_JFIF *app_data; - 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) { - app_data = (struct JPEG_APPn_JFIF *)j_info->appn[i].app_data; - switch (app_data->units) { - case 1: /* pixels per inch */ - *xdensity = 72.0 / app_data->Xdensity; - *ydensity = 72.0 / app_data->Ydensity; - break; - case 2: /* pixels per centimeter */ - *xdensity = 72.0 / 2.54 / app_data->Xdensity; - *ydensity = 72.0 / 2.54 / app_data->Ydensity; - break; - default: - break; - } - } - } -} - -static void -JPEG_info_init (struct JPEG_info *j_info) -{ - j_info->width = 0; - j_info->height = 0; - j_info->bits_per_component = 0; - j_info->num_components = 0; - - j_info->xdpi = 0; - j_info->ydpi = 0; - - j_info->flags = 0; - j_info->num_appn = 0; - j_info->max_appn = 0; - j_info->appn = NULL; - - memset(j_info->skipbits, 0, MAX_COUNT / 8 + 1); -} - -static void -JPEG_release_APPn_data (JPEG_marker marker, JPEG_APPn_sig app_sig, void *app_data) -{ - if (marker == JM_APP0 && - app_sig == JS_APPn_JFIF) { - struct JPEG_APPn_JFIF *data; - - data = (struct JPEG_APPn_JFIF *) app_data; - if (data->thumbnail) - RELEASE(data->thumbnail); - data->thumbnail = NULL; - - RELEASE(data); - } else if (marker == JM_APP2 && - app_sig == JS_APPn_ICC) { - struct JPEG_APPn_ICC *data; - - data = (struct JPEG_APPn_ICC *) app_data; - if (data->chunk) - RELEASE(data->chunk); - data->chunk = NULL; - - RELEASE(data); - } else if (marker == JM_APP14 && - app_sig == JS_APPn_ADOBE) { - struct JPEG_APPn_Adobe *data; - - data = (struct JPEG_APPn_Adobe *) app_data; - - RELEASE(data); - } -} - -static void -JPEG_info_clear (struct JPEG_info *j_info) -{ - if (j_info->num_appn > 0 && - j_info->appn != NULL) { - int i; - - for (i = 0; i < j_info->num_appn; i++) - JPEG_release_APPn_data(j_info->appn[i].marker, - j_info->appn[i].app_sig, j_info->appn[i].app_data); - RELEASE(j_info->appn); - } - j_info->appn = NULL; - j_info->num_appn = 0; - j_info->max_appn = 0; - j_info->flags = 0; -} - -static pdf_obj * -JPEG_get_iccp (struct JPEG_info *j_info) -{ - pdf_obj *icc_stream; - struct JPEG_APPn_ICC *icc; - int i, prev_id = 0, num_icc_seg = -1; - - icc_stream = pdf_new_stream(STREAM_COMPRESS); - for (i = 0; i < j_info->num_appn; i++) { - if (j_info->appn[i].marker != JM_APP2 || - j_info->appn[i].app_sig != JS_APPn_ICC) - continue; - icc = (struct JPEG_APPn_ICC *) j_info->appn[i].app_data; - if (num_icc_seg < 0 && prev_id == 0) { - num_icc_seg = icc->num_chunks; - /* ICC chunks are sorted? */ - } else if (icc->seq_id != prev_id + 1 || - num_icc_seg != icc->num_chunks || - icc->seq_id > icc->num_chunks) { - WARN("Invalid JPEG ICC chunk: %d (p:%d, n:%d)", - icc->seq_id, prev_id, icc->num_chunks); - pdf_release_obj(icc_stream); - icc_stream = NULL; - break; - } - pdf_add_stream(icc_stream, icc->chunk, icc->length); - prev_id = icc->seq_id; - num_icc_seg = icc->num_chunks; - } - - return icc_stream; -} - -static JPEG_marker -JPEG_get_marker (FILE *fp) -{ - int c; - - c = fgetc(fp); - if (c != 255) - return -1; - - for (;;) { - c = fgetc(fp); - if (c < 0) - return -1; - else if (c > 0 && c < 255) { - return c; - } - } - - return -1; -} - -static int -add_APPn_marker (struct JPEG_info *j_info, - JPEG_marker marker, int app_sig, void *app_data) -{ - int n; - - if (j_info->num_appn >= j_info->max_appn) { - j_info->max_appn += 16; - j_info->appn = RENEW(j_info->appn, j_info->max_appn, struct JPEG_ext); - } - n = j_info->num_appn; - - j_info->appn[n].marker = marker; - j_info->appn[n].app_sig = app_sig; - j_info->appn[n].app_data = app_data; - - j_info->num_appn += 1; - - return n; -} - -static unsigned short -read_APP14_Adobe (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_Adobe *app_data; - - app_data = NEW(1, struct JPEG_APPn_Adobe); - app_data->version = get_unsigned_pair(fp); - app_data->flag0 = get_unsigned_pair(fp); - app_data->flag1 = get_unsigned_pair(fp); - app_data->transform = get_unsigned_byte(fp); - - add_APPn_marker(j_info, JM_APP14, JS_APPn_ADOBE, app_data); - - return 7; -} - -#ifdef XETEX -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; - int num_fields, tag, type; - int value = 0, num = 0, den = 0; /* silence uninitialized warnings */ - 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); - 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; -} -#endif - -static unsigned short -read_APP0_JFIF (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_JFIF *app_data; - unsigned short thumb_data_len; - - app_data = NEW(1, struct JPEG_APPn_JFIF); - app_data->version = get_unsigned_pair(fp); - app_data->units = get_unsigned_byte(fp); - app_data->Xdensity = get_unsigned_pair(fp); - app_data->Ydensity = get_unsigned_pair(fp); - app_data->Xthumbnail = get_unsigned_byte(fp); - app_data->Ythumbnail = get_unsigned_byte(fp); - thumb_data_len = 3 * app_data->Xthumbnail * app_data->Ythumbnail; - if (thumb_data_len > 0) { - app_data->thumbnail = NEW(thumb_data_len, unsigned char); - fread(app_data->thumbnail, 1, thumb_data_len, fp); - } else { - app_data->thumbnail = NULL; - } - - add_APPn_marker(j_info, JM_APP0, JS_APPn_JFIF, app_data); - - switch (app_data->units) { - case 1: - j_info->xdpi = app_data->Xdensity; - j_info->ydpi = app_data->Ydensity; - break; - case 2: /* density is in pixels per cm */ - j_info->xdpi = app_data->Xdensity * 2.54; - j_info->ydpi = app_data->Ydensity * 2.54; - break; - default: /* FIXME: not sure what to do with this.... */ - j_info->xdpi = 72.0; - j_info->ydpi = 72.0 * app_data->Ydensity / app_data->Xdensity; - break; - } - - return (9 + thumb_data_len); -} - -static unsigned short -read_APP0_JFXX (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - get_unsigned_byte(fp); - /* Extension Code: - * - * 0x10: Thumbnail coded using JPEG - * 0x11: Thumbnail stored using 1 byte/pixel - * 0x13: Thumbnail stored using 3 bytes/pixel - */ - seek_relative(fp, length-1); /* Thunbnail image */ - - /* Ignore */ - - return length; -} - -static unsigned short -read_APP2_ICC (struct JPEG_info *j_info, FILE *fp, unsigned short length) -{ - struct JPEG_APPn_ICC *app_data; - - app_data = NEW(1, struct JPEG_APPn_ICC); - app_data->seq_id = get_unsigned_byte(fp); /* Starting at 1 */ - app_data->num_chunks = get_unsigned_byte(fp); - app_data->length = length - 2; - app_data->chunk = NEW(app_data->length, unsigned char); - fread(app_data->chunk, 1, app_data->length, fp); - - add_APPn_marker(j_info, JM_APP2, JS_APPn_ICC, app_data); - - return length; -} - -static int -JPEG_copy_stream (struct JPEG_info *j_info, - pdf_obj *stream, FILE *fp, int flags) /* flags unused yet */ -{ - JPEG_marker marker; - long length, nb_read; - int found_SOFn, count; - - rewind(fp); - count = 0; - found_SOFn = 0; - while (!found_SOFn && - count < MAX_COUNT && - (marker = JPEG_get_marker(fp)) >= 0) { - if (marker == JM_SOI || - (marker >= JM_RST0 && marker <= JM_RST7)) { - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - pdf_add_stream(stream, work_buffer, 2); - count++; - continue; - } - length = get_unsigned_pair(fp) - 2; - switch (marker) { - case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: - case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: - case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: - case JM_SOF15: - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - work_buffer[2] = ((length + 2) >> 8) & 0xff; - work_buffer[3] = (length + 2) & 0xff; - pdf_add_stream(stream, work_buffer, 4); - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - if (nb_read > 0) - pdf_add_stream(stream, work_buffer, nb_read); - length -= nb_read; - } - found_SOFn = 1; - break; - default: - if (j_info->skipbits[count / 8] & (1 << (7 - (count % 8)))) { - /* skip */ - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - length -= nb_read; - } - } else { - work_buffer[0] = (char) 0xff; - work_buffer[1] = (char) marker; - work_buffer[2] = ((length + 2) >> 8) & 0xff; - work_buffer[3] = (length + 2) & 0xff; - pdf_add_stream(stream, work_buffer, 4); - while (length > 0) { - nb_read = fread(work_buffer, sizeof(char), - MIN(length, WORK_BUFFER_SIZE), fp); - if (nb_read > 0) - pdf_add_stream(stream, work_buffer, nb_read); - length -= nb_read; - } - } - } - count++; - } - - while ((length = fread(work_buffer, - sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) { - pdf_add_stream(stream, work_buffer, length); - } - - return (found_SOFn ? 0 : -1); -} - -static int -JPEG_scan_file (struct JPEG_info *j_info, FILE *fp) -{ - JPEG_marker marker; - unsigned short length; - int found_SOFn, count; - char app_sig[128]; - - rewind(fp); - count = 0; - found_SOFn = 0; - while (!found_SOFn && - (marker = JPEG_get_marker(fp)) >= 0) { - if (marker == JM_SOI || - (marker >= JM_RST0 && marker <= JM_RST7)) { - count++; - continue; - } - length = get_unsigned_pair(fp) - 2; - switch (marker) { - case JM_SOF0: case JM_SOF1: case JM_SOF2: case JM_SOF3: - case JM_SOF5: case JM_SOF6: case JM_SOF7: case JM_SOF9: - case JM_SOF10: case JM_SOF11: case JM_SOF13: case JM_SOF14: - case JM_SOF15: - j_info->bits_per_component = get_unsigned_byte(fp); - j_info->height = get_unsigned_pair(fp); - j_info->width = get_unsigned_pair(fp); - j_info->num_components = get_unsigned_byte(fp); - found_SOFn = 1; - break; - case JM_APP0: - if (length > 5) { - if (fread(app_sig, sizeof(char), 5, fp) != 5) - return -1; - length -= 5; - if (!memcmp(app_sig, "JFIF\000", 5)) { - j_info->flags |= HAVE_APPn_JFIF; - length -= read_APP0_JFIF(j_info, fp, length); - } else if (!memcmp(app_sig, "JFXX", 5)) { - length -= read_APP0_JFXX(j_info, fp, length); - } - } - 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)) { - j_info->flags |= HAVE_APPn_Exif; - 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) - return -1; - length -= 12; - if (!memcmp(app_sig, "ICC_PROFILE\000", 12)) { - j_info->flags |= HAVE_APPn_ICC; - length -= read_APP2_ICC(j_info, fp, length); - if (count < MAX_COUNT) { - j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); - } - } - } - seek_relative(fp, length); - break; - case JM_APP14: - if (length > 5) { - if (fread(app_sig, sizeof(char), 5, fp) != 5) - return -1; - length -= 5; - if (!memcmp(app_sig, "Adobe", 5)) { - j_info->flags |= HAVE_APPn_ADOBE; - length -= read_APP14_Adobe(j_info, fp, length); - } else { - if (count < MAX_COUNT) { - j_info->skipbits[count/8] |= (1 << (7 - (count % 8))); - } - } - } - seek_relative(fp, length); - break; - default: - seek_relative(fp, length); - if (marker >= JM_APP0 && - marker <= JM_APP15) { - if (count < MAX_COUNT) { - j_info->skipbits[count / 8] |= (1 << (7 - (count % 8))); - } - } - break; - } - count++; - } - - return (found_SOFn ? 0 : -1); -} - -int -jpeg_get_bbox (FILE *fp, long *width, long *height, - double *xdensity, double *ydensity) -{ - struct JPEG_info j_info; - - JPEG_info_init(&j_info); - - if (JPEG_scan_file(&j_info, fp) < 0) { - WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR); - JPEG_info_clear(&j_info); - return -1; - } - - *width = j_info.width; - *height = j_info.height; - - jpeg_get_density(&j_info, xdensity, ydensity); - - JPEG_info_clear(&j_info); - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfcolor.c b/Build/source/texk/dvipdfm-x/xsrc/pdfcolor.c deleted file mode 100644 index 1fff1c284b0..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfcolor.c +++ /dev/null @@ -1,1584 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -/* No page independence here... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfdoc.h" -#include "pdfdev.h" - -#include "pdfcolor.h" - - -static int verbose = 0; -void -pdf_color_set_verbose (void) -{ - verbose++; -} - -#ifndef XETEX -/* This function returns PDF_COLORSPACE_TYPE_GRAY, - * PDF_COLORSPACE_TYPE_RGB or PDF_COLORSPACE_TYPE_CMYK. - */ -int -pdf_color_type (const pdf_color *color) -{ - ASSERT(color); - - return -color->num_components; -} -#endif - -int -pdf_color_rgbcolor (pdf_color *color, double r, double g, double b) -{ - ASSERT(color); - - if (r < 0.0 || r > 1.0) { - WARN("Invalid color value specified: red=%g", r); - return -1; - } - if (g < 0.0 || g > 1.0) { - WARN("Invalid color value specified: green=%g", g); - return -1; - } - if (b < 0.0 || b > 1.0) { - WARN("Invalid color value specified: blue=%g", b); - return -1; - } - color->values[0] = r; - color->values[1] = g; - color->values[2] = b; - - color->num_components = 3; - - return 0; -} - -int -pdf_color_cmykcolor (pdf_color *color, - double c, double m, double y, double k) -{ - ASSERT(color); - - if (c < 0.0 || c > 1.0) { - WARN("Invalid color value specified: cyan=%g", c); - return -1; - } - if (m < 0.0 || m > 1.0) { - WARN("Invalid color value specified: magenta=%g", m); - return -1; - } - if (y < 0.0 || y > 1.0) { - WARN("Invalid color value specified: yellow=%g", y); - return -1; - } - if (k < 0.0 || k > 1.0) { - WARN("Invalid color value specified: black=%g", k); - return -1; - } - - color->values[0] = c; - color->values[1] = m; - color->values[2] = y; - color->values[3] = k; - - color->num_components = 4; - - return 0; -} - -int -pdf_color_graycolor (pdf_color *color, double g) -{ - ASSERT(color); - - if (g < 0.0 || g > 1.0) { - WARN("Invalid color value specified: gray=%g", g); - return -1; - } - - color->values[0] = g; - - color->num_components = 1; - - return 0; -} - - -void -pdf_color_copycolor (pdf_color *color1, const pdf_color *color2) -{ - ASSERT(color1 && color2); - - memcpy(color1, color2, sizeof(pdf_color)); -} - -#ifndef XETEX -/* Brighten up a color. f == 0 means no change, f == 1 means white. */ -void -pdf_color_brighten_color (pdf_color *dst, const pdf_color *src, double f) -{ - ASSERT(dst && src); - - if (f == 1.0) { - pdf_color_white(dst); - } else { - double f0, f1; - int n; - - n = dst->num_components = src->num_components; - f1 = n == 4 ? 0.0 : f; /* n == 4 is CMYK, others are RGB and Gray */ - f0 = 1.0-f; - - while (n--) - dst->values[n] = f0 * src->values[n] + f1; - } -} -#endif - -int -pdf_color_is_white (const pdf_color *color) -{ - int n; - double f; - - ASSERT(color); - - n = color->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - f = 1.0; - break; - case 4: /* CMYK */ - f = 0.0; - break; - default: - return 0; - } - - while (n--) - if (color->values[n] != f) - return 0; - - return 1; -} - -#ifndef XETEX -int -pdf_color_to_string (const pdf_color *color, char *buffer) -{ - int i, len = 0; - - for (i = 0; i < color->num_components; i++) { - len += sprintf(buffer+len, " %g", ROUND(color->values[i], 0.001)); - } - return len; -} -#endif - -pdf_color current_fill = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -pdf_color current_stroke = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -#ifndef XETEX -/* - * This routine is not a real color matching. - */ -int -pdf_color_compare (const pdf_color *color1, const pdf_color *color2) -{ - int n; - - n = color1->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - case 4: /* CMYK */ - break; - default: - return -1; - } - - if (n != color2->num_components) - return -1; - - while (n--) - if (color1->values[n] != color2->values[n]) - return -1; - - return 0; -} -#endif - -int -pdf_color_is_valid (const pdf_color *color) -{ - int n; - - n = color->num_components; - switch (n) { - case 1: /* Gray */ - case 3: /* RGB */ - case 4: /* CMYK */ - break; - default: - return 0; - } - - while (n--) - if (color->values[n] < 0.0 || color->values[n] > 1.0) { - WARN("Invalid color value: %g", color->values[n]); - return 0; - } - - return 1; -} - -/* Dvipdfm special */ -pdf_color default_color = { - 1, - {0.0, 0.0, 0.0, 0.0} -}; - -void -pdf_color_set_default (const pdf_color *color) -{ - pdf_color_copycolor(&default_color, color); -} - -#define DEV_COLOR_STACK_MAX 128 - -static struct { - int current; - pdf_color stroke[DEV_COLOR_STACK_MAX]; - pdf_color fill[DEV_COLOR_STACK_MAX]; -} color_stack = { - 0, -}; - -void -pdf_color_clear_stack (void) -{ - 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; -} - -#ifndef XETEX -void -pdf_color_set (pdf_color *sc, pdf_color *fc) -{ - pdf_color_copycolor(&color_stack.stroke[color_stack.current], sc); - pdf_color_copycolor(&color_stack.fill[color_stack.current], fc); - pdf_dev_reset_color(0); -} -#endif - -void -pdf_color_push (pdf_color *sc, pdf_color *fc) -{ - if (color_stack.current >= DEV_COLOR_STACK_MAX-1) { - WARN("Color stack overflow. Just ignore."); - } else { - 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(); - } - return; -} - -void -pdf_color_pop (void) -{ - if (color_stack.current <= 0) { - WARN("Color stack underflow. Just ignore."); - } else { - color_stack.current--; - pdf_dev_reset_color(); - } - return; -} - -void -pdf_color_get_current (pdf_color **sc, pdf_color **fc) -{ - *sc = &color_stack.stroke[color_stack.current]; - *fc = &color_stack.fill[color_stack.current]; - return; -} - -#ifdef XETEX -/* 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) -{ - if (color_stack.current > 0) { - current_stroke = color_stack.stroke[color_stack.current]; - current_fill = color_stack.fill[color_stack.current]; - } -} -#endif - -/***************************** COLOR SPACE *****************************/ - -static int pdf_colorspace_defineresource (const char *ident, - int subtype, - void *cdata, pdf_obj *resource); - -static int pdf_colorspace_findresource (const char *ident, - int subtype, const void *cdata); - -#if 0 -struct calgray_cdata -{ - double white_point[3]; /* required, second component must - * be equal to 1.0 - */ - double black_point[3]; /* optional, default: [0 0 0] */ - double gamma; /* optional, default: 1.0 */ -}; - -struct calrgb_cdata -{ - double white_point[3]; /* required, second component must - * be equal to 1.0 - */ - double black_point[3]; /* optional, default: [0 0 0] */ - double gamma[3]; /* optional, default: [1 1 1] */ - double matrix[9]; /* optional, default: identity - * [1 0 0 0 1 0 0 0 1] - */ -}; - -static void -release_calrgb (void *cdata) -{ - struct calrgb_cdata *calrgb; - - if (cdata) { - calrgb = (struct calrgb_cdata *) cdata; - RELEASE(calrgb); - } -} - -static int -compare_calrgb (const char *ident1, const void *cdata1, - const char *ident2, const void *cdata2) -{ - struct calrgb_cdata *calrgb1; - struct calrgb_cdata *calrgb2; - - if (ident1 && ident2 && - !strcmp(ident1, ident2)) { - return 0; - } -} - -static void -init_calrgb (struct calrgb_cdata *calrgb) -{ - ASSERT(calrgb); - - calrgb->white_point[0] = 1.0; - calrgb->white_point[1] = 1.0; - calrgb->white_point[2] = 1.0; - - calrgb->black_point[0] = 0.0; - calrgb->black_point[1] = 0.0; - calrgb->black_point[2] = 0.0; - - calrgb->gamma[0] = 1.0; - calrgb->gamma[1] = 1.0; - calrgb->gamma[2] = 1.0; - - calrgb->matrix[0] = 1.0; - calrgb->matrix[1] = 0.0; - calrgb->matrix[2] = 0.0; - - calrgb->matrix[3] = 0.0; - calrgb->matrix[4] = 1.0; - calrgb->matrix[5] = 0.0; - - calrgb->matrix[6] = 0.0; - calrgb->matrix[7] = 0.0; - calrgb->matrix[8] = 1.0; -} - -static int -valid_calrgb (struct calrgb_cdata *calrgb) -{ - if (calrgb->white_point[1] != 1.0 || - calrgb->white_point[0] <= 0.0 || - calrgb->white_point[2] <= 0.0) - return 0; - - if (calrgb->black_point[0] < 0.0 || - calrgb->black_point[1] < 0.0 || - calrgb->black_point[2] < 0.0) - return 0; - - if (calrgb->gamma[0] < 0.0 || - calrgb->gamma[1] < 0.0 || - calrgb->gamma[2] < 0.0) - return 0; - - /* matrix should be invertible? */ - - return 1; -} - -static pdf_obj * -pdf_color_make_calrgb_resource (struct calrgb_cdata *calrgb) -{ - pdf_obj *colorspace; - pdf_obj *calparams, *tmp_array; - - ASSERT(calrgb); - - if (!valid_calrgb(calrgb)) - return NULL; - - colorspace = pdf_new_array(); - calparams = pdf_new_dict(); - - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(1.0)); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->white_point[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("WhitePoint"), tmp_array); - - if (calrgb->black_point[0] != 0.0 || - calrgb->black_point[1] != 0.0 || - calrgb->black_point[2] != 0.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->black_point[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("BlackPoint"), tmp_array); - } - - if (calrgb->gamma[0] != 1.0 || - calrgb->gamma[1] != 1.0 || - calrgb->gamma[2] != 1.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->gamma[2], 0.001))); - pdf_add_dict(calparams, pdf_new_name("Gamma"), tmp_array); - } - - if (calrgb->matrix[0] != 1.0 || - calrgb->matrix[1] != 0.0 || - calrgb->matrix[2] != 0.0 || - calrgb->matrix[3] != 0.0 || - calrgb->matrix[4] != 1.0 || - calrgb->matrix[5] != 0.0 || - calrgb->matrix[6] != 0.0 || - calrgb->matrix[7] != 0.0 || - calrgb->matrix[8] != 1.0) { - tmp_array = pdf_new_array(); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[0], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[1], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[2], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[3], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[4], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[5], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[6], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[7], 0.001))); - pdf_add_array(tmp_array, pdf_new_number(ROUND(calrgb->matrix[8], 0.001))); - pdf_add_dict(calparams, pdf_new_name("Matrix"), tmp_array); - } - - pdf_add_array(colorspace, pdf_new_name("CalRGB")); - pdf_add_array(colorspace, calparams); - - return colorspace; -} -#endif - -static unsigned char nullbytes16[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static struct -{ - int major; - int minor; -} icc_versions[] = { - {0, 0}, /* PDF-1.0, we don't support them */ - {0, 0}, /* PDF-1.1, we don't support them */ - {0, 0}, /* PDF-1.2, we don't support them */ - {0x02, 0x10}, /* PDF-1.3 */ - {0x02, 0x20}, /* PDF-1.4 */ - {0x04, 0x00} /* PDF-1.5 */ -}; - -static int -iccp_version_supported (int major, int minor) -{ - int pdf_ver; - - pdf_ver = pdf_get_version(); - if (pdf_ver < 6) { - if (icc_versions[pdf_ver].major < major) - return 0; - else if (icc_versions[pdf_ver].major == major && - icc_versions[pdf_ver].minor < minor) - return 0; - else { - return 1; - } - } - - return 0; -} - -typedef unsigned long iccSig; -static iccSig -str2iccSig (const void *s) -{ - const char *p; - - p = (const char *) s; - - return (iccSig) ((p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]); -} - -typedef struct -{ - long X, Y, Z; /* s15Fixed16Numeber */ -} iccXYZNumber; - -typedef struct -{ - long size; - iccSig CMMType; - long version; - iccSig devClass; - iccSig colorSpace; - iccSig PCS; /* Profile Connection Space */ - char creationDate[12]; - iccSig acsp; - iccSig platform; - char flags[4]; - iccSig devMnfct; - iccSig devModel; - char devAttr[8]; - long intent; - iccXYZNumber illuminant; - iccSig creator; - unsigned char ID[16]; /* MD5 checksum with Rendering intent, - * Header attrs, Profile ID fields are - * set to zeros. - */ - /* 28 bytes reserved - must be set to zeros */ -} iccHeader; - -#define iccNullSig 0 -static void -iccp_init_iccHeader (iccHeader *icch) -{ - ASSERT(icch); - - icch->size = 0; - icch->CMMType = iccNullSig; - icch->version = 0xFFFFFF; - icch->devClass = iccNullSig; - icch->colorSpace = iccNullSig; - icch->PCS = iccNullSig; - memset(icch->creationDate, 0, 12); - icch->acsp = str2iccSig("ascp"); - icch->platform = iccNullSig; - memset(icch->flags, 0, 4); - icch->devMnfct = iccNullSig; - icch->devModel = iccNullSig; - memset(icch->devAttr, 0, 8); - icch->intent = 0; - icch->illuminant.X = 0; - icch->illuminant.Y = 0; - icch->illuminant.Z = 0; - icch->creator = iccNullSig; - memset(icch->ID, 0, 16); -} - -#define ICC_INTENT_TYPE(n) ((int) (((n) >> 16) & 0xff)) -#define ICC_INTENT_PERCEPTUAL 0 -#define ICC_INTENT_RELATIVE 1 -#define ICC_INTENT_SATURATION 2 -#define ICC_INTENT_ABSOLUTE 3 - -/* - * In ICC profile stream dicrionary, there is /Range whose values must - * "match the information in the profile". But where is those values in? - * - * How should I treat rendering intent? - */ -struct iccbased_cdata -{ - long sig; /* 'i' 'c' 'c' 'b' */ - - unsigned char checksum[16]; /* 16 bytes MD5 Checksum */ - int colorspace; /* input colorspace: - * RGB, Gray, CMYK, (Lab?) - */ - int alternate; /* alternate colorspace (id), unused */ -}; - -#define check_sig(d,p,q,r,s) ((d) && (d)->sig == ((p)<<24|(q)<<16|(r)<<8|(s))) - -static void -init_iccbased_cdata (struct iccbased_cdata *cdata) -{ - ASSERT(cdata); - - cdata->sig = ('i' << 24|'c' << 16|'c' << 8|'b'); - memset(cdata->checksum, 0, 16); - cdata->colorspace = PDF_COLORSPACE_TYPE_INVALID; - cdata->alternate = -1; - - return; -} - -static void -release_iccbased_cdata (struct iccbased_cdata *cdata) -{ - ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); - - RELEASE(cdata); -} - -static int -get_num_components_iccbased (const struct iccbased_cdata *cdata) -{ - int num_components = 0; - - ASSERT(check_sig(cdata, 'i', 'c', 'c', 'b')); - - switch (cdata->colorspace) { - case PDF_COLORSPACE_TYPE_RGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_CMYK: - num_components = 4; - break; - case PDF_COLORSPACE_TYPE_GRAY: - num_components = 1; - break; - case PDF_COLORSPACE_TYPE_CIELAB: - num_components = 3; - break; - } - - return num_components; -} - -static int -compare_iccbased (const char *ident1, const struct iccbased_cdata *cdata1, - const char *ident2, const struct iccbased_cdata *cdata2) -{ - if (cdata1 && cdata2) { - - ASSERT(check_sig(cdata1, 'i', 'c', 'c', 'b')); - ASSERT(check_sig(cdata2, 'i', 'c', 'c', 'b')); - - if (memcmp(cdata1->checksum, nullbytes16, 16) && - memcmp(cdata2->checksum, nullbytes16, 16)) { - return memcmp(cdata1->checksum, cdata2->checksum, 16); - } - if (cdata1->colorspace != cdata2->colorspace) { - return (cdata1->colorspace - cdata2->colorspace); - } - - /* Continue if checksum unknown and colorspace is same. */ - } - - if (ident1 && ident2) - return strcmp(ident1, ident2); - - /* No way to compare */ - return -1; -} - -int -iccp_check_colorspace (int colortype, const void *profile, long proflen) -{ - iccSig colorspace; - const unsigned char *p; - - if (!profile || proflen < 128) - return -1; - - p = (const unsigned char *) profile; - - colorspace = str2iccSig(p + 16); - - switch (colortype) { - case PDF_COLORSPACE_TYPE_CALRGB: - case PDF_COLORSPACE_TYPE_RGB: - if (colorspace != str2iccSig("RGB ")) { - return -1; - } - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - case PDF_COLORSPACE_TYPE_GRAY: - if (colorspace != str2iccSig("GRAY")) { - return -1; - } - break; - case PDF_COLORSPACE_TYPE_CMYK: - if (colorspace != str2iccSig("CMYK")) { - return -1; - } - break; - default: - return -1; - break; - } - - return 0; -} - -pdf_obj * -iccp_get_rendering_intent (const void *profile, long proflen) -{ - pdf_obj *ri = NULL; - const unsigned char *p; - long intent; - - if (!profile || proflen < 128) - return NULL; - - p = (const unsigned char *) profile; - - intent = (p[64] << 24)|(p[65] << 16)|(p[66] << 8)|p[67]; - switch (ICC_INTENT_TYPE(intent)) { - case ICC_INTENT_SATURATION: - ri = pdf_new_name("Saturation"); - break; - case ICC_INTENT_PERCEPTUAL: - ri = pdf_new_name("Perceptual"); - break; - case ICC_INTENT_ABSOLUTE: - ri = pdf_new_name("AbsoluteColorimetric"); - break; - case ICC_INTENT_RELATIVE: - ri = pdf_new_name("RelativeColorimetric"); - break; - default: - WARN("Invalid rendering intent type: %d", ICC_INTENT_TYPE(intent)); - ri = NULL; - } - - return ri; -} - -#define sget_signed_long(p) ((long) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) -#define sget_signed_short(p) ((short) ((p)[0] << 8|(p)[1])) -#define get_iccSig(p) ((iccSig) ((p)[0] << 24|(p)[1] << 16|(p)[2] << 8|(p)[3])) - -static int -iccp_unpack_header (iccHeader *icch, - const void *profile, long proflen, int check_size) -{ - const unsigned char *p, *endptr; - - if (check_size) { - if (!profile || proflen < 128 || - proflen % 4 != 0) { - WARN("Profile size: %ld", proflen); - return -1; - } - } - - p = (const unsigned char *) profile; - endptr = p + 128; - - icch->size = sget_signed_long(p); - if (check_size) { - if (icch->size != proflen) { - WARN("ICC Profile size: %ld(header) != %ld", icch->size, proflen); - return -1; - } - } - p += 4; - - icch->CMMType = str2iccSig(p); - p += 4; - icch->version = sget_signed_long(p); - p += 4; - icch->devClass = str2iccSig(p); - p += 4; - icch->colorSpace = str2iccSig(p); - p += 4; - icch->PCS = str2iccSig(p); - p += 4; - memcpy(icch->creationDate, p, 12); - p += 12; - icch->acsp = str2iccSig(p); /* acsp */ - if (icch->acsp != str2iccSig("acsp")) { - WARN("Invalid ICC profile: not \"acsp\" - %c%c%c%c ", - p[0], p[1], p[2], p[3]); - return -1; - } - p += 4; - icch->platform = str2iccSig(p); - p += 4; - memcpy(icch->flags, p, 4); - p += 4; - icch->devMnfct = str2iccSig(p); - p += 4; - icch->devModel = str2iccSig(p); - p += 4; - memcpy(icch->devAttr, p, 8); - p += 8; - icch->intent = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; - p += 4; - icch->illuminant.X = sget_signed_long(p); - p += 4; - icch->illuminant.Y = sget_signed_long(p); - p += 4; - icch->illuminant.Z = sget_signed_long(p); - p += 4; - icch->creator = str2iccSig(p); - p += 4; - memcpy(icch->ID, p, 16); - p += 16; - - /* 28 bytes reserved - must be set to zeros */ - for (; p < endptr; p++) { - if (*p != '\0') { - WARN("Reserved pad not zero: %02x (at offset %ld in ICC profile header.)", - *p, 128 - ((long) (endptr - p))); - return -1; - } - } - - return 0; -} - -/* MD5 checksum with Rendering intent, - * Header attrs, Profile ID fields are - * set to zeros. - */ -#define ICC_HEAD_SECT1_START 0 -#define ICC_HEAD_SECT1_LENGTH 56 -/* 8 bytes devAttr, 4 bytes intent */ -#define ICC_HEAD_SECT2_START 68 -#define ICC_HEAD_SECT2_LENGTH 16 -/* 16 bytes ID (checksum) */ -#define ICC_HEAD_SECT3_START 100 -#define ICC_HEAD_SECT3_LENGTH 28 - -#include "dpxcrypt.h" -static void -iccp_get_checksum (unsigned char *checksum, const void *profile, long proflen) -{ - const unsigned char *p; - MD5_CONTEXT md5; - - p = (const unsigned char *) profile; - - MD5_init (&md5); - MD5_write(&md5, p + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); - MD5_write(&md5, nullbytes16, 12); - MD5_write(&md5, p + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); - MD5_write(&md5, nullbytes16, 16); - MD5_write(&md5, p + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); - - /* body */ - MD5_write(&md5, p + 128, proflen - 128); - - MD5_final(checksum, &md5); -} - -static void -print_iccp_header (iccHeader *icch, unsigned char *checksum) -{ - int i; - - ASSERT(icch); - -#define print_iccSig(s,t) if ((s) == 0) {\ - MESG("pdf_color>> %s:\t(null)\n", (t)); \ - } else if (!isprint(((s) >> 24) & 0xff) || \ - !isprint(((s) >> 16) & 0xff) || \ - !isprint(((s) >> 8) & 0xff) || \ - !isprint((s) & 0xff)) { \ - MESG("pdf_color>> %s:\t(invalid)\n", (t)); \ - } else { \ - MESG("pdf_color>> %s:\t%c%c%c%c\n", (t), \ - ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, \ - ((s) >> 8) & 0xff, (s) & 0xff); \ -} - - MESG("\n"); - MESG("pdf_color>> ICC Profile Info\n"); - MESG("pdf_color>> Profile Size:\t%ld bytes\n", icch->size); - print_iccSig(icch->CMMType, "CMM Type"); - MESG("pdf_color>> Profile Version:\t%d.%01d.%01d\n", - (icch->version >> 24) & 0xff, - (icch->version >> 20) & 0x0f, - (icch->version >> 16) & 0x0f); - print_iccSig(icch->devClass, "Device Class"); - print_iccSig(icch->colorSpace, "Color Space"); - print_iccSig(icch->PCS, "Connection Space"); - MESG("pdf_color>> Creation Date:\t"); - for (i = 0; i < 12; i += 2) { - if (i == 0) - MESG("%04u", - sget_unsigned_pair((unsigned char *) icch->creationDate)); - else { - MESG(":%02u", - sget_unsigned_pair((unsigned char *) (&icch->creationDate[i]))); - } - } - MESG("\n"); - print_iccSig(icch->platform, "Primary Platform"); - MESG("pdf_color>> Profile Flags:\t%02x:%02x:%02x:%02x\n", - icch->flags[0], icch->flags[1], icch->flags[2], icch->flags[3]); - print_iccSig(icch->devMnfct, "Device Mnfct"); - print_iccSig(icch->devModel, "Device Model"); - MESG("pdf_color>> Device Attr:\t"); - for (i = 0; i < 8; i++) { - if (i == 0) - MESG("%02x", icch->devAttr[i]); - else - MESG(":%02x", icch->devAttr[i]); - } - MESG("\n"); - MESG("pdf_color>> Rendering Intent:\t"); - switch (ICC_INTENT_TYPE(icch->intent)) { - case ICC_INTENT_SATURATION: - MESG("Saturation"); - break; - case ICC_INTENT_PERCEPTUAL: - MESG("Perceptual"); - break; - case ICC_INTENT_ABSOLUTE: - MESG("Absolute Colorimetric"); - break; - case ICC_INTENT_RELATIVE: - MESG("Relative Colorimetric"); - break; - default: - MESG("(invalid)"); - break; - } - MESG("\n"); - print_iccSig(icch->creator, "Creator"); - MESG("pdf_color>> Illuminant (XYZ):\t"); - MESG("%.3f %.3f %.3f\n", - (double) icch->illuminant.X / 0x10000, - (double) icch->illuminant.Y / 0x10000, - (double) icch->illuminant.Z / 0x10000); - MESG("pdf_color>> Checksum:\t"); - if (!memcmp(icch->ID, nullbytes16, 16)) { - MESG("(null)"); - } else { - for (i = 0; i < 16; i++) { - if (i == 0) - MESG("%02x", icch->ID[i]); - else - MESG(":%02x", icch->ID[i]); - } - } - MESG("\n"); - if (checksum) { - MESG("pdf_color>> Calculated:\t"); - for (i = 0; i < 16; i++) { - if (i == 0) - MESG("%02x", checksum[i]); - else - MESG(":%02x", checksum[i]); - } - MESG("\n"); - } - - return; -} - - -static int -iccp_devClass_allowed (int dev_class) -{ - int colormode; - - colormode = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - - switch (colormode) { -#if 0 - case PDF_DEV_COLORMODE_PDFX1: - break; - case PDF_DEV_COLORMODE_PDFX3: - if (dev_class != str2iccSig("prtr")) { - return 0; - } - break; -#endif - default: - if (dev_class != str2iccSig("scnr") && - dev_class != str2iccSig("mntr") && - dev_class != str2iccSig("prtr") && - dev_class != str2iccSig("spac")) { - return 0; - } - break; - } - - - return 1; -} - -int -iccp_load_profile (const char *ident, - const void *profile, long proflen) -{ - int cspc_id; - pdf_obj *resource; - pdf_obj *stream; - pdf_obj *stream_dict; - iccHeader icch; - int colorspace; - unsigned char checksum[16]; - struct iccbased_cdata *cdata; - - iccp_init_iccHeader(&icch); - if (iccp_unpack_header(&icch, profile, proflen, 1) < 0) { /* check size */ - WARN("Invalid ICC profile header in \"%s\"", ident); - print_iccp_header(&icch, NULL); - return -1; - } - - if (!iccp_version_supported((icch.version >> 24) & 0xff, - (icch.version >> 16) & 0xff)) { - WARN("ICC profile format spec. version %d.%01d.%01d" - " not supported in current PDF version setting.", - (icch.version >> 24) & 0xff, - (icch.version >> 20) & 0x0f, - (icch.version >> 16) & 0x0f); - WARN("ICC profile not embedded."); - print_iccp_header(&icch, NULL); - return -1; - } - - if (!iccp_devClass_allowed(icch.devClass)) { - WARN("Unsupported ICC Profile Device Class:"); - print_iccp_header(&icch, NULL); - return -1; - } - - if (icch.colorSpace == str2iccSig("RGB ")) { - colorspace = PDF_COLORSPACE_TYPE_RGB; - } else if (icch.colorSpace == str2iccSig("GRAY")) { - colorspace = PDF_COLORSPACE_TYPE_GRAY; - } else if (icch.colorSpace == str2iccSig("CMYK")) { - colorspace = PDF_COLORSPACE_TYPE_CMYK; - } else { - WARN("Unsupported input color space."); - print_iccp_header(&icch, NULL); - return -1; - } - - iccp_get_checksum(checksum, profile, proflen); - if (memcmp(icch.ID, nullbytes16, 16) && - memcmp(icch.ID, checksum, 16)) { - WARN("Invalid ICC profile: Inconsistent checksum."); - print_iccp_header(&icch, checksum); - return -1; - } - - cdata = NEW(1, struct iccbased_cdata); - init_iccbased_cdata(cdata); - cdata->colorspace = colorspace; - memcpy(cdata->checksum, checksum, 16); - - cspc_id = pdf_colorspace_findresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, cdata); - if (cspc_id >= 0) { - if (verbose) - MESG("(ICCP:[id=%d])", cspc_id); - release_iccbased_cdata(cdata); - return cspc_id; - } - if (verbose > 1) { - print_iccp_header(&icch, checksum); - } - - resource = pdf_new_array(); - - stream = pdf_new_stream(STREAM_COMPRESS); - pdf_add_array(resource, pdf_new_name("ICCBased")); - pdf_add_array(resource, pdf_ref_obj (stream)); - - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, pdf_new_name("N"), - pdf_new_number(get_num_components_iccbased(cdata))); - - pdf_add_stream (stream, profile, proflen); - pdf_release_obj(stream); - - cspc_id = pdf_colorspace_defineresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, - cdata, resource); - - return cspc_id; -} - -#ifdef XETEX -#define WBUF_SIZE 4096 -static unsigned char wbuf[WBUF_SIZE]; - -static pdf_obj * -iccp_load_file_stream (unsigned char *checksum, long length, FILE *fp) -{ - pdf_obj *stream; - MD5_CONTEXT md5; - long nb_read; - - rewind(fp); - - if (fread(wbuf, 1, 128, fp) != 128) { - return NULL; - } - length -= 128; - - stream = pdf_new_stream(STREAM_COMPRESS); - - MD5_init (&md5); - MD5_write(&md5, wbuf + ICC_HEAD_SECT1_START, ICC_HEAD_SECT1_LENGTH); - MD5_write(&md5, nullbytes16, 12); - MD5_write(&md5, wbuf + ICC_HEAD_SECT2_START, ICC_HEAD_SECT2_LENGTH); - MD5_write(&md5, nullbytes16, 16); - MD5_write(&md5, wbuf + ICC_HEAD_SECT3_START, ICC_HEAD_SECT3_LENGTH); - - pdf_add_stream(stream, wbuf, 128); - - /* body */ - while (length > 0) { - nb_read = fread(wbuf, 1, MIN(length, WBUF_SIZE), fp); - MD5_write(&md5, wbuf, nb_read); - pdf_add_stream(stream, wbuf, nb_read); - length -= nb_read; - } - - MD5_final(checksum, &md5); - - - return stream; -} - -int -pdf_colorspace_load_ICCBased (const char *ident, const char *filename) -{ - int cspc_id; - FILE *fp; - pdf_obj *resource; - pdf_obj *stream; - pdf_obj *stream_dict; - iccHeader icch; - int colorspace; - long size; - unsigned char checksum[16]; - struct iccbased_cdata *cdata; - - - fp = DPXFOPEN(filename, DPX_RES_TYPE_ICCPROFILE); - if (!fp) - return -1; - - size = file_size(fp); - if (size < 128) { - MFCLOSE(fp); - return -1; - } - if (fread(wbuf, 1, 128, fp) != 128) { - DPXFCLOSE(fp); - return -1; - } - - iccp_init_iccHeader(&icch); - if (iccp_unpack_header(&icch, wbuf, 128, 0) < 0) { - WARN("Invalid ICC profile header in \"%s\"", ident); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - if (icch.size > size) { - WARN("File size smaller than recorded in header: %ld %ld", - icch.size, size); - DPXFCLOSE(fp); - return -1; - } - - if (!iccp_version_supported((icch.version >> 24) & 0xff, - (icch.version >> 16) & 0xff)) { - WARN("ICC profile format spec. version %d.%01d.%01d" - " not supported in current PDF version setting.", - (icch.version >> 24) & 0xff, - (icch.version >> 20) & 0x0f, - (icch.version >> 16) & 0x0f); - WARN("ICC profile not embedded."); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - if (!iccp_devClass_allowed(icch.devClass)) { - WARN("Unsupported ICC Profile Device Class:"); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - if (icch.colorSpace == str2iccSig("RGB ")) { - colorspace = PDF_COLORSPACE_TYPE_RGB; - } else if (icch.colorSpace == str2iccSig("GRAY")) { - colorspace = PDF_COLORSPACE_TYPE_GRAY; - } else if (icch.colorSpace == str2iccSig("CMYK")) { - colorspace = PDF_COLORSPACE_TYPE_CMYK; - } else { - WARN("Unsupported input color space."); - print_iccp_header(&icch, NULL); - DPXFCLOSE(fp); - return -1; - } - - stream = iccp_load_file_stream(checksum, icch.size, fp); - DPXFCLOSE(fp); - - if (!stream) { - WARN("Loading ICC Profile failed...: %s", filename); - return -1; - } - - if (memcmp(icch.ID, nullbytes16, 16) && - memcmp(icch.ID, checksum, 16)) { - WARN("Invalid ICC profile: Inconsistent checksum."); - print_iccp_header(&icch, NULL); - pdf_release_obj(stream); - return -1; - } - - cdata = NEW(1, struct iccbased_cdata); - init_iccbased_cdata(cdata); - cdata->colorspace = colorspace; - memcpy(cdata->checksum, checksum, 16); - - cspc_id = pdf_colorspace_findresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, cdata); - if (cspc_id >= 0) { - if (verbose) - MESG("(ICCP:[id=%d])", cspc_id); - release_iccbased_cdata(cdata); - pdf_release_obj(stream); - return cspc_id; - } - if (verbose > 1) { - print_iccp_header(&icch, checksum); - } - - resource = pdf_new_array(); - - pdf_add_array(resource, pdf_new_name("ICCBased")); - pdf_add_array(resource, pdf_ref_obj (stream)); - - stream_dict = pdf_stream_dict(stream); - pdf_add_dict(stream_dict, pdf_new_name("N"), - pdf_new_number(get_num_components_iccbased(cdata))); - pdf_release_obj(stream); - - cspc_id = pdf_colorspace_defineresource(ident, - PDF_COLORSPACE_TYPE_ICCBASED, - cdata, resource); - - return cspc_id; -} -#endif - -typedef struct { - char *ident; - int subtype; - - pdf_obj *resource; - pdf_obj *reference; - - void *cdata; -} pdf_colorspace; - -static struct { - int count; - int capacity; - pdf_colorspace *colorspaces; -} cspc_cache = { - 0, 0, NULL -}; - -int -pdf_colorspace_findresource (const char *ident, - int type, const void *cdata) -{ - pdf_colorspace *colorspace; - int cspc_id, cmp = -1; - - for (cspc_id = 0; - cmp && cspc_id < cspc_cache.count; cspc_id++) { - colorspace = &cspc_cache.colorspaces[cspc_id]; - if (colorspace->subtype != type) - continue; - - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - cmp = compare_iccbased(ident, cdata, - colorspace->ident, colorspace->cdata); - break; - } - if (!cmp) - return cspc_id; - } - - return -1; /* not found */ -} - -static void -pdf_init_colorspace_struct (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - colorspace->ident = NULL; - colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; - - colorspace->resource = NULL; - colorspace->reference = NULL; - colorspace->cdata = NULL; - - return; -} - -static void -pdf_clean_colorspace_struct (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - if (colorspace->ident) - RELEASE(colorspace->ident); - if (colorspace->resource) - pdf_release_obj(colorspace->resource); - if (colorspace->reference) - pdf_release_obj(colorspace->reference); - colorspace->resource = NULL; - colorspace->reference = NULL; - - if (colorspace->cdata) { - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - release_iccbased_cdata(colorspace->cdata); - break; - } - } - colorspace->cdata = NULL; - colorspace->subtype = PDF_COLORSPACE_TYPE_INVALID; - - return; -} - -static void -pdf_flush_colorspace (pdf_colorspace *colorspace) -{ - ASSERT(colorspace); - - if (colorspace->resource) - pdf_release_obj(colorspace->resource); - if (colorspace->reference) - pdf_release_obj(colorspace->reference); - - colorspace->resource = NULL; - colorspace->reference = NULL; -} - -int -pdf_colorspace_defineresource (const char *ident, - int subtype, void *cdata, pdf_obj *resource) -{ - int cspc_id; - pdf_colorspace *colorspace; - - if (cspc_cache.count >= cspc_cache.capacity) { - cspc_cache.capacity += 16; - cspc_cache.colorspaces = RENEW(cspc_cache.colorspaces, - cspc_cache.capacity, pdf_colorspace); - } - cspc_id = cspc_cache.count; - colorspace = &cspc_cache.colorspaces[cspc_id]; - - pdf_init_colorspace_struct(colorspace); - if (ident) { - colorspace->ident = NEW(strlen(ident) + 1, char); - strcpy(colorspace->ident, ident); - } - colorspace->subtype = subtype; - colorspace->cdata = cdata; - colorspace->resource = resource; - - if (verbose) { - MESG("(ColorSpace:%s", ident); - if (verbose > 1) { - switch (subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - MESG("[ICCBased]"); - break; - case PDF_COLORSPACE_TYPE_CALRGB: - MESG("[CalRGB]"); - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - MESG("[CalGray]"); - break; - } - } - MESG(")"); - } - - cspc_cache.count++; - - return cspc_id; -} - -pdf_obj * -pdf_get_colorspace_reference (int cspc_id) -{ - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - if (!colorspace->reference) { - colorspace->reference = pdf_ref_obj(colorspace->resource); - pdf_release_obj(colorspace->resource); /* .... */ - colorspace->resource = NULL; - } - - return pdf_link_obj(colorspace->reference); -} - -#if 0 -int -pdf_get_colorspace_num_components (int cspc_id) -{ - pdf_colorspace *colorspace; - int num_components; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - - switch (colorspace->subtype) { - case PDF_COLORSPACE_TYPE_ICCBASED: - num_components = get_num_components_iccbased(colorspace->cdata); - break; - case PDF_COLORSPACE_TYPE_DEVICEGRAY: - num_components = 1; - break; - case PDF_COLORSPACE_TYPE_DEVICERGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_DEVICECMYK: - num_components = 4; - break; - case PDF_COLORSPACE_TYPE_CALRGB: - num_components = 3; - break; - case PDF_COLORSPACE_TYPE_CALGRAY: - num_components = 1; - break; - default: - num_components = 0; - break; - } - - return num_components; -} - -int -pdf_get_colorspace_subtype (int cspc_id) -{ - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[cspc_id]; - - return colorspace->subtype; -} -#endif - -void -pdf_init_colors (void) -{ - cspc_cache.count = 0; - cspc_cache.capacity = 0; - cspc_cache.colorspaces = NULL; -} - -void -pdf_close_colors (void) -{ - int i; - - for (i = 0; i < cspc_cache.count; i++) { - pdf_colorspace *colorspace; - - colorspace = &cspc_cache.colorspaces[i]; - pdf_flush_colorspace(colorspace); - pdf_clean_colorspace_struct(colorspace); - } - RELEASE(cspc_cache.colorspaces); - cspc_cache.colorspaces = NULL; - cspc_cache.count = cspc_cache.capacity = 0; - -} - -#define PDF_COLORSPACE_FAMILY_DEVICE 0 -#define PDF_COLORSPACE_FAMILY_CIEBASED 1 -#define PDF_COLORSPACE_FAMILY_SPECIAL 2 diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfdev.c b/Build/source/texk/dvipdfm-x/xsrc/pdfdev.c deleted file mode 100644 index c5f857920e2..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfdev.c +++ /dev/null @@ -1,2004 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "mfileio.h" -#include "numbers.h" - -#include "pdfdoc.h" -#include "pdfobj.h" - -#include "pdffont.h" -#include "fontmap.h" -#include "cmap.h" -#include "pdfximage.h" - -#include "pdfdraw.h" -#include "pdfcolor.h" - -#include "pdflimits.h" - -#include "dvi.h" - -#include "pdfdev.h" - -static int verbose = 0; - -void -pdf_dev_set_verbose (void) -{ - verbose++; -} - -/* Not working yet... */ -double -pdf_dev_scale (void) -{ - return 1.0; -} - -/* - * Unit conversion, formatting and others. - */ - -#define TEX_ONE_HUNDRED_BP 6578176 -static struct { - double dvi2pts; - long min_bp_val; /* Shortest resolvable distance in the output PDF. */ - int precision; /* Number of decimal digits (in fractional part) kept. */ -} dev_unit = { - 0.0, - 658, - 2 -}; - - -double -dev_unit_dviunit (void) -{ - return (1.0/dev_unit.dvi2pts); -} - -#define DEV_PRECISION_MAX 8 -static unsigned long ten_pow[10] = { - 1ul, 10ul, 100ul, 1000ul, 10000ul, 100000ul, 1000000ul, 10000000ul, 100000000ul, 1000000000ul -}; - -static double ten_pow_inv[10] = { - 1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001 -}; - -#define bpt2spt(b) ( (spt_t) round( (b) / dev_unit.dvi2pts ) ) -#define spt2bpt(s) ( (s) * dev_unit.dvi2pts ) -#define dround_at(v,p) (ROUND( (v), ten_pow_inv[(p)] )) - -static int -p_itoa (long value, char *buf) -{ - int sign, ndigits; - char *p = buf; - - if (value < 0) { - *p++ = '-'; - value = -value; - sign = 1; - } else { - sign = 0; - } - - ndigits = 0; - /* Generate at least one digit in reverse order */ - do { - p[ndigits++] = (value % 10) + '0'; - value /= 10; - } while (value != 0); - - /* Reverse the digits */ - { - int i; - - for (i = 0; i < ndigits / 2 ; i++) { - char tmp = p[i]; - p[i] = p[ndigits-i-1]; - p[ndigits-i-1] = tmp; - } - } - p[ndigits] = '\0'; - - return (sign ? ndigits + 1 : ndigits); -} - -/* ... */ -static int -p_dtoa (double value, int prec, char *buf) -{ - int n; - char *p, *q; - - n = sprintf(buf, "%.*f", prec, value); - /* find decimal-point */ - for (p = buf + n - 1; p > buf && *p != '.'; p--); - if (p > buf) { - /* chop trailing zeros */ - for (q = buf + n - 1; q > p && *q == '0'; q--) { - *q = '\0'; n--; - } - /* If a decimal point appears, at least one digit appears - * before it. - */ - if (q == p) { - *q = '\0'; n--; - } - } - /* -0 --> 0 */ - if (n == 2 && buf[0] == '-' && buf[1] == '0') { - buf[0] = '0'; buf[1] = '\0'; n = 1; - } - - return n; -} - -static int -dev_sprint_bp (char *buf, spt_t value, spt_t *error) -{ - double value_in_bp; - double error_in_bp; - int prec = dev_unit.precision; - - value_in_bp = spt2bpt(value); - if (error) { - error_in_bp = value_in_bp - dround_at(value_in_bp, prec); - *error = bpt2spt(error_in_bp); - } - - return p_dtoa(value_in_bp, prec, buf); -} - -/* They are affected by precision (set at device initialization). */ -int -pdf_sprint_matrix (char *buf, const pdf_tmatrix *M) -{ - int len; - int prec2 = MIN(dev_unit.precision + 2, DEV_PRECISION_MAX); - int prec0 = MAX(dev_unit.precision, 2); - - len = p_dtoa(M->a, prec2, buf); - buf[len++] = ' '; - len += p_dtoa(M->b, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->c, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->d, prec2, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->e, prec0, buf+len); - buf[len++] = ' '; - len += p_dtoa(M->f, prec0, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_rect (char *buf, const pdf_rect *rect) -{ - int len; - - len = p_dtoa(rect->llx, dev_unit.precision, buf); - buf[len++] = ' '; - len += p_dtoa(rect->lly, dev_unit.precision, buf+len); - buf[len++] = ' '; - len += p_dtoa(rect->urx, dev_unit.precision, buf+len); - buf[len++] = ' '; - len += p_dtoa(rect->ury, dev_unit.precision, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_coord (char *buf, const pdf_coord *p) -{ - int len; - - len = p_dtoa(p->x, dev_unit.precision, buf); - buf[len++] = ' '; - len += p_dtoa(p->y, dev_unit.precision, buf+len); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - -int -pdf_sprint_length (char *buf, double value) -{ - int len; - - len = p_dtoa(value, dev_unit.precision, buf); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - - -int -pdf_sprint_number (char *buf, double value) -{ - int len; - - len = p_dtoa(value, DEV_PRECISION_MAX, buf); - buf[len] = '\0'; /* xxx_sprint_xxx NULL terminates strings. */ - - return len; -} - - -static struct -{ - /* Text composition (direction) mode is ignored (always same - * as font's writing mode) if autorotate is unset (value zero). - */ - int autorotate; - - /* - * Ignore color migrated to here. This is device's capacity. - * colormode 0 for ignore colors - */ - int colormode; - -} dev_param = { - 1, /* autorotate */ - 1, /* colormode */ -}; - -/* - * Text handling routines. - */ - -/* Motion state: - * GRAPHICS_MODE Initial state (not within BT/ET block nor in string) - * TEXT_MODE Text section is started via BT operator but not - * in string. - * STRING_MODE In string. A string or array of strings are currently - * in process. May started '[', '<' or '('. - */ -#define GRAPHICS_MODE 1 -#define TEXT_MODE 2 -#define STRING_MODE 3 - -static int motion_state = GRAPHICS_MODE; - -#define FORMAT_BUF_SIZE 4096 -static char format_buffer[FORMAT_BUF_SIZE]; - -/* - * In PDF, vertical text positioning is always applied when current font - * is vertical font. While ASCII pTeX manages current writing direction - * and font's WMode separately. - * - * 00/11 WMODE_HH/VV h(v) font, h(v) direction. - * 01 WMODE_HV -90 deg. rotated - * 10 WMODE_VH +90 deg. rotated - * - * In MetaPost PostScript file processing (mp_mode = 1), only HH/VV mode - * is applied. - */ -#define TEXT_WMODE_HH 0 -#define TEXT_WMODE_HV 1 -#define TEXT_WMODE_VH 2 -#define TEXT_WMODE_VV 3 - -#define ANGLE_CHANGES(m1,m2) ((abs((m1)-(m2)) % 3) == 0 ? 0 : 1) -#define ROTATE_TEXT(m) ((m) != TEXT_WMODE_HH && (m) != TEXT_WMODE_VV) - -static struct { - - /* Current font. - * This is index within dev_fonts. - */ - int font_id; - - /* Dvipdfmx does compression of text by doing text positioning - * in relative motion and uses string array [(foo) -250 (bar)] - * with kerning (negative kern is used for white space as suited - * for TeX). This is offset within current string. - */ - spt_t offset; - - /* This is reference point of strings. - * It may include error correction induced by rounding. - */ - spt_t ref_x; - spt_t ref_y; - - /* Using text raise and leading is highly recommended for - * text extraction to work properly. But not implemented yet. - * We can't do consice output for \TeX without this. - */ - spt_t raise; /* unused */ - spt_t leading; /* unused */ - - /* This is not always text matrix but rather font matrix. - * We do not use horizontal scaling in PDF text state parameter - * since they always apply scaling in fixed direction regardless - * of writing mode. - */ - struct { - double slant; - double extend; - int rotate; /* TEXT_WMODE_XX */ - } matrix; - - /* Fake bold parameter: - * If bold_param is positive, use text rendering mode - * fill-then-stroke with stroking line width specified - * by bold_param. - */ - double bold_param; - - /* Text composition (direction) mode. */ - int dir_mode; - - /* internal */ - - /* Flag indicating text matrix to be forcibly reset. - * Enabled if synthetic font features (slant, extend, etc) - * are used for current font or when text rotation mode - * changes. - */ - int force_reset; - - /* This information is duplicated from dev[font_id].format. - * Set to 1 if font is composite (Type0) font. - */ - int is_mb; -} text_state = { - -1, /* font */ - 0, /* offset */ - 0, 0, /* ref_x, ref_y */ - 0, 0, /* raise, leading */ - {0.0, 1.0, 0}, - - 0.0, /* Experimental boldness param */ - - 0, /* dir_mode */ - - /* internal */ - 0, /* force_reset */ - 0 /* is_mb */ -}; - -#define PDF_FONTTYPE_SIMPLE 1 -#define PDF_FONTTYPE_BITMAP 2 -#define PDF_FONTTYPE_COMPOSITE 3 - -struct dev_font { - /* Needs to be big enough to hold name "Fxxx" - * where xxx is number of largest font - */ - char short_name[7]; /* Resource name */ - int used_on_this_page; - - char *tex_name; /* String identifier of this font */ - spt_t sptsize; /* Point size */ - - /* Returned values from font/encoding layer: - * - * The font_id and enc_id is font and encoding (CMap) identifier - * used in pdf_font or encoding/cmap layer. - * The PDF object "resource" is an indirect reference object - * pointing font resource of this font. The used_chars is somewhat - * misleading, this is actually used_glyphs in CIDFont for Type0 - * and is 65536/8 bytes binary data with each bits representing - * whether the glyph is in-use or not. It is 256 char array for - * simple font. - */ - int font_id; - int enc_id; -#ifdef XETEX - unsigned short *ft_to_gid; - - /* if >= 0, index of a dev_font that really has the resource and used_chars */ - int real_font_index; -#endif - - pdf_obj *resource; - char *used_chars; - - /* Font format: - * simple, composite or bitmap. - */ - int format; - - /* Writing mode: - * Non-zero for vertical. Duplicated from CMap. - */ - int wmode; - - /* Syntetic Font: - * - * We use text matrix for creating extended or slanted font, - * but not with font's FontMatrix since TrueType and Type0 - * font don't support them. - */ - double extend; - double slant; - double bold; /* Boldness prameter */ - - /* Compatibility */ - int mapc; /* Nasty workaround for Omega */ - - /* There are no font metric format supporting four-bytes - * charcter code. So we should provide an option to specify - * UCS group and plane. - */ - int ucs_group; - int ucs_plane; - - int is_unicode; -}; -static struct dev_font *dev_fonts = NULL; - -static int num_dev_fonts = 0; -static int max_dev_fonts = 0; -static int num_phys_fonts = 0; - -#define CURRENTFONT() ((text_state.font_id < 0) ? NULL : &(dev_fonts[text_state.font_id])) -#define GET_FONT(n) (&(dev_fonts[(n)])) - - -static void -dev_set_text_matrix (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - pdf_tmatrix tm; - int len = 0; - - /* slant is negated for vertical font so that right-side - * is always lower. */ - switch (rotate) { - case TEXT_WMODE_VH: - /* Vertical font */ - tm.a = slant ; tm.b = 1.0; - tm.c = -extend; tm.d = 0.0 ; - break; - case TEXT_WMODE_HV: - /* Horizontal font */ - tm.a = 0.0; tm.b = -extend; - tm.c = 1.0; tm.d = -slant ; - break; - case TEXT_WMODE_HH: - /* Horizontal font */ - tm.a = extend; tm.b = 0.0; - tm.c = slant ; tm.d = 1.0; - break; - case TEXT_WMODE_VV: - /* Vertical font */ - tm.a = 1.0; tm.b = -slant; - tm.c = 0.0; tm.d = extend; - break; - } - tm.e = xpos * dev_unit.dvi2pts; - tm.f = ypos * dev_unit.dvi2pts; - - format_buffer[len++] = ' '; - len += pdf_sprint_matrix(format_buffer+len, &tm); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'm'; - - pdf_doc_add_page_content(format_buffer, len); /* op: Tm */ - - text_state.ref_x = xpos; - text_state.ref_y = ypos; - text_state.matrix.slant = slant; - text_state.matrix.extend = extend; - text_state.matrix.rotate = rotate; -} - -/* - * reset_text_state() outputs a BT and does any necessary coordinate - * transformations to get ready to ship out text. - */ - -static void -reset_text_state (void) -{ - /* - * We need to reset the line matrix to handle slanted fonts. - */ - pdf_doc_add_page_content(" BT", 3); /* op: BT */ - /* - * text_state.matrix is identity at top of page. - * This sometimes write unnecessary "Tm"s when transition from - * GRAPHICS_MODE to TEXT_MODE occurs. - */ - if (text_state.force_reset || - text_state.matrix.slant != 0.0 || - text_state.matrix.extend != 1.0 || - ROTATE_TEXT(text_state.matrix.rotate)) { - dev_set_text_matrix(0, 0, - text_state.matrix.slant, - text_state.matrix.extend, - text_state.matrix.rotate); - } - text_state.ref_x = 0; - text_state.ref_y = 0; - text_state.offset = 0; - text_state.force_reset = 0; -} - -static void -text_mode (void) -{ - switch (motion_state) { - case TEXT_MODE: - break; - case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ - break; - case GRAPHICS_MODE: - reset_text_state(); - break; - } - motion_state = TEXT_MODE; - text_state.offset = 0; -} - -void -graphics_mode (void) -{ - switch (motion_state) { - case GRAPHICS_MODE: - break; - case STRING_MODE: - pdf_doc_add_page_content(text_state.is_mb ? ">]TJ" : ")]TJ", 4); /* op: TJ */ - /* continue */ - case TEXT_MODE: - pdf_doc_add_page_content(" ET", 3); /* op: ET */ - text_state.force_reset = 0; - text_state.font_id = -1; - break; - } - motion_state = GRAPHICS_MODE; -} - -static void -start_string (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - spt_t delx, dely, error_delx, error_dely; - spt_t desired_delx, desired_dely; - int len = 0; - - delx = xpos - text_state.ref_x; - dely = ypos - text_state.ref_y; - /* - * Precompensating for line transformation matrix. - * - * Line transformation matrix L for horizontal font in horizontal - * mode and it's inverse I is - * - * | e 0| | 1/e 0| - * L_hh = | | , I_hh = | | - * | s 1| |-s/e 1| - * - * For vertical font in vertical mode, - * - * | 1 -s| | 1 s/e| - * L_vv = | | , I_vv = | | - * | 0 e| | 0 1/e| - * - * For vertical font in horizontal mode, - * - * | s 1| | 0 1| - * L_vh = | | = L_vv x | | - * |-e 0| |-1 0| - * - * | 0 -1| - * I_vh = | | x I_vv - * | 1 0| - * - * For horizontal font in vertical mode, - * - * | 0 -e| | 0 -1| - * L_hv = | | = L_hh x | | - * | 1 -s| | 1 0| - * - * | 0 1| - * I_hv = | | x I_hh - * |-1 0| - * - */ - switch (rotate) { - case TEXT_WMODE_VH: - /* Vertical font in horizontal mode: rot = +90 - * | 0 -1/e| - * d_user = d x I_vh = d x | | - * | 1 s/e| - */ - desired_delx = dely; - desired_dely = (spt_t) (-(delx - dely*slant)/extend); - - /* error_del is in device space - * - * | 0 1| - * e = e_user x | | = (-e_user_y, e_user_x) - * |-1 0| - * - * We must care about rotation here but not extend/slant... - * The extend and slant actually is font matrix. - */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); - error_delx = -error_delx; - break; - case TEXT_WMODE_HV: - /* Horizontal font in vertical mode: rot = -90 - * - * |-s/e 1| - * d_user = d x I_hv = d x | | - * |-1/e 0| - */ - desired_delx = (spt_t)(-(dely + delx*slant)/extend); - desired_dely = delx; - - /* - * e = (e_user_y, -e_user_x) - */ - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_dely); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_delx); - error_dely = -error_dely; - break; - case TEXT_WMODE_HH: - /* Horizontal font in horizontal mode: - * | 1/e 0| - * d_user = d x I_hh = d x | | - * |-s/e 1| - */ - desired_delx = (spt_t)((delx - dely*slant)/extend); - desired_dely = dely; - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); - break; - case TEXT_WMODE_VV: - /* Vertical font in vertical mode: - * | 1 s/e| - * d_user = d x I_vv = d x | | - * | 0 1/e| - */ - desired_delx = delx; - desired_dely = (spt_t)((dely + delx*slant)/extend); - - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_delx, &error_delx); - format_buffer[len++] = ' '; - len += dev_sprint_bp(format_buffer+len, desired_dely, &error_dely); - break; - } - pdf_doc_add_page_content(format_buffer, len); /* op: */ - /* - * dvipdfm wrongly using "TD" in place of "Td". - * The TD operator set leading, but we are not using T* etc. - */ - pdf_doc_add_page_content(text_state.is_mb ? " Td[<" : " Td[(", 5); /* op: Td */ - - /* Error correction */ - text_state.ref_x = xpos - error_delx; - text_state.ref_y = ypos - error_dely; - - text_state.offset = 0; -} - -static void -string_mode (spt_t xpos, spt_t ypos, double slant, double extend, int rotate) -{ - switch (motion_state) { - case STRING_MODE: - break; - case GRAPHICS_MODE: - reset_text_state(); - /* continue */ - case TEXT_MODE: - if (text_state.force_reset) { - dev_set_text_matrix(xpos, ypos, slant, extend, rotate); - pdf_doc_add_page_content(text_state.is_mb ? "[<" : "[(", 2); /* op: */ - text_state.force_reset = 0; - } else { - start_string(xpos, ypos, slant, extend, rotate); - } - break; - } - motion_state = STRING_MODE; -} - -/* - * The purpose of the following routine is to force a Tf only - * when it's actually necessary. This became a problem when the - * VF code was added. The VF spec says to instantiate the - * first font contained in the VF file before drawing a virtual - * character. However, that font may not be used for - * many characters (e.g. small caps fonts). For this reason, - * dev_select_font() should not force a "physical" font selection. - * This routine prevents a PDF Tf font selection until there's - * really a character in that font. - */ - -static int -dev_set_font (int font_id) -{ - struct dev_font *font; - struct dev_font *real_font; - int text_rotate; - double font_scale; - int len; - int vert_dir, vert_font; - - /* text_mode() must come before text_state.is_mb is changed. */ - text_mode(); - - font = GET_FONT(font_id); - ASSERT(font); /* Caller should check font_id. */ - - if (font->real_font_index >= 0) - real_font = GET_FONT(font->real_font_index); - else - real_font = font; - - text_state.is_mb = (font->format == PDF_FONTTYPE_COMPOSITE) ? 1 : 0; - - vert_font = font->wmode ? 1 : 0; - if (dev_param.autorotate) { - vert_dir = text_state.dir_mode ? 1 : 0; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 1)|vert_dir; - - if (font->slant != text_state.matrix.slant || - font->extend != text_state.matrix.extend || - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - text_state.matrix.slant = font->slant; - text_state.matrix.extend = font->extend; - text_state.matrix.rotate = text_rotate; - - if (!real_font->resource) { - real_font->resource = pdf_get_font_reference(real_font->font_id); - real_font->used_chars = pdf_get_font_usedchars(real_font->font_id); - } - - if (!real_font->used_on_this_page) { - pdf_doc_add_page_resource("Font", - real_font->short_name, - pdf_link_obj(real_font->resource)); - real_font->used_on_this_page = 1; - } - - font_scale = (double) font->sptsize * dev_unit.dvi2pts; - len = sprintf(format_buffer, " /%s", real_font->short_name); /* space not necessary. */ - format_buffer[len++] = ' '; - len += p_dtoa(font_scale, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), format_buffer+len); - format_buffer[len++] = ' '; - format_buffer[len++] = 'T'; - format_buffer[len++] = 'f'; - pdf_doc_add_page_content(format_buffer, len); /* op: Tf */ - - if (font->bold > 0.0 || font->bold != text_state.bold_param) { - if (font->bold <= 0.0) - len = sprintf(format_buffer, " 0 Tr"); - else - len = sprintf(format_buffer, " 2 Tr %.6f w", font->bold); /* _FIXME_ */ - pdf_doc_add_page_content(format_buffer, len); /* op: Tr w */ - } - text_state.bold_param = font->bold; - - text_state.font_id = font_id; - - return 0; -} - - -/* Access text state parameters. - */ -#if 0 -int -pdf_dev_currentfont (void) -{ - return text_state.font_id; -} - -double -pdf_dev_get_font_ptsize (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->sptsize * dev_unit.dvi2pts; - } - - return 1.0; -} -#endif - -int -pdf_dev_get_font_wmode (int font_id) -{ - struct dev_font *font; - - font = GET_FONT(font_id); - if (font) { - return font->wmode; - } - - return 0; -} - -static unsigned char sbuf0[FORMAT_BUF_SIZE]; -static unsigned char sbuf1[FORMAT_BUF_SIZE]; - -static int -handle_multibyte_string (struct dev_font *font, - const unsigned char **str_ptr, int *str_len, int ctype) -{ - const unsigned char *p; - int i, length; - - p = *str_ptr; - length = *str_len; - -#ifdef XETEX - if (ctype == -1) { /* freetype glyph indexes */ - if (font->ft_to_gid) { - /* convert freetype glyph indexes to physical GID */ - const unsigned char *inbuf = p; - unsigned char *outbuf = sbuf0; - for (i = 0; i < length; i += 2) { - unsigned int gid; - gid = *inbuf++ << 8; - gid += *inbuf++; - gid = font->ft_to_gid[gid]; - *outbuf++ = gid >> 8; - *outbuf++ = gid & 0xff; - } - p = sbuf0; - length = outbuf - sbuf0; - } - } - else -#endif - /* _FIXME_ */ - if (font->is_unicode) { /* UCS-4 */ - if (ctype == 1) { - if (length * 4 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i++) { - sbuf1[i*4 ] = font->ucs_group; - sbuf1[i*4+1] = font->ucs_plane; - sbuf1[i*4+2] = '\0'; - sbuf1[i*4+3] = p[i]; - } - length *= 4; - } else if (ctype == 2) { - int len = 0; - - if (length * 2 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i += 2, len += 4) { - sbuf1[len ] = font->ucs_group; - if ((p[i] & 0xf8) == 0xd8) { - int c; - /* Check for valid surrogate pair. */ - if ((p[i] & 0xfc) != 0xd8 || i + 2 >= length || (p[i+2] & 0xfc) != 0xdc) { - WARN("Invalid surrogate p[%d]=%02X...", i, p[i]); - return -1; - } - c = (((p[i] & 0x03) << 10) | (p[i+1] << 2) | (p[i+2] & 0x03)) + 0x100; - sbuf1[len+1] = (c >> 8) & 0xff; - sbuf1[len+2] = c & 0xff; - i += 2; - } else { - sbuf1[len+1] = font->ucs_plane; - sbuf1[len+2] = p[i]; - } - sbuf1[len+3] = p[i+1]; - } - length = len; - } - p = sbuf1; - } else if (ctype == 1 && font->mapc >= 0) { - /* Omega workaround... - * Translate single-byte chars to double byte code space. - */ - if (length * 2 >= FORMAT_BUF_SIZE) { - WARN("Too long string..."); - return -1; - } - for (i = 0; i < length; i++) { - sbuf1[i*2 ] = (font->mapc & 0xff); - sbuf1[i*2+1] = p[i]; - } - length *= 2; - p = sbuf1; - } - - /* - * Font is double-byte font. Output is assumed to be 16-bit fixed length - * encoding. - * TODO: A character decomposed to multiple characters. - */ - if (ctype != -1 && font->enc_id >= 0) { - const unsigned char *inbuf; - unsigned char *outbuf; - long inbytesleft, outbytesleft; - CMap *cmap; - - cmap = CMap_cache_get(font->enc_id); - inbuf = p; - outbuf = sbuf0; - inbytesleft = length; - outbytesleft = FORMAT_BUF_SIZE; - - CMap_decode(cmap, - &inbuf, &inbytesleft, &outbuf, &outbytesleft); - if (inbytesleft != 0) { - WARN("CMap conversion failed. (%d bytes remains)", inbytesleft); - return -1; - } - length = FORMAT_BUF_SIZE - outbytesleft; - p = sbuf0; - } - - *str_ptr = p; - *str_len = length; - return 0; -} - - -static pdf_coord *dev_coords = NULL; -static int num_dev_coords = 0; -static int max_dev_coords = 0; - -void pdf_dev_get_coord(double *xpos, double *ypos) -{ - if (num_dev_coords > 0) { - *xpos = dev_coords[num_dev_coords-1].x; - *ypos = dev_coords[num_dev_coords-1].y; - } else { - *xpos = *ypos = 0.0; - } -} - -void pdf_dev_push_coord(double xpos, double ypos) -{ - if (num_dev_coords >= max_dev_coords) { - max_dev_coords += 4; - dev_coords = RENEW(dev_coords, max_dev_coords, pdf_coord); - } - dev_coords[num_dev_coords].x = xpos; - dev_coords[num_dev_coords].y = ypos; - num_dev_coords++; -} - -void pdf_dev_pop_coord(void) -{ - if (num_dev_coords > 0) num_dev_coords--; -} - -/* - * ctype: -#ifdef XETEX - * -1 input string contains 2-byte Freetype glyph index values -#endif - * 0 byte-width of char can be variable and input string - * is properly encoded. - * n Single character cosumes n bytes in input string. - * - * _FIXME_ - * --> - * selectfont(font_name, point_size) and show_string(pos, string) - */ -void -pdf_dev_set_string (spt_t xpos, spt_t ypos, - const void *instr_ptr, int instr_len, - spt_t width, - int font_id, int ctype) -{ - struct dev_font *font; - struct dev_font *real_font; - const unsigned char *str_ptr; /* Pointer to the reencoded string. */ - int length, i, len = 0; - spt_t kern, delh, delv; - spt_t text_xorigin; - spt_t text_yorigin; - - if (font_id < 0 || font_id >= num_dev_fonts) { - ERROR("Invalid font: %d (%d)", font_id, num_dev_fonts); - return; - } - if (font_id != text_state.font_id) { - dev_set_font(font_id); - } - - font = CURRENTFONT(); - if (!font) { - ERROR("Currentfont not set."); - return; - } - - if (font->real_font_index >= 0) - real_font = GET_FONT(font->real_font_index); - else - real_font = font; - - text_xorigin = text_state.ref_x; - text_yorigin = text_state.ref_y; - - str_ptr = instr_ptr; - length = instr_len; - - if (font->format == PDF_FONTTYPE_COMPOSITE) { - if (handle_multibyte_string(font, &str_ptr, &length, ctype) < 0) { - ERROR("Error in converting input string..."); - return; - } - if (real_font->used_chars != NULL) { - for (i = 0; i < length; i += 2) - add_to_used_chars2(real_font->used_chars, - (unsigned short) (str_ptr[i] << 8)|str_ptr[i+1]); - } - } else { - if (real_font->used_chars != NULL) { - for (i = 0; i < length; i++) - real_font->used_chars[str_ptr[i]] = 1; - } - } - - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); - } - - /* - * Kern is in units of character units, i.e., 1000 = 1 em. - * - * Positive kern means kerning (reduce excess white space). - * - * The following formula is of the form a*x/b where a, x, and b are signed long - * integers. Since in integer arithmetic (a*x) could overflow and a*(x/b) would - * not be accurate, we use floating point arithmetic rather than trying to do - * this all with integer arithmetic. - * - * 1000.0 / (font->extend * font->sptsize) is caluculated each times... - * Is accuracy really a matter? Character widths are always rounded to integer - * (in 1000 units per em) but dvipdfmx does not take into account of this... - */ - - if (text_state.dir_mode) { - /* Top-to-bottom */ - delh = ypos - text_yorigin + text_state.offset; - delv = xpos - text_xorigin; - } else { - /* Left-to-right */ - delh = text_xorigin + text_state.offset - xpos; - delv = ypos - text_yorigin; - } - - /* White-space more than 3em is not considered as a part of single text. - * So we will break string mode in that case. - * Dvipdfmx spend most of time processing strings with kern = 0 (but far - * more times in font handling). - * You may want to use pre-calculated value for WORD_SPACE_MAX. - * More text compression may be possible by replacing kern with space char - * when -kern is equal to space char width. - */ -#define WORD_SPACE_MAX(f) (spt_t) (3.0 * (f)->extend * (f)->sptsize) - - if (text_state.force_reset || - labs(delv) > dev_unit.min_bp_val || - labs(delh) > WORD_SPACE_MAX(font)) { - text_mode(); - kern = 0; - } else { - kern = (spt_t) (1000.0 / font->extend * delh / font->sptsize); - } - - /* Inaccucary introduced by rounding of character width appears within - * single text block. There are point_size/1000 rounding error per character. - * If you really care about accuracy, you should compensate this here too. - */ - if (motion_state != STRING_MODE) - string_mode(xpos, ypos, - font->slant, font->extend, text_state.matrix.rotate); - else if (kern != 0) { - /* - * Same issues as earlier. Use floating point for simplicity. - * This routine needs to be fast, so we don't call sprintf() or strcpy(). - */ - text_state.offset -= - (spt_t) (kern * font->extend * (font->sptsize / 1000.0)); - format_buffer[len++] = text_state.is_mb ? '>' : ')'; - if (font->wmode) - len += p_itoa(-kern, format_buffer + len); - else { - len += p_itoa( kern, format_buffer + len); - } - format_buffer[len++] = text_state.is_mb ? '<' : '('; - pdf_doc_add_page_content(format_buffer, len); /* op: */ - len = 0; - } - - if (text_state.is_mb) { - if (FORMAT_BUF_SIZE - len < 2 * length) - ERROR("Buffer overflow..."); - for (i = 0; i < length; i++) { - int first, second; - - first = (str_ptr[i] >> 4) & 0x0f; - second = str_ptr[i] & 0x0f; - format_buffer[len++] = ((first >= 10) ? first + 'W' : first + '0'); - format_buffer[len++] = ((second >= 10) ? second + 'W' : second + '0'); - } - } else { - len += pdfobj_escape_str(format_buffer + len, - FORMAT_BUF_SIZE - len, str_ptr, length); - } - /* I think if you really care about speed, you should avoid memcopy here. */ - pdf_doc_add_page_content(format_buffer, len); /* op: */ - - text_state.offset += width; -} - -void -pdf_init_device (double dvi2pts, int precision, int black_and_white) -{ - if (precision < 0 || - precision > DEV_PRECISION_MAX) - WARN("Number of decimal digits out of range [0-%d].", - DEV_PRECISION_MAX); - - if (precision < 0) { - dev_unit.precision = 0; - } else if (precision > DEV_PRECISION_MAX) { - dev_unit.precision = DEV_PRECISION_MAX; - } else { - dev_unit.precision = precision; - } - dev_unit.dvi2pts = dvi2pts; - dev_unit.min_bp_val = (long) ROUND(1.0/(ten_pow[dev_unit.precision]*dvi2pts), 1); - if (dev_unit.min_bp_val < 0) - dev_unit.min_bp_val = -dev_unit.min_bp_val; - - dev_param.colormode = (black_and_white ? 0 : 1); - - graphics_mode(); - pdf_color_clear_stack(); - pdf_dev_init_gstates(); - - num_dev_fonts = max_dev_fonts = 0; - dev_fonts = NULL; - num_dev_coords = max_dev_coords = 0; - dev_coords = NULL; -} - -void -pdf_close_device (void) -{ - if (dev_fonts) { - int i; - - for (i = 0; i < num_dev_fonts; i++) { - if (dev_fonts[i].tex_name) - RELEASE(dev_fonts[i].tex_name); - if (dev_fonts[i].resource) - pdf_release_obj(dev_fonts[i].resource); - dev_fonts[i].tex_name = NULL; - dev_fonts[i].resource = NULL; - } - RELEASE(dev_fonts); - } - if (dev_coords) RELEASE(dev_coords); - pdf_dev_clear_gstates(); -} - -/* - * BOP, EOP, and FONT section. - * BOP and EOP manipulate some of the same data structures - * as the font stuff. - */ -void -pdf_dev_reset_fonts (void) -{ - int i; - - for (i = 0; i < num_dev_fonts; i++) { - dev_fonts[i].used_on_this_page = 0; - } - - text_state.font_id = -1; - - text_state.matrix.slant = 0.0; - text_state.matrix.extend = 1.0; - text_state.matrix.rotate = TEXT_WMODE_HH; - - text_state.bold_param = 0.0; - - text_state.is_mb = 0; -} - -#ifdef XETEX -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; -} -#endif - -#if 0 -/* Not working */ -void -pdf_dev_set_origin (double phys_x, double phys_y) -{ - pdf_tmatrix M0, M1; - - pdf_dev_currentmatrix(&M0); - pdf_dev_currentmatrix(&M1); - pdf_invertmatrix(&M1); - M0.e = phys_x; M0.f = phys_y; - pdf_concatmatrix(&M1, &M0); - - pdf_dev_concat(&M1); -} -#endif - -void -pdf_dev_bop (const pdf_tmatrix *M) -{ - graphics_mode(); - - text_state.force_reset = 0; - - pdf_dev_gsave(); - pdf_dev_concat(M); - - pdf_dev_reset_fonts(); - pdf_dev_reset_color(); -} - -void -pdf_dev_eop (void) -{ - int depth; - - graphics_mode(); - - depth = pdf_dev_current_depth(); - if (depth != 1) { - WARN("Unbalenced q/Q nesting...: %d", depth); - pdf_dev_grestore_to(0); - } else { - pdf_dev_grestore(); - } -} - -static void -print_fontmap (const char *font_name, fontmap_rec *mrec) -{ - if (!mrec) - return; - - MESG("\n"); - - MESG("fontmap: %s -> %s", font_name, mrec->font_name); - if (mrec->enc_name) - MESG("(%s)", mrec->enc_name); - if (mrec->opt.extend != 1.0) - MESG("[extend:%g]", mrec->opt.extend); - if (mrec->opt.slant != 0.0) - MESG("[slant:%g]", mrec->opt.slant); - if (mrec->opt.bold != 0.0) - MESG("[bold:%g]", mrec->opt.bold); - if (mrec->opt.flags & FONTMAP_OPT_NOEMBED) - MESG("[noemb]"); - if (mrec->opt.mapc >= 0) - MESG("[map:<%02x>]", mrec->opt.mapc); - if (mrec->opt.charcoll) - MESG("[csi:%s]", mrec->opt.charcoll); - if (mrec->opt.index) - MESG("[index:%d]", mrec->opt.index); - - switch (mrec->opt.style) { - case FONTMAP_STYLE_BOLD: - MESG("[style:bold]"); - break; - case FONTMAP_STYLE_ITALIC: - MESG("[style:italic]"); - break; - case FONTMAP_STYLE_BOLDITALIC: - MESG("[style:bolditalic]"); - break; - } - MESG("\n"); - -} - -/* _FIXME_ - * Font is identified with font_name and point_size as in DVI here. - * However, except for PDF_FONTTYPE_BITMAP, we can share the - * short_name, resource and used_chars between multiple instances - * of the same font at different sizes. - */ -int -pdf_dev_locate_font (const char *font_name, spt_t ptsize) -{ - int i; - fontmap_rec *mrec; - struct dev_font *font; - - if (!font_name) - return -1; - - if (ptsize == 0) { - ERROR("pdf_dev_locate_font() called with the zero ptsize."); - return -1; - } - - for (i = 0; i < num_dev_fonts; i++) { - if (strcmp(font_name, dev_fonts[i].tex_name) == 0) { - if (ptsize == dev_fonts[i].sptsize) - return i; /* found a dev_font that matches the request */ - if (dev_fonts[i].format != PDF_FONTTYPE_BITMAP) - break; /* new dev_font will share pdf resource with /i/ */ - } - } - - /* - * Make sure we have room for a new one, even though we may not - * actually create one. - */ - if (num_dev_fonts >= max_dev_fonts) { - max_dev_fonts += 16; - dev_fonts = RENEW(dev_fonts, max_dev_fonts, struct dev_font); - } - - font = &dev_fonts[num_dev_fonts]; - - /* New font */ - mrec = pdf_lookup_fontmap_record(font_name); - - if (verbose > 1) - print_fontmap(font_name, mrec); - - font->font_id = pdf_font_findresource(font_name, ptsize * dev_unit.dvi2pts, mrec); - if (font->font_id < 0) - return -1; - - /* We found device font here. */ - if (i < num_dev_fonts) { - font->real_font_index = i; - strcpy(font->short_name, dev_fonts[i].short_name); - } - else { - font->real_font_index = -1; - font->short_name[0] = 'F'; - p_itoa(num_phys_fonts + 1, &font->short_name[1]); /* NULL terminated here */ - num_phys_fonts++; - } - - font->used_on_this_page = 0; - - font->tex_name = NEW(strlen(font_name) + 1, char); - strcpy(font->tex_name, font_name); - font->sptsize = ptsize; - - switch (pdf_get_font_subtype(font->font_id)) { - case PDF_FONT_FONTTYPE_TYPE3: - font->format = PDF_FONTTYPE_BITMAP; - break; - case PDF_FONT_FONTTYPE_TYPE0: - font->format = PDF_FONTTYPE_COMPOSITE; - break; - default: - font->format = PDF_FONTTYPE_SIMPLE; - break; - } - - font->wmode = pdf_get_font_wmode (font->font_id); - font->enc_id = pdf_get_font_encoding(font->font_id); -#ifdef XETEX - font->ft_to_gid = pdf_get_font_ft_to_gid(font->font_id); -#endif - - font->resource = NULL; /* Don't ref obj until font is actually used. */ - font->used_chars = NULL; - - font->extend = 1.0; - font->slant = 0.0; - font->bold = 0.0; - font->mapc = -1; - font->is_unicode = 0; - font->ucs_group = 0; - font->ucs_plane = 0; - - if (mrec) { - font->extend = mrec->opt.extend; - font->slant = mrec->opt.slant; - font->bold = mrec->opt.bold; - if (mrec->opt.mapc >= 0) - font->mapc = (mrec->opt.mapc >> 8) & 0xff; - else { - font->mapc = -1; - } - if (mrec->enc_name && - !strcmp(mrec->enc_name, "unicode")) { - font->is_unicode = 1; - if (mrec->opt.mapc >= 0) { - font->ucs_group = (mrec->opt.mapc >> 24) & 0xff; - font->ucs_plane = (mrec->opt.mapc >> 16) & 0xff; - } else { - font->ucs_group = 0; - font->ucs_plane = 0; - } - } else { - font->is_unicode = 0; - } - } - - return num_dev_fonts++; -} - - -/* This does not remember current stroking width. */ -static int -dev_sprint_line (char *buf, spt_t width, - spt_t p0_x, spt_t p0_y, spt_t p1_x, spt_t p1_y) -{ - int len = 0; - double w; - - w = width * dev_unit.dvi2pts; - - len += p_dtoa(w, MIN(dev_unit.precision+1, DEV_PRECISION_MAX), buf+len); - buf[len++] = ' '; - buf[len++] = 'w'; - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p0_x, NULL); - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p0_y, NULL); - buf[len++] = ' '; - buf[len++] = 'm'; - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_x, NULL); - buf[len++] = ' '; - len += dev_sprint_bp(buf+len, p1_y, NULL); - buf[len++] = ' '; - buf[len++] = 'l'; - buf[len++] = ' '; - buf[len++] = 'S'; - - return len; -} - -/* Not optimized. */ -#define PDF_LINE_THICKNESS_MAX 5.0 -void -pdf_dev_set_rule (spt_t xpos, spt_t ypos, spt_t width, spt_t height) -{ - int len = 0; - double width_in_bp; - - if (num_dev_coords > 0) { - xpos -= bpt2spt(dev_coords[num_dev_coords-1].x); - ypos -= bpt2spt(dev_coords[num_dev_coords-1].y); - } - - graphics_mode(); - - format_buffer[len++] = ' '; - format_buffer[len++] = 'q'; - format_buffer[len++] = ' '; - /* Don't use too thick line. */ - width_in_bp = ((width < height) ? width : height) * dev_unit.dvi2pts; - if (width_in_bp < 0.0 || /* Shouldn't happen */ - width_in_bp > PDF_LINE_THICKNESS_MAX) { - pdf_rect rect; - - rect.llx = dev_unit.dvi2pts * xpos; - rect.lly = dev_unit.dvi2pts * ypos; - rect.urx = dev_unit.dvi2pts * width; - rect.ury = dev_unit.dvi2pts * height; - len += pdf_sprint_rect(format_buffer+len, &rect); - format_buffer[len++] = ' '; - format_buffer[len++] = 'r'; - format_buffer[len++] = 'e'; - format_buffer[len++] = ' '; - format_buffer[len++] = 'f'; - } else { - if (width > height) { - /* NOTE: - * A line width of 0 denotes the thinnest line that can be rendered at - * device resolution. See, PDF Reference Manual 4th ed., sec. 4.3.2, - * "Details of Graphics State Parameters", p. 185. - */ - if (height < dev_unit.min_bp_val) { - WARN("Too thin line: height=%ld (%g bp)", height, width_in_bp); - WARN("Please consider using \"-d\" option."); - } - len += dev_sprint_line(format_buffer+len, - height, - xpos, - ypos + height/2, - xpos + width, - ypos + height/2); - } else { - if (width < dev_unit.min_bp_val) { - WARN("Too thin line: width=%ld (%g bp)", width, width_in_bp); - WARN("Please consider using \"-d\" option."); - } - len += dev_sprint_line(format_buffer+len, - width, - xpos + width/2, - ypos, - xpos + width/2, - ypos + height); - } - } - format_buffer[len++] = ' '; - format_buffer[len++] = 'Q'; - pdf_doc_add_page_content(format_buffer, len); /* op: q re f Q */ -} - -/* Rectangle in device space coordinate. */ -void -pdf_dev_set_rect (pdf_rect *rect, - spt_t x_user, spt_t y_user, - spt_t width, spt_t height, spt_t depth) -{ - double dev_x, dev_y; - pdf_coord p0, p1, p2, p3; - double min_x, min_y, max_x, max_y; - - dev_x = x_user * dev_unit.dvi2pts; - dev_y = y_user * dev_unit.dvi2pts; - if (text_state.dir_mode) { - p0.x = dev_x - dev_unit.dvi2pts * depth; - p0.y = dev_y - dev_unit.dvi2pts * width; - p1.x = dev_x + dev_unit.dvi2pts * height; - p1.y = p0.y; - p2.x = p1.x; - p2.y = dev_y; - p3.x = p0.x; - p3.y = p2.y; - } else { - p0.x = dev_x; - p0.y = dev_y - dev_unit.dvi2pts * depth; - p1.x = dev_x + dev_unit.dvi2pts * width; - p1.y = p0.y; - p2.x = p1.x; - p2.y = dev_y + dev_unit.dvi2pts * height; - p3.x = p0.x; - p3.y = p2.y; - } - - pdf_dev_transform(&p0, NULL); /* currentmatrix */ - pdf_dev_transform(&p1, NULL); - pdf_dev_transform(&p2, NULL); - pdf_dev_transform(&p3, NULL); - - min_x = MIN(p0.x , p1.x); - min_x = MIN(min_x, p2.x); - min_x = MIN(min_x, p3.x); - - max_x = MAX(p0.x , p1.x); - max_x = MAX(max_x, p2.x); - max_x = MAX(max_x, p3.x); - - min_y = MIN(p0.y , p1.y); - min_y = MIN(min_y, p2.y); - min_y = MIN(min_y, p3.y); - - max_y = MAX(p0.y , p1.y); - max_y = MAX(max_y, p2.y); - max_y = MAX(max_y, p3.y); - - rect->llx = min_x; - rect->lly = min_y; - rect->urx = max_x; - rect->ury = max_y; - - return; -} - -int -pdf_dev_get_dirmode (void) -{ - return text_state.dir_mode; -} - -void -pdf_dev_set_dirmode (int text_dir) -{ - struct dev_font *font; - int text_rotate; - int vert_dir, vert_font; - - font = CURRENTFONT(); - - vert_font = (font && font->wmode) ? 1 : 0; - if (dev_param.autorotate) { - vert_dir = text_dir ? 1 : 0; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 1)|vert_dir; - - if (font && - ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - - text_state.matrix.rotate = text_rotate; - text_state.dir_mode = text_dir; -} - -static void -dev_set_param_autorotate (int auto_rotate) -{ - struct dev_font *font; - int text_rotate, vert_font, vert_dir; - - font = CURRENTFONT(); - - vert_font = (font && font->wmode) ? 1 : 0; - if (auto_rotate) { - vert_dir = text_state.dir_mode ? 1 : 0; - } else { - vert_dir = vert_font; - } - text_rotate = (vert_font << 1)|vert_dir; - - if (ANGLE_CHANGES(text_rotate, text_state.matrix.rotate)) { - text_state.force_reset = 1; - } - text_state.matrix.rotate = text_rotate; - dev_param.autorotate = auto_rotate; -} - -int -pdf_dev_get_param (int param_type) -{ - int value = 0; - - switch (param_type) { - case PDF_DEV_PARAM_AUTOROTATE: - value = dev_param.autorotate; - break; - case PDF_DEV_PARAM_COLORMODE: - value = dev_param.colormode; - break; - default: - ERROR("Unknown device parameter: %d", param_type); - } - - return value; -} - -void -pdf_dev_set_param (int param_type, int value) -{ - switch (param_type) { - case PDF_DEV_PARAM_AUTOROTATE: - dev_set_param_autorotate(value); - break; - case PDF_DEV_PARAM_COLORMODE: - dev_param.colormode = value; /* 0 for B&W */ - break; - default: - ERROR("Unknown device parameter: %d", param_type); - } - - return; -} - - -int -pdf_dev_put_image (int id, - transform_info *p, - double ref_x, - double ref_y) -{ - char *res_name; - pdf_tmatrix M; - pdf_rect r; - int len = 0; - - if (num_dev_coords > 0) { - ref_x -= dev_coords[num_dev_coords-1].x; - ref_y -= dev_coords[num_dev_coords-1].y; - } - - pdf_copymatrix(&M, &(p->matrix)); - M.e += ref_x; M.f += ref_y; - /* Just rotate by -90, but not tested yet. Any problem if M has scaling? */ - if (dev_param.autorotate && - text_state.dir_mode) { - double tmp; - tmp = -M.a; M.a = M.b; M.b = tmp; - tmp = -M.c; M.c = M.d; M.d = tmp; - } - - graphics_mode(); - pdf_dev_gsave(); - - pdf_dev_concat(&M); - - pdf_ximage_scale_image(id, &M, &r, p); - pdf_dev_concat(&M); - - /* Clip */ - if (p->flags & INFO_DO_CLIP) { -#if 0 - pdf_dev_newpath(); - pdf_dev_moveto(r.llx, r.lly); - pdf_dev_lineto(r.urx, r.lly); - pdf_dev_lineto(r.urx, r.ury); - pdf_dev_lineto(r.llx, r.ury); - pdf_dev_closepath(); - pdf_dev_clip(); - pdf_dev_newpath(); -#else - pdf_dev_rectclip(r.llx, r.lly, r.urx - r.llx, r.ury - r.lly); -#endif - } - - res_name = pdf_ximage_get_resname(id); - len = sprintf(work_buffer, " /%s Do", res_name); - pdf_doc_add_page_content(work_buffer, len); /* op: Do */ - - pdf_dev_grestore(); - - pdf_doc_add_page_resource("XObject", - 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; -} - - -void -transform_info_clear (transform_info *info) -{ - /* Physical dimensions */ - info->width = 0.0; - info->height = 0.0; - info->depth = 0.0; - - info->bbox.llx = 0.0; - info->bbox.lly = 0.0; - info->bbox.urx = 0.0; - info->bbox.ury = 0.0; - - /* Transformation matrix */ - pdf_setmatrix(&(info->matrix), 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); - - info->flags = 0; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfdoc.c b/Build/source/texk/dvipdfm-x/xsrc/pdfdoc.c deleted file mode 100644 index 73ee86c8c38..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfdoc.c +++ /dev/null @@ -1,2719 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -/* - * TODO: Many things... - * {begin,end}_{bead,article}, box stack, name tree (not limited to dests)... - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" - -#include "numbers.h" - -#include "pdfobj.h" -#include "pdfparse.h" -#include "pdfnames.h" - -#include "pdfencrypt.h" - -#include "pdfdev.h" -#include "pdfdraw.h" -#include "pdfcolor.h" - -#include "pdfresource.h" -#include "pdffont.h" -#include "pdfximage.h" - -#include "pdflimits.h" - -#if HAVE_LIBPNG -#include "pngimage.h" -#endif -#include "jpegimage.h" - -#include "pdfdoc.h" - -#define PDFDOC_PAGES_ALLOC_SIZE 128u -#define PDFDOC_ARTICLE_ALLOC_SIZE 16 -#define PDFDOC_BEAD_ALLOC_SIZE 16 - -static int verbose = 0; - -static char manual_thumb_enabled = 0; -static char *thumb_basename = NULL; - -void -pdf_doc_enable_manual_thumbnails (void) -{ -#if HAVE_LIBPNG - manual_thumb_enabled = 1; -#else - WARN("Manual thumbnail is not supported without the libpng library."); -#endif -} - -static pdf_obj * -read_thumbnail (const char *thumb_filename) -{ - pdf_obj *image_ref; - int xobj_id; - FILE *fp; - - fp = MFOPEN(thumb_filename, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Could not open thumbnail file \"%s\"", thumb_filename); - return NULL; - } - if (!check_for_png(fp) && !check_for_jpeg(fp)) { - WARN("Thumbnail \"%s\" not a png/jpeg file!", thumb_filename); - MFCLOSE(fp); - return NULL; - } - MFCLOSE(fp); - - xobj_id = pdf_ximage_findresource(thumb_filename, 0, NULL); - if (xobj_id < 0) { - WARN("Could not read thumbnail file \"%s\".", thumb_filename); - image_ref = NULL; - } else { - image_ref = pdf_ximage_get_reference(xobj_id); - } - - return image_ref; -} - -void -pdf_doc_set_verbose (void) -{ - verbose++; - pdf_font_set_verbose(); - pdf_color_set_verbose(); - pdf_ximage_set_verbose(); -} - -typedef struct pdf_form -{ - char *ident; - - pdf_tmatrix matrix; - pdf_rect cropbox; - - pdf_obj *resources; - pdf_obj *contents; -} pdf_form; - -struct form_list_node -{ - int q_depth; - pdf_form form; - - struct form_list_node *prev; -}; - -#define USE_MY_MEDIABOX (1 << 0) -typedef struct pdf_page -{ - pdf_obj *page_obj; - pdf_obj *page_ref; - - int flags; - - double ref_x, ref_y; - pdf_rect cropbox; - - pdf_obj *resources; - - /* Contents */ - pdf_obj *background; - pdf_obj *contents; - - /* global bop, background, contents, global eop */ - pdf_obj *content_refs[4]; - - pdf_obj *annots; - pdf_obj *beads; -} pdf_page; - -typedef struct pdf_olitem -{ - pdf_obj *dict; - - int is_open; - - struct pdf_olitem *first; - struct pdf_olitem *parent; - - struct pdf_olitem *next; -} pdf_olitem; - -typedef struct pdf_bead -{ - char *id; - long page_no; - pdf_rect rect; -} pdf_bead; - -typedef struct pdf_article -{ - char *id; - pdf_obj *info; - long num_beads; - long max_beads; - pdf_bead *beads; -} pdf_article; - -struct name_dict -{ - const char *category; - struct ht_table *data; -}; - - -typedef struct pdf_doc -{ - struct { - pdf_obj *dict; - - pdf_obj *viewerpref; - pdf_obj *pagelabels; - pdf_obj *pages; - pdf_obj *names; - pdf_obj *threads; - } root; - - pdf_obj *info; - - struct { - pdf_rect mediabox; - pdf_obj *bop, *eop; - - long num_entries; /* This is not actually total number of pages. */ - long max_entries; - pdf_page *entries; - } pages; - - struct { - pdf_olitem *first; - pdf_olitem *current; - int current_depth; - } outlines; - - struct { - long num_entries; - long max_entries; - pdf_article *entries; - } articles; - - struct name_dict *names; - - int check_gotos; - struct ht_table gotos; - - struct { - int outline_open_depth; - double annot_grow; - } opt; - - struct form_list_node *pending_forms; - -} pdf_doc; -static pdf_doc pdoc; - -static void -pdf_doc_init_catalog (pdf_doc *p) -{ - p->root.viewerpref = NULL; - p->root.pagelabels = NULL; - p->root.pages = NULL; - p->root.names = NULL; - p->root.threads = NULL; - - p->root.dict = pdf_new_dict(); - pdf_set_root(p->root.dict); - - return; -} - -static void -pdf_doc_close_catalog (pdf_doc *p) -{ - pdf_obj *tmp; - - if (p->root.viewerpref) { - tmp = pdf_lookup_dict(p->root.dict, "ViewerPreferences"); - if (!tmp) { - pdf_add_dict(p->root.dict, - pdf_new_name("ViewerPreferences"), - pdf_ref_obj (p->root.viewerpref)); - } else if (PDF_OBJ_DICTTYPE(tmp)) { - pdf_merge_dict(p->root.viewerpref, tmp); - pdf_add_dict(p->root.dict, - pdf_new_name("ViewerPreferences"), - pdf_ref_obj (p->root.viewerpref)); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify ViewerPreferences."); - } - pdf_release_obj(p->root.viewerpref); - p->root.viewerpref = NULL; - } - - if (p->root.pagelabels) { - tmp = pdf_lookup_dict(p->root.dict, "PageLabels"); - if (!tmp) { - tmp = pdf_new_dict(); - pdf_add_dict(tmp, pdf_new_name("Nums"), pdf_link_obj(p->root.pagelabels)); - pdf_add_dict(p->root.dict, - pdf_new_name("PageLabels"), pdf_ref_obj(tmp)); - pdf_release_obj(tmp); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify PageLabels."); - } - pdf_release_obj(p->root.pagelabels); - p->root.pagelabels = NULL; - } - - pdf_add_dict(p->root.dict, - pdf_new_name("Type"), pdf_new_name("Catalog")); - pdf_release_obj(p->root.dict); - p->root.dict = NULL; - - return; -} - -/* - * Pages are starting at 1. - * The page count does not increase until the page is finished. - */ -#define LASTPAGE(p) (&(p->pages.entries[p->pages.num_entries])) -#define FIRSTPAGE(p) (&(p->pages.entries[0])) -#define PAGECOUNT(p) (p->pages.num_entries) -#define MAXPAGES(p) (p->pages.max_entries) - -static void -doc_resize_page_entries (pdf_doc *p, long size) -{ - if (size > MAXPAGES(p)) { - long i; - - p->pages.entries = RENEW(p->pages.entries, size, struct pdf_page); - for (i = p->pages.max_entries; i < size; i++) { - p->pages.entries[i].page_obj = NULL; - p->pages.entries[i].page_ref = NULL; - p->pages.entries[i].flags = 0; - p->pages.entries[i].resources = NULL; - p->pages.entries[i].background = NULL; - p->pages.entries[i].contents = NULL; - p->pages.entries[i].content_refs[0] = NULL; /* global bop */ - p->pages.entries[i].content_refs[1] = NULL; /* background */ - p->pages.entries[i].content_refs[2] = NULL; /* page body */ - p->pages.entries[i].content_refs[3] = NULL; /* global eop */ - p->pages.entries[i].annots = NULL; - p->pages.entries[i].beads = NULL; - } - p->pages.max_entries = size; - } - - return; -} - -static pdf_page * -doc_get_page_entry (pdf_doc *p, unsigned long page_no) -{ - pdf_page *page; - - if (page_no > 65535ul) { - ERROR("Page number %ul too large!", page_no); - } else if (page_no == 0) { - ERROR("Invalid Page number %ul.", page_no); - } - - if (page_no > MAXPAGES(p)) { - doc_resize_page_entries(p, page_no + PDFDOC_PAGES_ALLOC_SIZE); - } - - page = &(p->pages.entries[page_no - 1]); - - return page; -} - -static void pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height); -static void pdf_doc_close_page_tree (pdf_doc *p); - -static void pdf_doc_init_names (pdf_doc *p, int check_gotos); -static void pdf_doc_close_names (pdf_doc *p); - -static void pdf_doc_add_goto (pdf_obj *annot_dict); - -static void pdf_doc_init_docinfo (pdf_doc *p); -static void pdf_doc_close_docinfo (pdf_doc *p); - -static void pdf_doc_init_articles (pdf_doc *p); -static void pdf_doc_close_articles (pdf_doc *p); -static void pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth); -static void pdf_doc_close_bookmarks (pdf_doc *p); - -void -pdf_doc_set_bop_content (const char *content, unsigned length) -{ - pdf_doc *p = &pdoc; - - ASSERT(p); - - if (p->pages.bop) { - pdf_release_obj(p->pages.bop); - p->pages.bop = NULL; - } - - if (length > 0) { - p->pages.bop = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(p->pages.bop, content, length); - } else { - p->pages.bop = NULL; - } - - return; -} - -void -pdf_doc_set_eop_content (const char *content, unsigned length) -{ - pdf_doc *p = &pdoc; - - if (p->pages.eop) { - pdf_release_obj(p->pages.eop); - p->pages.eop = NULL; - } - - if (length > 0) { - p->pages.eop = pdf_new_stream(STREAM_COMPRESS); - pdf_add_stream(p->pages.eop, content, length); - } else { - p->pages.eop = NULL; - } - - return; -} - -#ifndef HAVE_TM_GMTOFF -#ifndef HAVE_TIMEZONE - -/* auxiliary function to compute timezone offset on - systems that do not support the tm_gmtoff in struct tm, - or have a timezone variable. Such as i386-solaris. */ - -static long -compute_timezone_offset() -{ - const time_t now = time(NULL); - struct tm tm; - struct tm local; - time_t gmtoff; - - localtime_r(&now, &local); - gmtime_r(&now, &tm); - return (mktime(&local) - mktime(&tm)); -} - -#endif /* HAVE_TIMEZONE */ -#endif /* HAVE_TM_GMTOFF */ - -/* - * Docinfo - */ -static long -asn_date (char *date_string) -{ - long tz_offset; - time_t current_time; - struct tm *bd_time; - - time(¤t_time); - bd_time = localtime(¤t_time); - -#ifdef HAVE_TM_GMTOFF - tz_offset = bd_time->tm_gmtoff; -#else -# ifdef HAVE_TIMEZONE - tz_offset = -timezone; -# else - tz_offset = compute_timezone_offset(); -# endif /* HAVE_TIMEZONE */ -#endif /* HAVE_TM_GMTOFF */ - - sprintf(date_string, "D:%04d%02d%02d%02d%02d%02d%c%02ld'%02ld'", - bd_time->tm_year + 1900, bd_time->tm_mon + 1, bd_time->tm_mday, - bd_time->tm_hour, bd_time->tm_min, bd_time->tm_sec, - (tz_offset > 0) ? '+' : '-', labs(tz_offset) / 3600, - (labs(tz_offset) / 60) % 60); - - return strlen(date_string); -} - -static void -pdf_doc_init_docinfo (pdf_doc *p) -{ - p->info = pdf_new_dict(); - pdf_set_info(p->info); - - return; -} - -static void -pdf_doc_close_docinfo (pdf_doc *p) -{ - pdf_obj *docinfo = p->info; - - /* - * Excerpt from PDF Reference 4th ed., sec. 10.2.1. - * - * Any entry whose value is not known should be omitted from the dictionary, - * rather than included with an empty string as its value. - * - * .... - * - * Note: Although viewer applications can store custom metadata in the document - * information dictionary, it is inappropriate to store private content or - * structural information there; such information should be stored in the - * document catalog instead (see Section 3.6.1, Document Catalog ). - */ - const char *keys[] = { - "Title", "Author", "Subject", "Keywords", "Creator", "Producer", - "CreationDate", "ModDate", /* Date */ - NULL - }; - pdf_obj *value; - char *banner; - int i; - - for (i = 0; keys[i] != NULL; i++) { - value = pdf_lookup_dict(docinfo, keys[i]); - if (value) { - if (!PDF_OBJ_STRINGTYPE(value)) { - WARN("\"%s\" in DocInfo dictionary not string type.", keys[i]); - pdf_remove_dict(docinfo, keys[i]); - WARN("\"%s\" removed from DocInfo.", keys[i]); - } else if (pdf_string_length(value) == 0) { - /* The hyperref package often uses emtpy strings. */ - pdf_remove_dict(docinfo, keys[i]); - } - } - } - - banner = NEW(strlen(PACKAGE)+strlen(VERSION)+4, char); - sprintf(banner, "%s (%s)", PACKAGE, VERSION); - pdf_add_dict(docinfo, - pdf_new_name("Producer"), - pdf_new_string(banner, strlen(banner))); - RELEASE(banner); - - if (!pdf_lookup_dict(docinfo, "CreationDate")) { - char now[32]; - - asn_date(now); - pdf_add_dict(docinfo, - pdf_new_name ("CreationDate"), - pdf_new_string(now, strlen(now))); - } - - pdf_release_obj(docinfo); - p->info = NULL; - - return; -} - -static pdf_obj * -pdf_doc_get_page_resources (pdf_doc *p, const char *category) -{ - pdf_obj *resources; - pdf_page *currentpage; - pdf_obj *res_dict; - - if (!p || !category) { - return NULL; - } - - if (p->pending_forms) { - if (p->pending_forms->form.resources) { - res_dict = p->pending_forms->form.resources; - } else { - res_dict = p->pending_forms->form.resources = pdf_new_dict(); - } - } else { - currentpage = LASTPAGE(p); - if (currentpage->resources) { - res_dict = currentpage->resources; - } else { - res_dict = currentpage->resources = pdf_new_dict(); - } - } - resources = pdf_lookup_dict(res_dict, category); - if (!resources) { - resources = pdf_new_dict(); - pdf_add_dict(res_dict, pdf_new_name(category), resources); - } - - return resources; -} - -void -pdf_doc_add_page_resource (const char *category, - const char *resource_name, pdf_obj *resource_ref) -{ - pdf_doc *p = &pdoc; - pdf_obj *resources; - pdf_obj *duplicate; - - if (!PDF_OBJ_INDIRECTTYPE(resource_ref)) { - WARN("Passed non indirect reference..."); - resource_ref = pdf_ref_obj(resource_ref); /* leak */ - } - resources = pdf_doc_get_page_resources(p, category); - duplicate = pdf_lookup_dict(resources, resource_name); - if (duplicate && pdf_compare_reference(duplicate, resource_ref)) { - WARN("Conflicting page resource found (page: %ld, category: %s, name: %s).", - pdf_doc_current_page_number(), category, resource_name); - WARN("Ignoring..."); - pdf_release_obj(resource_ref); - } else { - pdf_add_dict(resources, pdf_new_name(resource_name), resource_ref); - } - - return; -} - -static void -doc_flush_page (pdf_doc *p, pdf_page *page, pdf_obj *parent_ref) -{ - pdf_obj *contents_array; - int count; - - pdf_add_dict(page->page_obj, - pdf_new_name("Type"), pdf_new_name("Page")); - pdf_add_dict(page->page_obj, - pdf_new_name("Parent"), parent_ref); - - /* - * Clipping area specified by CropBox is affected by MediaBox which - * might be inherit from parent node. If MediaBox of the root node - * does not have enough size to cover all page's imaging area, using - * CropBox here gives incorrect result. - */ - if (page->flags & USE_MY_MEDIABOX) { - pdf_obj *mediabox; - - mediabox = pdf_new_array(); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.llx, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.lly, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.urx, 0.01))); - pdf_add_array(mediabox, - pdf_new_number(ROUND(page->cropbox.ury, 0.01))); - pdf_add_dict(page->page_obj, pdf_new_name("MediaBox"), mediabox); - } - - count = 0; - contents_array = pdf_new_array(); - if (page->content_refs[0]) { /* global bop */ - pdf_add_array(contents_array, page->content_refs[0]); - count++; - } else if (p->pages.bop && - pdf_stream_length(p->pages.bop) > 0) { - pdf_add_array(contents_array, pdf_ref_obj(p->pages.bop)); - count++; - } - if (page->content_refs[1]) { /* background */ - pdf_add_array(contents_array, page->content_refs[1]); - count++; - } - if (page->content_refs[2]) { /* page body */ - pdf_add_array(contents_array, page->content_refs[2]); - count++; - } - if (page->content_refs[3]) { /* global eop */ - pdf_add_array(contents_array, page->content_refs[3]); - count++; - } else if (p->pages.eop && - pdf_stream_length(p->pages.eop) > 0) { - pdf_add_array(contents_array, pdf_ref_obj(p->pages.eop)); - count++; - } - - if (count == 0) { - WARN("Page with empty content found!!!"); - } - page->content_refs[0] = NULL; - page->content_refs[1] = NULL; - page->content_refs[2] = NULL; - page->content_refs[3] = NULL; - - pdf_add_dict(page->page_obj, - pdf_new_name("Contents"), contents_array); - - - if (page->annots) { - pdf_add_dict(page->page_obj, - pdf_new_name("Annots"), pdf_ref_obj(page->annots)); - pdf_release_obj(page->annots); - } - if (page->beads) { - pdf_add_dict(page->page_obj, - pdf_new_name("B"), pdf_ref_obj(page->beads)); - pdf_release_obj(page->beads); - } - pdf_release_obj(page->page_obj); - pdf_release_obj(page->page_ref); - - page->page_obj = NULL; - page->page_ref = NULL; - page->annots = NULL; - page->beads = NULL; - - return; -} - -/* B-tree? */ -#define PAGE_CLUSTER 4 -static pdf_obj * -build_page_tree (pdf_doc *p, - pdf_page *firstpage, long num_pages, - pdf_obj *parent_ref) -{ - pdf_obj *self, *self_ref, *kids; - long i; - - self = pdf_new_dict(); - /* - * This is a slight kludge which allow the subtree dictionary - * generated by this routine to be merged with the real - * page_tree dictionary, while keeping the indirect object - * references right. - */ - self_ref = parent_ref ? pdf_ref_obj(self) : pdf_ref_obj(p->root.pages); - - pdf_add_dict(self, pdf_new_name("Type"), pdf_new_name("Pages")); - pdf_add_dict(self, pdf_new_name("Count"), pdf_new_number((double) num_pages)); - - if (parent_ref != NULL) - pdf_add_dict(self, pdf_new_name("Parent"), parent_ref); - - kids = pdf_new_array(); - if (num_pages > 0 && num_pages <= PAGE_CLUSTER) { - for (i = 0; i < num_pages; i++) { - pdf_page *page; - - page = firstpage + i; - if (!page->page_ref) - page->page_ref = pdf_ref_obj(page->page_obj); - pdf_add_array (kids, pdf_link_obj(page->page_ref)); - doc_flush_page(p, page, pdf_link_obj(self_ref)); - } - } else if (num_pages > 0) { - for (i = 0; i < PAGE_CLUSTER; i++) { - long start, end; - - start = (i*num_pages)/PAGE_CLUSTER; - end = ((i+1)*num_pages)/PAGE_CLUSTER; - if (end - start > 1) { - pdf_obj *subtree; - - subtree = build_page_tree(p, firstpage + start, end - start, - pdf_link_obj(self_ref)); - pdf_add_array(kids, pdf_ref_obj(subtree)); - pdf_release_obj(subtree); - } else { - pdf_page *page; - - page = firstpage + start; - if (!page->page_ref) - page->page_ref = pdf_ref_obj(page->page_obj); - pdf_add_array (kids, pdf_link_obj(page->page_ref)); - doc_flush_page(p, page, pdf_link_obj(self_ref)); - } - } - } - pdf_add_dict(self, pdf_new_name("Kids"), kids); - pdf_release_obj(self_ref); - - return self; -} - -static void -pdf_doc_init_page_tree (pdf_doc *p, double media_width, double media_height) -{ - /* - * Create empty page tree. - * The docroot.pages is kept open until the document is closed. - * This allows the user to write to pages if he so choses. - */ - p->root.pages = pdf_new_dict(); - - p->pages.num_entries = 0; - p->pages.max_entries = 0; - p->pages.entries = NULL; - - p->pages.bop = NULL; - p->pages.eop = NULL; - - p->pages.mediabox.llx = 0.0; - p->pages.mediabox.lly = 0.0; - p->pages.mediabox.urx = media_width; - p->pages.mediabox.ury = media_height; - - return; -} - -static void -pdf_doc_close_page_tree (pdf_doc *p) -{ - pdf_obj *page_tree_root; - pdf_obj *mediabox; - long page_no; - - /* - * Do consistency check on forward references to pages. - */ - for (page_no = PAGECOUNT(p) + 1; page_no <= MAXPAGES(p); page_no++) { - pdf_page *page; - - page = doc_get_page_entry(p, page_no); - if (page->page_obj) { - WARN("Nonexistent page #%ld refered.", page_no); - pdf_release_obj(page->page_ref); - page->page_ref = NULL; - } - if (page->page_obj) { - WARN("Entry for a nonexistent page #%ld created.", page_no); - pdf_release_obj(page->page_obj); - page->page_obj = NULL; - } - if (page->annots) { - WARN("Annotation attached to a nonexistent page #%ld.", page_no); - pdf_release_obj(page->annots); - page->annots = NULL; - } - if (page->beads) { - WARN("Article beads attached to a nonexistent page #%ld.", page_no); - pdf_release_obj(page->beads); - page->beads = NULL; - } - if (page->resources) { - pdf_release_obj(page->resources); - page->resources = NULL; - } - } - - /* - * Connect page tree to root node. - */ - page_tree_root = build_page_tree(p, FIRSTPAGE(p), PAGECOUNT(p), NULL); - pdf_merge_dict (p->root.pages, page_tree_root); - pdf_release_obj(page_tree_root); - - /* They must be after build_page_tree() */ - if (p->pages.bop) { - pdf_add_stream (p->pages.bop, "\n", 1); - pdf_release_obj(p->pages.bop); - p->pages.bop = NULL; - } - if (p->pages.eop) { - pdf_add_stream (p->pages.eop, "\n", 1); - pdf_release_obj(p->pages.eop); - p->pages.eop = NULL; - } - - /* Create media box at root node and let the other pages inherit it. */ - mediabox = pdf_new_array(); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.llx, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.lly, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.urx, 0.01))); - pdf_add_array(mediabox, pdf_new_number(ROUND(p->pages.mediabox.ury, 0.01))); - pdf_add_dict(p->root.pages, pdf_new_name("MediaBox"), mediabox); - - pdf_add_dict(p->root.dict, - pdf_new_name("Pages"), - pdf_ref_obj (p->root.pages)); - pdf_release_obj(p->root.pages); - p->root.pages = NULL; - - RELEASE(p->pages.entries); - p->pages.entries = NULL; - p->pages.num_entries = 0; - p->pages.max_entries = 0; - - return; -} - -/* - * From PDFReference15_v6.pdf (p.119 and p.834) - * - * MediaBox rectangle (Required; inheritable) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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) - * - * 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. - */ - -pdf_obj * -pdf_doc_get_page (pdf_file *pf, long page_no, long *count_p, - pdf_rect *bbox, pdf_obj **resources_p) { - pdf_obj *page_tree = NULL; - pdf_obj *resources = NULL, *box = NULL, *rotate = NULL; - pdf_obj *catalog; - - catalog = pdf_file_get_catalog(pf); - - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - - if (!PDF_OBJ_DICTTYPE(page_tree)) - goto error; - - { - long count; - pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); - if (!PDF_OBJ_NUMBERTYPE(tmp)) { - if (tmp) - pdf_release_obj(tmp); - goto error; - } - count = pdf_number_value(tmp); - pdf_release_obj(tmp); - if (count_p) - *count_p = count; - if (page_no <= 0 || page_no > count) { - WARN("Page %ld does not exist.", page_no); - goto error_silent; - } - } - - /* - * Seek correct page. Get MediaBox, CropBox and Resources. - * (Note that these entries can be inherited.) - */ - { - pdf_obj *media_box = NULL, *crop_box = NULL, *kids, *tmp; - int depth = PDF_OBJ_MAX_DEPTH; - long page_idx = page_no-1, kids_length = 1, i = 0; - - while (--depth && i != kids_length) { - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "MediaBox")))) { - if (media_box) - pdf_release_obj(media_box); - media_box = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Rotate")))) { - if (rotate) - pdf_release_obj(rotate); - rotate = tmp; - } - - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Resources")))) { - if (resources) - pdf_release_obj(resources); - resources = tmp; - } - - kids = pdf_deref_obj(pdf_lookup_dict(page_tree, "Kids")); - if (!kids) - break; - else if (!PDF_OBJ_ARRAYTYPE(kids)) { - pdf_release_obj(kids); - goto error; - } - 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)); - if (!PDF_OBJ_DICTTYPE(page_tree)) - goto error; - - tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "Count")); - if (PDF_OBJ_NUMBERTYPE(tmp)) { - /* Pages object */ - count = pdf_number_value(tmp); - pdf_release_obj(tmp); - } else if (!tmp) - /* Page object */ - count = 1; - else { - pdf_release_obj(tmp); - goto error; - } - - if (page_idx < count) - break; - - page_idx -= count; - } - - pdf_release_obj(kids); - } - - if (!depth || kids_length == i) { - if (media_box) - pdf_release_obj(media_box); - if (crop_box) - pdf_release_obj(crop_box); - goto error; - } - - if (crop_box) - box = crop_box; - else - if (!(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "ArtBox"))) && - !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "TrimBox"))) && - !(box = pdf_deref_obj(pdf_lookup_dict(page_tree, "BleedBox"))) && - media_box) { - box = media_box; - media_box = NULL; - } - if (media_box) - pdf_release_obj(media_box); - } - - if (!PDF_OBJ_ARRAYTYPE(box) || pdf_array_length(box) != 4 || - !PDF_OBJ_DICTTYPE(resources)) - goto error; - - if (PDF_OBJ_NUMBERTYPE(rotate)) { - if (pdf_number_value(rotate)) - WARN("<< /Rotate %d >> found. (Not supported yet)", - (int) pdf_number_value(rotate)); - pdf_release_obj(rotate); - rotate = NULL; - } else if (rotate) - goto error; - - { - int i; - - for (i = 4; i--; ) { - double x; - pdf_obj *tmp = pdf_deref_obj(pdf_get_array(box, i)); - if (!PDF_OBJ_NUMBERTYPE(tmp)) { - pdf_release_obj(tmp); - goto error; - } - x = pdf_number_value(tmp); - switch (i) { - case 0: bbox->llx = x; break; - case 1: bbox->lly = x; break; - case 2: bbox->urx = x; break; - case 3: bbox->ury = x; break; - } - pdf_release_obj(tmp); - } - } - - pdf_release_obj(box); - - if (resources_p) - *resources_p = resources; - else if (resources) - pdf_release_obj(resources); - - return page_tree; - - error: - WARN("Cannot parse document. Broken PDF file?"); - error_silent: - if (box) - pdf_release_obj(box); - if (rotate) - pdf_release_obj(rotate); - if (resources) - pdf_release_obj(resources); - if (page_tree) - pdf_release_obj(page_tree); - - return NULL; -} - -#ifndef BOOKMARKS_OPEN_DEFAULT -#define BOOKMARKS_OPEN_DEFAULT 0 -#endif - -static int clean_bookmarks (pdf_olitem *item); -static int flush_bookmarks (pdf_olitem *item, - pdf_obj *parent_ref, - pdf_obj *parent_dict); - -static void -pdf_doc_init_bookmarks (pdf_doc *p, int bm_open_depth) -{ - pdf_olitem *item; - -#define MAX_OUTLINE_DEPTH 256u - p->opt.outline_open_depth = - ((bm_open_depth >= 0) ? - bm_open_depth : MAX_OUTLINE_DEPTH - bm_open_depth); - - p->outlines.current_depth = 1; - - item = NEW(1, pdf_olitem); - item->dict = NULL; - item->next = NULL; - item->first = NULL; - item->parent = NULL; - item->is_open = 1; - - p->outlines.current = item; - p->outlines.first = item; - - return; -} - -static int -clean_bookmarks (pdf_olitem *item) -{ - pdf_olitem *next; - - while (item) { - next = item->next; - if (item->dict) - pdf_release_obj(item->dict); - if (item->first) - clean_bookmarks(item->first); - RELEASE(item); - - item = next; - } - - return 0; -} - -static int -flush_bookmarks (pdf_olitem *node, - pdf_obj *parent_ref, pdf_obj *parent_dict) -{ - int retval; - int count; - pdf_olitem *item; - pdf_obj *this_ref, *prev_ref, *next_ref; - - ASSERT(node->dict); - - this_ref = pdf_ref_obj(node->dict); - pdf_add_dict(parent_dict, - pdf_new_name("First"), pdf_link_obj(this_ref)); - - retval = 0; - for (item = node, prev_ref = NULL; - item && item->dict; item = item->next) { - if (item->first && item->first->dict) { - count = flush_bookmarks(item->first, this_ref, item->dict); - if (item->is_open) { - pdf_add_dict(item->dict, - pdf_new_name("Count"), - pdf_new_number(count)); - retval += count; - } else { - pdf_add_dict(item->dict, - pdf_new_name("Count"), - pdf_new_number(-count)); - } - } - pdf_add_dict(item->dict, - pdf_new_name("Parent"), - pdf_link_obj(parent_ref)); - if (prev_ref) { - pdf_add_dict(item->dict, - pdf_new_name("Prev"), - prev_ref); - } - if (item->next && item->next->dict) { - next_ref = pdf_ref_obj(item->next->dict); - pdf_add_dict(item->dict, - pdf_new_name("Next"), - pdf_link_obj(next_ref)); - } else { - next_ref = NULL; - } - - pdf_release_obj(item->dict); - item->dict = NULL; - - prev_ref = this_ref; - this_ref = next_ref; - retval++; - } - - pdf_add_dict(parent_dict, - pdf_new_name("Last"), - pdf_link_obj(prev_ref)); - - pdf_release_obj(prev_ref); - pdf_release_obj(node->dict); - node->dict = NULL; - - return retval; -} - -int -pdf_doc_bookmarks_up (void) -{ - pdf_doc *p = &pdoc; - pdf_olitem *parent, *item; - - item = p->outlines.current; - if (!item || !item->parent) { - WARN("Can't go up above the bookmark root node!"); - return -1; - } - parent = item->parent; - item = parent->next; - if (!parent->next) { - parent->next = item = NEW(1, pdf_olitem); - item->dict = NULL; - item->first = NULL; - item->next = NULL; - item->is_open = 0; - item->parent = parent->parent; - } - p->outlines.current = item; - p->outlines.current_depth--; - - return 0; -} - -int -pdf_doc_bookmarks_down (void) -{ - pdf_doc *p = &pdoc; - pdf_olitem *item, *first; - - item = p->outlines.current; - if (!item->dict) { - pdf_obj *tcolor, *action; - - WARN("Empty bookmark node!"); - WARN("You have tried to jump more than 1 level."); - - item->dict = pdf_new_dict(); - -#define TITLE_STRING "" - pdf_add_dict(item->dict, - pdf_new_name("Title"), - pdf_new_string(TITLE_STRING, strlen(TITLE_STRING))); - - tcolor = pdf_new_array(); - pdf_add_array(tcolor, pdf_new_number(1.0)); - pdf_add_array(tcolor, pdf_new_number(0.0)); - pdf_add_array(tcolor, pdf_new_number(0.0)); - pdf_add_dict (item->dict, - pdf_new_name("C"), pdf_link_obj(tcolor)); - pdf_release_obj(tcolor); - - pdf_add_dict (item->dict, - pdf_new_name("F"), pdf_new_number(1.0)); - -#define JS_CODE "app.alert(\"The author of this document made this bookmark item empty!\", 3, 0)" - action = pdf_new_dict(); - pdf_add_dict(action, - pdf_new_name("S"), pdf_new_name("JavaScript")); - pdf_add_dict(action, - pdf_new_name("JS"), pdf_new_string(JS_CODE, strlen(JS_CODE))); - pdf_add_dict(item->dict, - pdf_new_name("A"), pdf_link_obj(action)); - pdf_release_obj(action); - } - - item->first = first = NEW(1, pdf_olitem); - first->dict = NULL; - first->is_open = 0; - first->parent = item; - first->next = NULL; - first->first = NULL; - - p->outlines.current = first; - p->outlines.current_depth++; - - return 0; -} - -int -pdf_doc_bookmarks_depth (void) -{ - pdf_doc *p = &pdoc; - - return p->outlines.current_depth; -} - -void -pdf_doc_bookmarks_add (pdf_obj *dict, int is_open) -{ - pdf_doc *p = &pdoc; - pdf_olitem *item, *next; - - ASSERT(p && dict); - - item = p->outlines.current; - - if (!item) { - item = NEW(1, pdf_olitem); - item->parent = NULL; - p->outlines.first = item; - } else if (item->dict) { /* go to next item */ - item = item->next; - } - -#define BMOPEN(b,p) (((b) < 0) ? (((p)->outlines.current_depth > (p)->opt.outline_open_depth) ? 0 : 1) : (b)) - -#if 0 - item->dict = pdf_link_obj(dict); -#endif - item->dict = dict; - item->first = NULL; - item->is_open = BMOPEN(is_open, p); - - item->next = next = NEW(1, pdf_olitem); - next->dict = NULL; - next->parent = item->parent; - next->first = NULL; - next->is_open = -1; - next->next = NULL; - - p->outlines.current = item; - - pdf_doc_add_goto(dict); - - return; -} - -static void -pdf_doc_close_bookmarks (pdf_doc *p) -{ - pdf_obj *catalog = p->root.dict; - pdf_olitem *item; - int count; - pdf_obj *bm_root, *bm_root_ref; - - item = p->outlines.first; - if (item->dict) { - bm_root = pdf_new_dict(); - bm_root_ref = pdf_ref_obj(bm_root); - count = flush_bookmarks(item, bm_root_ref, bm_root); - pdf_add_dict(bm_root, - pdf_new_name("Count"), - pdf_new_number(count)); - pdf_add_dict(catalog, - pdf_new_name("Outlines"), - bm_root_ref); - pdf_release_obj(bm_root); - } - clean_bookmarks(item); - - p->outlines.first = NULL; - p->outlines.current = NULL; - p->outlines.current_depth = 0; - - return; -} - - -static const char *name_dict_categories[] = { - "Dests", "AP", "JavaScript", "Pages", - "Templates", "IDS", "URLS", "EmbeddedFiles", - "AlternatePresentations", "Renditions" -}; -#define NUM_NAME_CATEGORY (sizeof(name_dict_categories)/sizeof(name_dict_categories[0])) - -static void -pdf_doc_init_names (pdf_doc *p, int check_gotos) -{ - int i; - - p->root.names = NULL; - - p->names = NEW(NUM_NAME_CATEGORY + 1, struct name_dict); - for (i = 0; i < NUM_NAME_CATEGORY; i++) { - p->names[i].category = name_dict_categories[i]; - p->names[i].data = NULL; - } - p->names[NUM_NAME_CATEGORY].category = NULL; - p->names[NUM_NAME_CATEGORY].data = NULL; - - p->check_gotos = check_gotos; - ht_init_table(&p->gotos, (void (*) (void *)) pdf_release_obj); - - return; -} - -int -pdf_doc_add_names (const char *category, - const void *key, int keylen, pdf_obj *value) -{ - pdf_doc *p = &pdoc; - int i; - - for (i = 0; p->names[i].category != NULL; i++) { - if (!strcmp(p->names[i].category, category)) { - break; - } - } - if (p->names[i].category == NULL) { - WARN("Unknown name dictionary category \"%s\".", category); - return -1; - } - if (!p->names[i].data) { - p->names[i].data = pdf_new_name_tree(); - } - - return pdf_names_add_object(p->names[i].data, key, keylen, value); -} - -static void -pdf_doc_add_goto (pdf_obj *annot_dict) -{ - pdf_obj *subtype = NULL, *A = NULL, *S = NULL, *D = NULL, *D_new, *dict; - const char *dest, *key; - - if (!pdoc.check_gotos) - return; - - /* - * An annotation dictionary coming from an annotation special - * must have a "Subtype". An annotation dictionary coming from - * an outline special has none. - */ - subtype = pdf_deref_obj(pdf_lookup_dict(annot_dict, "Subtype")); - if (subtype) { - if (PDF_OBJ_UNDEFINED(subtype)) - goto undefined; - else if (!PDF_OBJ_NAMETYPE(subtype)) - goto error; - else if (strcmp(pdf_name_value(subtype), "Link")) - goto cleanup; - } - - dict = annot_dict; - key = "Dest"; - D = pdf_deref_obj(pdf_lookup_dict(annot_dict, key)); - if (PDF_OBJ_UNDEFINED(D)) - goto undefined; - - A = pdf_deref_obj(pdf_lookup_dict(annot_dict, "A")); - if (A) { - if (PDF_OBJ_UNDEFINED(A)) - goto undefined; - else if (D || !PDF_OBJ_DICTTYPE(A)) - goto error; - else { - S = pdf_deref_obj(pdf_lookup_dict(A, "S")); - if (PDF_OBJ_UNDEFINED(S)) - goto undefined; - else if (!PDF_OBJ_NAMETYPE(S)) - goto error; - else if (strcmp(pdf_name_value(S), "GoTo")) - goto cleanup; - - dict = A; - key = "D"; - D = pdf_deref_obj(pdf_lookup_dict(A, key)); - } - } - - if (PDF_OBJ_STRINGTYPE(D)) - dest = (char *) pdf_string_value(D); -#if 0 - /* Names as destinations are not supported by dvipdfmx */ - else if (PDF_OBJ_NAMETYPE(D)) - dest = pdf_name_value(D); -#endif - else if (PDF_OBJ_ARRAYTYPE(D)) - goto cleanup; - else if (PDF_OBJ_UNDEFINED(D)) - goto undefined; - else - goto error; - - D_new = ht_lookup_table(&pdoc.gotos, dest, strlen(dest)); - if (!D_new) { - char buf[10]; - - /* We use hexadecimal notation for our numeric destinations. - * Other bases (e.g., 10+26 or 10+2*26) would be more efficient. - */ - sprintf(buf, "%lx", ht_table_size(&pdoc.gotos)); - D_new = pdf_new_string(buf, strlen(buf)); - ht_append_table(&pdoc.gotos, dest, strlen(dest), D_new); - } - - { - pdf_obj *key_obj = pdf_new_name(key); - if (!pdf_add_dict(dict, key_obj, pdf_link_obj(D_new))) - pdf_release_obj(key_obj); - } - - cleanup: - if (subtype) - pdf_release_obj(subtype); - if (A) - pdf_release_obj(A); - if (S) - pdf_release_obj(S); - if (D) - pdf_release_obj(D); - - return; - - error: - WARN("Unknown PDF annotation format. Output file may be broken."); - goto cleanup; - - undefined: - WARN("Cannot optimize PDF annotations. Output file may be broken." - " Please restart with option \"-C 0x10\"\n"); - goto cleanup; -} - -#ifndef XETEX -static void -warn_undef_dests (struct ht_table *dests, struct ht_table *gotos) -{ - struct ht_iter iter; - - if (ht_set_iter(gotos, &iter) < 0) - return; - - do { - int keylen; - char *key = ht_iter_getkey(&iter, &keylen); - if (!ht_lookup_table(dests, key, keylen)) { - char *dest = NEW(keylen+1, char); - memcpy(dest, key, keylen); - dest[keylen] = 0; - WARN("PDF destination \"%s\" not defined.", dest); - RELEASE(dest); - } - } while (ht_iter_next(&iter) >= 0); - - ht_clear_iter(&iter); -} -#endif - -static void -pdf_doc_close_names (pdf_doc *p) -{ - pdf_obj *tmp; - int i; - - for (i = 0; p->names[i].category != NULL; i++) { - if (p->names[i].data) { - struct ht_table *data = p->names[i].data; - pdf_obj *name_tree; - long count; - - name_tree = pdf_names_create_tree(data, &count, NULL); - - if (name_tree) { - if (!p->root.names) { - p->root.names = pdf_new_dict(); - } - pdf_add_dict(p->root.names, - pdf_new_name(p->names[i].category), pdf_ref_obj(name_tree)); - pdf_release_obj(name_tree); - } - pdf_delete_name_tree(&p->names[i].data); - } - } - - if (p->root.names) { - tmp = pdf_lookup_dict(p->root.dict, "Names"); - if (!tmp) { - pdf_add_dict(p->root.dict, - pdf_new_name("Names"), - pdf_ref_obj (p->root.names)); - } else if (PDF_OBJ_DICTTYPE(tmp)) { - pdf_merge_dict(p->root.names, tmp); - pdf_add_dict(p->root.dict, - pdf_new_name("Names"), - pdf_ref_obj (p->root.names)); - } else { /* Maybe reference */ - /* What should I do? */ - WARN("Could not modify Names dictionary."); - } - pdf_release_obj(p->root.names); - p->root.names = NULL; - } - - RELEASE(p->names); - p->names = NULL; - - ht_clear_table(&p->gotos); - - return; -} - - -void -pdf_doc_add_annot (unsigned page_no, const pdf_rect *rect, - pdf_obj *annot_dict, int new_annot) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - pdf_obj *rect_array; - double annot_grow = p->opt.annot_grow; - - page = doc_get_page_entry(p, page_no); - if (!page->annots) - page->annots = pdf_new_array(); - - { - pdf_rect mediabox; - - pdf_doc_get_mediabox(page_no, &mediabox); - if (rect->llx < mediabox.llx || - rect->urx > mediabox.urx || - rect->lly < mediabox.lly || - rect->ury > mediabox.ury) { - WARN("Annotation out of page boundary."); - WARN("Current page's MediaBox: [%g %g %g %g]", - mediabox.llx, mediabox.lly, mediabox.urx, mediabox.ury); - WARN("Annotation: [%g %g %g %g]", - rect->llx, rect->lly, rect->urx, rect->ury); - WARN("Maybe incorrect paper size specified."); - } - if (rect->llx > rect->urx || rect->lly > rect->ury) { - WARN("Rectangle with negative width/height: [%g %g %g %g]", - rect->llx, rect->lly, rect->urx, rect->ury); - } - } - - rect_array = pdf_new_array(); - 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)); - - if (new_annot) - pdf_doc_add_goto(annot_dict); - - return; -} - - -/* - * PDF Article Thread - */ -static void -pdf_doc_init_articles (pdf_doc *p) -{ - p->root.threads = NULL; - - p->articles.num_entries = 0; - p->articles.max_entries = 0; - p->articles.entries = NULL; - - return; -} - -void -pdf_doc_begin_article (const char *article_id, pdf_obj *article_info) -{ - pdf_doc *p = &pdoc; - pdf_article *article; - - if (article_id == NULL || strlen(article_id) == 0) - ERROR("Article thread without internal identifier."); - - if (p->articles.num_entries >= p->articles.max_entries) { - p->articles.max_entries += PDFDOC_ARTICLE_ALLOC_SIZE; - p->articles.entries = RENEW(p->articles.entries, - p->articles.max_entries, struct pdf_article); - } - article = &(p->articles.entries[p->articles.num_entries]); - - article->id = NEW(strlen(article_id)+1, char); - strcpy(article->id, article_id); - article->info = article_info; - article->num_beads = 0; - article->max_beads = 0; - article->beads = NULL; - - p->articles.num_entries++; - - return; -} - -#if 0 -void -pdf_doc_end_article (const char *article_id) -{ - return; /* no-op */ -} -#endif - -static pdf_bead * -find_bead (pdf_article *article, const char *bead_id) -{ - pdf_bead *bead; - long i; - - bead = NULL; - for (i = 0; i < article->num_beads; i++) { - if (!strcmp(article->beads[i].id, bead_id)) { - bead = &(article->beads[i]); - break; - } - } - - return bead; -} - -void -pdf_doc_add_bead (const char *article_id, - const char *bead_id, long page_no, const pdf_rect *rect) -{ - pdf_doc *p = &pdoc; - pdf_article *article; - pdf_bead *bead; - long i; - - if (!article_id) { - ERROR("No article identifier specified."); - } - - article = NULL; - for (i = 0; i < p->articles.num_entries; i++) { - if (!strcmp(p->articles.entries[i].id, article_id)) { - article = &(p->articles.entries[i]); - break; - } - } - if (!article) { - ERROR("Specified article thread that doesn't exist."); - return; - } - - bead = bead_id ? find_bead(article, bead_id) : NULL; - if (!bead) { - if (article->num_beads >= article->max_beads) { - article->max_beads += PDFDOC_BEAD_ALLOC_SIZE; - article->beads = RENEW(article->beads, - article->max_beads, struct pdf_bead); - for (i = article->num_beads; i < article->max_beads; i++) { - article->beads[i].id = NULL; - article->beads[i].page_no = -1; - } - } - bead = &(article->beads[article->num_beads]); - if (bead_id) { - bead->id = NEW(strlen(bead_id)+1, char); - strcpy(bead->id, bead_id); - } else { - bead->id = NULL; - } - article->num_beads++; - } - bead->rect.llx = rect->llx; - bead->rect.lly = rect->lly; - bead->rect.urx = rect->urx; - bead->rect.ury = rect->ury; - bead->page_no = page_no; - - return; -} - -static pdf_obj * -make_article (pdf_doc *p, - pdf_article *article, - const char **bead_ids, int num_beads, - pdf_obj *article_info) -{ - pdf_obj *art_dict; - pdf_obj *first, *prev, *last; - long i, n; - - if (!article) - return NULL; - - art_dict = pdf_new_dict(); - first = prev = last = NULL; - /* - * The bead_ids represents logical order of beads in an article thread. - * If bead_ids is not given, we create an article thread in the order of - * beads appeared. - */ - n = bead_ids ? num_beads : article->num_beads; - for (i = 0; i < n; i++) { - pdf_bead *bead; - - bead = bead_ids ? find_bead(article, bead_ids[i]) : &(article->beads[i]); - if (!bead || bead->page_no < 0) { - continue; - } - last = pdf_new_dict(); - if (prev == NULL) { - first = last; - pdf_add_dict(first, - pdf_new_name("T"), pdf_ref_obj(art_dict)); - } else { - pdf_add_dict(prev, - pdf_new_name("N"), pdf_ref_obj(last)); - pdf_add_dict(last, - pdf_new_name("V"), pdf_ref_obj(prev)); - /* We must link first to last. */ - if (prev != first) - pdf_release_obj(prev); - } - - /* Realize bead now. */ - { - pdf_page *page; - pdf_obj *rect; - - page = doc_get_page_entry(p, bead->page_no); - if (!page->beads) { - page->beads = pdf_new_array(); - } - pdf_add_dict(last, pdf_new_name("P"), pdf_link_obj(page->page_ref)); - rect = pdf_new_array(); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.llx, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.lly, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.urx, 0.01))); - pdf_add_array(rect, pdf_new_number(ROUND(bead->rect.ury, 0.01))); - pdf_add_dict (last, pdf_new_name("R"), rect); - pdf_add_array(page->beads, pdf_ref_obj(last)); - } - - prev = last; - } - - if (first && last) { - pdf_add_dict(last, - pdf_new_name("N"), pdf_ref_obj(first)); - pdf_add_dict(first, - pdf_new_name("V"), pdf_ref_obj(last)); - if (first != last) { - pdf_release_obj(last); - } - pdf_add_dict(art_dict, - pdf_new_name("F"), pdf_ref_obj(first)); - /* If article_info is supplied, we override article->info. */ - if (article_info) { - pdf_add_dict(art_dict, - pdf_new_name("I"), article_info); - } else if (article->info) { - pdf_add_dict(art_dict, - pdf_new_name("I"), pdf_ref_obj(article->info)); - pdf_release_obj(article->info); - article->info = NULL; /* We do not write as object reference. */ - } - pdf_release_obj(first); - } else { - pdf_release_obj(art_dict); - art_dict = NULL; - } - - return art_dict; -} - -static void -clean_article (pdf_article *article) -{ - if (!article) - return; - - if (article->beads) { - long i; - - for (i = 0; i < article->num_beads; i++) { - if (article->beads[i].id) - RELEASE(article->beads[i].id); - } - RELEASE(article->beads); - article->beads = NULL; - } - - if (article->id) - RELEASE(article->id); - article->id = NULL; - article->num_beads = 0; - article->max_beads = 0; - - return; -} - -static void -pdf_doc_close_articles (pdf_doc *p) -{ - int i; - - for (i = 0; i < p->articles.num_entries; i++) { - pdf_article *article; - - article = &(p->articles.entries[i]); - if (article->beads) { - pdf_obj *art_dict; - - art_dict = make_article(p, article, NULL, 0, NULL); - if (!p->root.threads) { - p->root.threads = pdf_new_array(); - } - pdf_add_array(p->root.threads, pdf_ref_obj(art_dict)); - pdf_release_obj(art_dict); - } - clean_article(article); - } - RELEASE(p->articles.entries); - p->articles.entries = NULL; - p->articles.num_entries = 0; - p->articles.max_entries = 0; - - if (p->root.threads) { - pdf_add_dict(p->root.dict, - pdf_new_name("Threads"), - pdf_ref_obj (p->root.threads)); - pdf_release_obj(p->root.threads); - p->root.threads = NULL; - } - - return; -} - -/* page_no = 0 for root page tree node. */ -void -pdf_doc_set_mediabox (unsigned page_no, const pdf_rect *mediabox) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - if (page_no == 0) { - p->pages.mediabox.llx = mediabox->llx; - p->pages.mediabox.lly = mediabox->lly; - p->pages.mediabox.urx = mediabox->urx; - p->pages.mediabox.ury = mediabox->ury; - } else { - page = doc_get_page_entry(p, page_no); - page->cropbox.llx = mediabox->llx; - page->cropbox.lly = mediabox->lly; - page->cropbox.urx = mediabox->urx; - page->cropbox.ury = mediabox->ury; - page->flags |= USE_MY_MEDIABOX; - } - - return; -} - -void -pdf_doc_get_mediabox (unsigned page_no, pdf_rect *mediabox) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - if (page_no == 0) { - mediabox->llx = p->pages.mediabox.llx; - mediabox->lly = p->pages.mediabox.lly; - mediabox->urx = p->pages.mediabox.urx; - mediabox->ury = p->pages.mediabox.ury; - } else { - page = doc_get_page_entry(p, page_no); - if (page->flags & USE_MY_MEDIABOX) { - mediabox->llx = page->cropbox.llx; - mediabox->lly = page->cropbox.lly; - mediabox->urx = page->cropbox.urx; - mediabox->ury = page->cropbox.ury; - } else { - mediabox->llx = p->pages.mediabox.llx; - mediabox->lly = p->pages.mediabox.lly; - mediabox->urx = p->pages.mediabox.urx; - mediabox->ury = p->pages.mediabox.ury; - } - } - - return; -} - -pdf_obj * -pdf_doc_current_page_resources (void) -{ - pdf_obj *resources; - pdf_doc *p = &pdoc; - pdf_page *currentpage; - - if (p->pending_forms) { - if (p->pending_forms->form.resources) { - resources = p->pending_forms->form.resources; - } else { - resources = p->pending_forms->form.resources = pdf_new_dict(); - } - } else { - currentpage = LASTPAGE(p); - if (currentpage->resources) { - resources = currentpage->resources; - } else { - resources = currentpage->resources = pdf_new_dict(); - } - } - - return resources; -} - -pdf_obj * -pdf_doc_get_dictionary (const char *category) -{ - pdf_doc *p = &pdoc; - pdf_obj *dict = NULL; - - ASSERT(category); - - if (!strcmp(category, "Names")) { - if (!p->root.names) - p->root.names = pdf_new_dict(); - dict = p->root.names; - } else if (!strcmp(category, "Pages")) { - if (!p->root.pages) - p->root.pages = pdf_new_dict(); - dict = p->root.pages; - } else if (!strcmp(category, "Catalog")) { - if (!p->root.dict) - p->root.dict = pdf_new_dict(); - dict = p->root.dict; - } else if (!strcmp(category, "Info")) { - if (!p->info) - p->info = pdf_new_dict(); - dict = p->info; - } else if (!strcmp(category, "@THISPAGE")) { - /* Sorry for this... */ - pdf_page *currentpage; - - currentpage = LASTPAGE(p); - dict = currentpage->page_obj; - } - - if (!dict) { - ERROR("Document dict. \"%s\" not exist. ", category); - } - - return dict; -} - -long -pdf_doc_current_page_number (void) -{ - pdf_doc *p = &pdoc; - - return (long) (PAGECOUNT(p) + 1); -} - -pdf_obj * -pdf_doc_ref_page (unsigned long page_no) -{ - pdf_doc *p = &pdoc; - pdf_page *page; - - page = doc_get_page_entry(p, page_no); - if (!page->page_obj) { - page->page_obj = pdf_new_dict(); - page->page_ref = pdf_ref_obj(page->page_obj); - } - - return pdf_link_obj(page->page_ref); -} - -pdf_obj * -pdf_doc_get_reference (const char *category) -{ - pdf_obj *ref = NULL; - long page_no; - - ASSERT(category); - - page_no = pdf_doc_current_page_number(); - if (!strcmp(category, "@THISPAGE")) { - ref = pdf_doc_ref_page(page_no); - } else if (!strcmp(category, "@PREVPAGE")) { - if (page_no <= 1) { - ERROR("Reference to previous page, but no pages have been completed yet."); - } - ref = pdf_doc_ref_page(page_no - 1); - } else if (!strcmp(category, "@NEXTPAGE")) { - ref = pdf_doc_ref_page(page_no + 1); - } - - if (!ref) { - ERROR("Reference to \"%s\" not exist. ", category); - } - - return ref; -} - -static void -pdf_doc_new_page (pdf_doc *p) -{ - pdf_page *currentpage; - - if (PAGECOUNT(p) >= MAXPAGES(p)) { - doc_resize_page_entries(p, MAXPAGES(p) + PDFDOC_PAGES_ALLOC_SIZE); - } - - /* - * This is confusing. pdf_doc_finish_page() have increased page count! - */ - currentpage = LASTPAGE(p); - /* Was this page already instantiated by a forward reference to it? */ - if (!currentpage->page_ref) { - currentpage->page_obj = pdf_new_dict(); - currentpage->page_ref = pdf_ref_obj(currentpage->page_obj); - } - - currentpage->background = NULL; - currentpage->contents = pdf_new_stream(STREAM_COMPRESS); - currentpage->resources = pdf_new_dict(); - - currentpage->annots = NULL; - currentpage->beads = NULL; - - return; -} - -/* This only closes contents and resources. */ -static void -pdf_doc_finish_page (pdf_doc *p) -{ - pdf_page *currentpage; - - if (p->pending_forms) { - ERROR("A pending form XObject at the end of page."); - } - - currentpage = LASTPAGE(p); - if (!currentpage->page_obj) - currentpage->page_obj = pdf_new_dict(); - - /* - * Make Contents array. - */ - - /* - * Global BOP content stream. - * pdf_ref_obj() returns reference itself when the object is - * indirect reference, not reference to the indirect reference. - * We keep bop itself but not reference to it since it is - * expected to be small. - */ - if (p->pages.bop && - pdf_stream_length(p->pages.bop) > 0) { - currentpage->content_refs[0] = pdf_ref_obj(p->pages.bop); - } else { - currentpage->content_refs[0] = NULL; - } - /* - * Current page background content stream. - */ - if (currentpage->background) { - if (pdf_stream_length(currentpage->background) > 0) { - currentpage->content_refs[1] = pdf_ref_obj(currentpage->background); - pdf_add_stream (currentpage->background, "\n", 1); - } - pdf_release_obj(currentpage->background); - currentpage->background = NULL; - } else { - currentpage->content_refs[1] = NULL; - } - - /* Content body of current page */ - currentpage->content_refs[2] = pdf_ref_obj(currentpage->contents); - pdf_add_stream (currentpage->contents, "\n", 1); - pdf_release_obj(currentpage->contents); - currentpage->contents = NULL; - - /* - * Global EOP content stream. - */ - if (p->pages.eop && - pdf_stream_length(p->pages.eop) > 0) { - currentpage->content_refs[3] = pdf_ref_obj(p->pages.eop); - } else { - currentpage->content_refs[3] = NULL; - } - - /* - * Page resources. - */ - if (currentpage->resources) { - pdf_obj *procset; - /* - * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. - */ - - procset = pdf_new_array (); - pdf_add_array(procset, pdf_new_name("PDF")); - pdf_add_array(procset, pdf_new_name("Text")); - pdf_add_array(procset, pdf_new_name("ImageC")); - pdf_add_array(procset, pdf_new_name("ImageB")); - pdf_add_array(procset, pdf_new_name("ImageI")); - pdf_add_dict(currentpage->resources, pdf_new_name("ProcSet"), procset); - - pdf_add_dict(currentpage->page_obj, - pdf_new_name("Resources"), - pdf_ref_obj(currentpage->resources)); - pdf_release_obj(currentpage->resources); - currentpage->resources = NULL; - } - - if (manual_thumb_enabled) { - char *thumb_filename; - pdf_obj *thumb_ref; - - thumb_filename = NEW(strlen(thumb_basename)+7, char); - sprintf(thumb_filename, "%s.%ld", - thumb_basename, (p->pages.num_entries % 99999) + 1L); - thumb_ref = read_thumbnail(thumb_filename); - RELEASE(thumb_filename); - if (thumb_ref) - pdf_add_dict(currentpage->page_obj, pdf_new_name("Thumb"), thumb_ref); - } - - p->pages.num_entries++; - - return; -} - - -static pdf_color bgcolor = { 1, { 1.0 } }; -void -pdf_doc_set_bgcolor (const pdf_color *color) -{ - if (color) - memcpy(&bgcolor, color, sizeof(pdf_color)); - else { /* as clear... */ - pdf_color_graycolor(&bgcolor, 1.0); - } -} - -static void -doc_fill_page_background (pdf_doc *p) -{ - pdf_page *currentpage; - pdf_rect r; - int cm; - pdf_obj *saved_content; - - cm = pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE); - if (!cm || pdf_color_is_white(&bgcolor)) { - return; - } - - pdf_doc_get_mediabox(pdf_doc_current_page_number(), &r); - - currentpage = LASTPAGE(p); - ASSERT(currentpage); - - if (!currentpage->background) - currentpage->background = pdf_new_stream(STREAM_COMPRESS); - - saved_content = currentpage->contents; - currentpage->contents = currentpage->background; - - pdf_dev_gsave(); - //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_dev_grestore(); - - currentpage->contents = saved_content; - - return; -} - -void -pdf_doc_begin_page (double scale, double x_origin, double y_origin) -{ - pdf_doc *p = &pdoc; - pdf_tmatrix M; - - M.a = scale; M.b = 0.0; - M.c = 0.0 ; M.d = scale; - M.e = x_origin; - M.f = y_origin; - - /* pdf_doc_new_page() allocates page content stream. */ - pdf_doc_new_page(p); - pdf_dev_bop(&M); - - return; -} - -void -pdf_doc_end_page (void) -{ - pdf_doc *p = &pdoc; - - pdf_dev_eop(); - doc_fill_page_background(p); - - pdf_doc_finish_page(p); - - return; -} - -void -pdf_doc_add_page_content (const char *buffer, unsigned length) -{ - pdf_doc *p = &pdoc; - pdf_page *currentpage; - - if (p->pending_forms) { - pdf_add_stream(p->pending_forms->form.contents, buffer, length); - } else { - currentpage = LASTPAGE(p); - pdf_add_stream(currentpage->contents, buffer, length); - } - - return; -} - -static char *doccreator = NULL; /* Ugh */ - -void -pdf_open_document (const char *filename, - int do_encryption, - double media_width, double media_height, - double annot_grow_amount, int bookmark_open_depth, - int check_gotos) -{ - pdf_doc *p = &pdoc; - - pdf_out_init(filename, do_encryption); - - pdf_doc_init_catalog(p); - - p->opt.annot_grow = annot_grow_amount; - p->opt.outline_open_depth = bookmark_open_depth; - - pdf_init_resources(); - pdf_init_colors(); - pdf_init_fonts(); - /* Thumbnail want this to be initialized... */ - pdf_init_images(); - - pdf_doc_init_docinfo(p); - if (doccreator) { - pdf_add_dict(p->info, - pdf_new_name("Creator"), - pdf_new_string(doccreator, strlen(doccreator))); - RELEASE(doccreator); doccreator = NULL; - } - - pdf_doc_init_bookmarks(p, bookmark_open_depth); - pdf_doc_init_articles (p); - pdf_doc_init_names (p, check_gotos); - pdf_doc_init_page_tree(p, media_width, media_height); - - if (do_encryption) { - pdf_obj *encrypt = pdf_encrypt_obj(); - pdf_set_encrypt(encrypt); - pdf_release_obj(encrypt); - } - pdf_set_id(pdf_enc_id_array()); - - /* Create a default name for thumbnail image files */ - if (manual_thumb_enabled) { - if (strlen(filename) > 4 && - !strncmp(".pdf", filename + strlen(filename) - 4, 4)) { - thumb_basename = NEW(strlen(filename)-4+1, char); - strncpy(thumb_basename, filename, strlen(filename)-4); - thumb_basename[strlen(filename)-4] = 0; - } else { - thumb_basename = NEW(strlen(filename)+1, char); - strcpy(thumb_basename, filename); - } - } - - p->pending_forms = NULL; - - return; -} - -void -pdf_doc_set_creator (const char *creator) -{ - if (!creator || - creator[0] == '\0') - return; - - doccreator = NEW(strlen(creator)+1, char); - strcpy(doccreator, creator); /* Ugh */ -} - - -void -pdf_close_document (void) -{ - pdf_doc *p = &pdoc; - - /* - * Following things were kept around so user can add dictionary items. - */ - pdf_doc_close_articles (p); - pdf_doc_close_names (p); - pdf_doc_close_bookmarks(p); - pdf_doc_close_page_tree(p); - pdf_doc_close_docinfo (p); - - pdf_doc_close_catalog (p); - - pdf_close_images(); - pdf_close_fonts (); - pdf_close_colors(); - - pdf_close_resources(); /* Should be at last. */ - - pdf_out_flush(); - - if (thumb_basename) - RELEASE(thumb_basename); - - return; -} - -/* - * All this routine does is give the form a name and add a unity scaling matrix. - * It fills in required fields. The caller must initialize the stream. - */ -static void -pdf_doc_make_xform (pdf_obj *xform, - pdf_rect *bbox, - pdf_tmatrix *matrix, - pdf_obj *resources, - pdf_obj *attrib) -{ - pdf_obj *xform_dict; - pdf_obj *tmp; - - xform_dict = pdf_stream_dict(xform); - pdf_add_dict(xform_dict, - pdf_new_name("Type"), pdf_new_name("XObject")); - pdf_add_dict(xform_dict, - pdf_new_name("Subtype"), pdf_new_name("Form")); - pdf_add_dict(xform_dict, - pdf_new_name("FormType"), pdf_new_number(1.0)); - - if (!bbox) - ERROR("No BoundingBox supplied."); - - tmp = pdf_new_array(); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->llx, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->lly, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->urx, .001))); - pdf_add_array(tmp, pdf_new_number(ROUND(bbox->ury, .001))); - pdf_add_dict(xform_dict, pdf_new_name("BBox"), tmp); - - if (matrix) { - tmp = pdf_new_array(); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->a, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->b, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->c, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->d, .00001))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->e, .001 ))); - pdf_add_array(tmp, pdf_new_number(ROUND(matrix->f, .001 ))); - pdf_add_dict(xform_dict, pdf_new_name("Matrix"), tmp); - } - - if (attrib) { - pdf_merge_dict(xform_dict, attrib); - } - - pdf_add_dict(xform_dict, pdf_new_name("Resources"), resources); - - return; -} - -/* - * begin_form_xobj creates an xobject with its "origin" at - * xpos and ypos that is clipped to the specified bbox. Note - * that the origin is not the lower left corner of the bbox. - */ -int -pdf_doc_begin_grabbing (const char *ident, - double ref_x, double ref_y, const pdf_rect *cropbox) -{ - int xobj_id = -1; - pdf_doc *p = &pdoc; - pdf_form *form; - struct form_list_node *fnode; - xform_info info; - - fnode = NEW(1, struct form_list_node); - - fnode->prev = p->pending_forms; - fnode->q_depth = pdf_dev_current_depth(); - form = &fnode->form; - - /* - * The reference point of an Xobject is at the lower left corner - * of the bounding box. Since we would like to have an arbitrary - * reference point, we use a transformation matrix, translating - * the reference point to (0,0). - */ - - form->matrix.a = 1.0; form->matrix.b = 0.0; - form->matrix.c = 0.0; form->matrix.d = 1.0; - form->matrix.e = -ref_x; - form->matrix.f = -ref_y; - - form->cropbox.llx = ref_x + cropbox->llx; - form->cropbox.lly = ref_y + cropbox->lly; - form->cropbox.urx = ref_x + cropbox->urx; - form->cropbox.ury = ref_y + cropbox->ury; - - form->contents = pdf_new_stream(STREAM_COMPRESS); - form->resources = pdf_new_dict(); - - pdf_ximage_init_form_info(&info); - - info.matrix.a = 1.0; info.matrix.b = 0.0; - info.matrix.c = 0.0; info.matrix.d = 1.0; - info.matrix.e = -ref_x; - info.matrix.f = -ref_y; - - info.bbox.llx = cropbox->llx; - info.bbox.lly = cropbox->lly; - info.bbox.urx = cropbox->urx; - info.bbox.ury = cropbox->ury; - - /* Use reference since content itself isn't available yet. */ - xobj_id = pdf_ximage_defineresource(ident, - PDF_XOBJECT_TYPE_FORM, - &info, pdf_ref_obj(form->contents)); - - p->pending_forms = fnode; - - /* - * Make sure the object is self-contained by adding the - * current font and color to the object stream. - */ - pdf_dev_reset_fonts(); - pdf_dev_reset_color(); - - return xobj_id; -} - -void -pdf_doc_end_grabbing (pdf_obj *attrib) -{ - pdf_form *form; - pdf_obj *procset; - pdf_doc *p = &pdoc; - struct form_list_node *fnode; - - if (!p->pending_forms) { - WARN("Tried to close a nonexistent form XOject."); - return; - } - - fnode = p->pending_forms; - form = &fnode->form; - - pdf_dev_grestore_to(fnode->q_depth); - - /* - * ProcSet is obsolete in PDF-1.4 but recommended for compatibility. - */ - procset = pdf_new_array(); - pdf_add_array(procset, pdf_new_name("PDF")); - pdf_add_array(procset, pdf_new_name("Text")); - pdf_add_array(procset, pdf_new_name("ImageC")); - pdf_add_array(procset, pdf_new_name("ImageB")); - pdf_add_array(procset, pdf_new_name("ImageI")); - pdf_add_dict (form->resources, pdf_new_name("ProcSet"), procset); - - pdf_doc_make_xform(form->contents, - &form->cropbox, &form->matrix, - pdf_ref_obj(form->resources), attrib); - pdf_release_obj(form->resources); - pdf_release_obj(form->contents); - if (attrib) pdf_release_obj(attrib); - - p->pending_forms = fnode->prev; - - /* Here we do not need pdf_dev_reset_color(). */ - pdf_dev_reset_fonts(); - - RELEASE(fnode); - - return; -} - -static struct -{ - int dirty; - pdf_obj *annot_dict; - pdf_rect rect; -} breaking_state = {0, NULL, {0.0, 0.0, 0.0, 0.0}}; - -static void -reset_box (void) -{ - breaking_state.rect.llx = 10000.0; /* large value */ - breaking_state.rect.lly = 10000.0; /* large value */ - breaking_state.rect.urx = 0.0; /* small value */ - breaking_state.rect.ury = 0.0; /* small value */ - breaking_state.dirty = 0; -} - -void -pdf_doc_begin_annot (pdf_obj *dict) -{ - breaking_state.annot_dict = dict; - reset_box(); -} - -void -pdf_doc_end_annot (void) -{ - pdf_doc_break_annot(); - breaking_state.annot_dict = NULL; -} - -void -pdf_doc_break_annot (void) -{ - if (breaking_state.dirty) { - pdf_obj *annot_dict; - - /* Copy dict */ - annot_dict = pdf_new_dict(); - pdf_merge_dict(annot_dict, breaking_state.annot_dict); - pdf_doc_add_annot(pdf_doc_current_page_number(), &(breaking_state.rect), - annot_dict, 0); - pdf_release_obj(annot_dict); - } - reset_box(); -} - -void -pdf_doc_expand_box (const pdf_rect *rect) -{ - breaking_state.rect.llx = MIN(breaking_state.rect.llx, rect->llx); - breaking_state.rect.lly = MIN(breaking_state.rect.lly, rect->lly); - breaking_state.rect.urx = MAX(breaking_state.rect.urx, rect->urx); - breaking_state.rect.ury = MAX(breaking_state.rect.ury, rect->ury); - breaking_state.dirty = 1; -} - -#if 0 -/* This should be number tree */ -void -pdf_doc_set_pagelabel (long pg_start, - const char *type, - const void *prefix, int prfx_len, long start) -{ - pdf_doc *p = &pdoc; - pdf_obj *label_dict; - - if (!p->root.pagelabels) - p->root.pagelabels = pdf_new_array(); - - label_dict = pdf_new_dict(); - if (!type || type[0] == '\0') /* Set back to default. */ - pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name("D")); - else { - if (type) - pdf_add_dict(label_dict, pdf_new_name("S"), pdf_new_name(type)); - if (prefix && prfx_len > 0) - pdf_add_dict(label_dict, - pdf_new_name("P"), - pdf_new_string(prefix, prfx_len)); - if (start != 1) - pdf_add_dict(label_dict, - pdf_new_name("St"), pdf_new_number(start)); - } - - pdf_add_array(p->root.pagelabels, pdf_new_number(pg_start)); - pdf_add_array(p->root.pagelabels, label_dict); - - return; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfdraw.c b/Build/source/texk/dvipdfm-x/xsrc/pdfdraw.c deleted file mode 100644 index 334649b3bec..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfdraw.c +++ /dev/null @@ -1,1906 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "error.h" -#include "mem.h" -#include "mfileio.h" -#include "dpxutil.h" -#include "numbers.h" - -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfcolor.h" - -#include "pdfdraw.h" - -#if 1 -typedef void pdf_dev; -#endif - - -/* - * Numbers are rounding to 0-5 fractional digits - * in output routine. - */ -#define detM(M) ((M).a * (M).d - (M).b * (M).c) -#define detP(M) ((M)->a * (M)->d - (M)->b * (M)->c) - - -static /* __inline__ */ int -inversematrix (pdf_tmatrix *W, const pdf_tmatrix *M) -{ - double det; - - det = detP(M); - if (fabs(det) < 1.e-8) { -#if 1 - WARN("Inverting matrix with zero determinant..."); -#endif - return -1; /* result is undefined. */ - } - - W->a = (M->d) / det; W->b = -(M->b) / det; - 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); - - return 0; -} - -/* pdf_coord as vector */ -#define vecprd(v,w) ((v).x * (w).x + (v).y * (w).y) -#define vecrot(v,w) ((v).x * (w).y - (v).y * (w).x) -#define dsign(v) (((v) >= 0.0) ? 1.0 : -1.0) -/* acos => [0, pi] */ -#define vecang(v,w) ( \ - dsign(vecrot((v),(w))) * \ - acos(vecprd((v),(w)) / sqrt(vecprd((v),(v)) * vecprd((w),(w)))) \ -) - -static /* __inline__ */ int -pdf_coord__equal (const pdf_coord *p1, const pdf_coord *p2) -{ - if (fabs(p1->x - p2->x) < 1.e-7 && - fabs(p1->y - p2->y) < 1.e-7) - return 1; - return 0; -} -#define COORD_EQUAL(p,q) pdf_coord__equal((p),(q)) - -#if 0 -static int -pdf_coord__sort_compar_X (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->x - p2->x); - - return 1; -} - -static int -pdf_coord__sort_compar_Y (const void *pp1, const void *pp2) -{ - pdf_coord *p1 = (pdf_coord *)pp1; - pdf_coord *p2 = (pdf_coord *)pp2; - - if (pdf_coord__equal(p1, p2)) - return 0; - else - return (int) dsign(p1->y - p2->y); - - return 1; -} -#endif - - -static /* __inline__ */ int -pdf_coord__transform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c + M->e; - p->y = x * M->b + y * M->d + M->f; - - return 0; -} - -#if 0 -static /* __inline__ */ int -pdf_coord__itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c + W.e; - p->y = x * W.b + y * W.d + W.f; - - return 0; -} -#endif - -static /* __inline__ */ int -pdf_coord__dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - double x, y; - - x = p->x; y = p->y; - p->x = x * M->a + y * M->c; - p->y = x * M->b + y * M->d; - - return 0; -} - -static /* __inline__ */ int -pdf_coord__idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - pdf_tmatrix W; - double x, y; - int error; - - error = inversematrix(&W, M); - if (error) - return error; - - x = p->x; y = p->y; - p->x = x * W.a + y * W.c; - p->y = x * W.b + y * W.d; - - return 0; -} - - -/* Modify M itself */ -void -pdf_invertmatrix (pdf_tmatrix *M) -{ - pdf_tmatrix W; - double det; - - ASSERT(M); - - det = detP(M); - if (fabs(det) < 1.e-8) { - WARN("Inverting matrix with zero determinant..."); - W.a = 1.0; W.c = 0.0; - W.b = 0.0; W.d = 1.0; - W.e = 0.0; W.f = 0.0; - } else { - W.a = (M->d) / det; W.b = -(M->b) / det; - 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); - - return; -} - - -typedef struct pa_elem_ -{ - int type; - pdf_coord p[3]; -} pa_elem; - -/* each subpath delimitted by moveto */ -struct pdf_path_ -{ - int num_paths; - int max_paths; - pa_elem *path; -}; - -static const struct { - char opchr; /* PDF operator char */ - int n_pts; /* number of *points* */ - const char *strkey; -} petypes[] = { -#define PE_TYPE__INVALID -1 -#define PE_TYPE__MOVETO 0 - {'m', 1, "moveto" }, -#define PE_TYPE__LINETO 1 - {'l', 1, "lineto" }, -#define PE_TYPE__CURVETO 2 - {'c', 3, "curveto" }, - /* no PS correspondence for v and y */ -#define PE_TYPE__CURVETO_V 3 - {'v', 2, "vcurveto"}, /* current point replicated */ -#define PE_TYPE__CURVETO_Y 4 - {'y', 2, "ycurveto"}, /* last point replicated */ -#define PE_TYPE__CLOSEPATH 5 - {'h', 0, "closepath"}, -#define PE_TYPE__TERMINATE 6 - {' ', 0, NULL} -}; - -#define PE_VALID(p) ((p) && \ - (p)->type > PE_TYPE__INVALID && (p)->type < PE_TYPE__TERMINATE) -#define PE_N_PTS(p) (PE_VALID((p)) ? petypes[(p)->type].n_pts : 0) -#define PE_OPCHR(p) (PE_VALID((p)) ? petypes[(p)->type].opchr : ' ') - -#define PA_LENGTH(pa) ((pa)->num_paths) - -#define GS_FLAG_CURRENTPOINT_SET (1 << 0) - - -static char fmt_buf[1024]; /* FIXME */ -#define FORMAT_BUFF_PTR(p) fmt_buf -#define FORMAT_BUFF_LEN(p) 1024 - -static void -init_a_path (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - p->max_paths = 0; - p->path = NULL; - - return; -} - -static void -pdf_path__clearpath (pdf_path *p) -{ - ASSERT(p); - - p->num_paths = 0; - - return; -} - -static int -pdf_path__growpath (pdf_path *p, int max_pe) -{ - if (max_pe < p->max_paths) - return 0; - - p->max_paths = MAX(p->max_paths + 8, max_pe); - p->path = RENEW(p->path, p->max_paths, pa_elem); - - return 0; -} - -static void -clear_a_path (pdf_path *p) -{ - ASSERT(p); - - if (p->path) - RELEASE(p->path); - p->path = NULL; - p->num_paths = 0; - p->max_paths = 0; - - return; -} - -static int -pdf_path__copypath (pdf_path *p1, const pdf_path *p0) -{ - pa_elem *pe0, *pe1; - int i; - - pdf_path__growpath(p1, PA_LENGTH(p0)); - for (i = 0; i < PA_LENGTH(p0); i++) { - pe1 = &(p1->path[i]); - pe0 = &(p0->path[i]); - /* FIXME */ - pe1->type = pe0->type; - pe1->p[0].x = pe0->p[0].x; - pe1->p[0].y = pe0->p[0].y; - pe1->p[1].x = pe0->p[1].x; - pe1->p[1].y = pe0->p[1].y; - pe1->p[2].x = pe0->p[2].x; - pe1->p[2].y = pe0->p[2].y; - } - p1->num_paths = PA_LENGTH(p0); - - return 0; -} - - -/* start new subpath */ -static int -pdf_path__moveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - if (PA_LENGTH(pa) > 0) { - pe = &pa->path[pa->num_paths-1]; - if (pe->type == PE_TYPE__MOVETO) { - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - return 0; - } - } - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -/* Do 'compression' of path while adding new path elements. - * Sequantial moveto command will be replaced with a - * single moveto. If cp is not equal to the last point in pa, - * then moveto is inserted (starting new subpath). - * FIXME: - * 'moveto' must be used to enforce starting new path. - * This affects how 'closepath' is treated. - */ -static pa_elem * -pdf_path__next_pe (pdf_path *pa, const pdf_coord *cp) -{ - pa_elem *pe; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 2); - if (PA_LENGTH(pa) == 0) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - - return &pa->path[pa->num_paths++]; - } - - pe = &pa->path[pa->num_paths-1]; - switch (pe->type) { - case PE_TYPE__MOVETO: - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - case PE_TYPE__LINETO: - if (!COORD_EQUAL(&pe->p[0], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO: - if (!COORD_EQUAL(&pe->p[2], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CURVETO_Y: - case PE_TYPE__CURVETO_V: - if (!COORD_EQUAL(&pe->p[1], cp)) { - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - } - break; - case PE_TYPE__CLOSEPATH: - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__MOVETO; - pe->p[0].x = cp->x; - pe->p[0].y = cp->y; - break; - } - - return &pa->path[pa->num_paths++]; -} - -static int -pdf_path__transform (pdf_path *pa, const pdf_tmatrix *M) -{ - pa_elem *pe; - int n = 0, i; - - ASSERT(pa && M); - - for (i = 0; i < PA_LENGTH(pa); i++) { - pe = &(pa->path[i]); - n = PE_N_PTS(pe); - while (n-- > 0) - pdf_coord__transform(&(pe->p[n]), M); - } - - return 0; -} - - -/* Path Construction */ -static int -pdf_path__lineto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - pe->type = PE_TYPE__LINETO; - pe->p[0].x = cp->x = p0->x; - pe->p[0].y = cp->y = p0->y; - - return 0; -} - -static int -pdf_path__curveto (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1, - const pdf_coord *p2 - ) -{ - pa_elem *pe; - - pe = pdf_path__next_pe(pa, cp); - if (COORD_EQUAL(cp, p0)) { - pe->type = PE_TYPE__CURVETO_V; - pe->p[0].x = p1->x; - pe->p[0].y = p1->y; - pe->p[1].x = cp->x = p2->x; - pe->p[1].y = cp->y = p2->y; - } else if (COORD_EQUAL(p1, p2)) { - pe->type = PE_TYPE__CURVETO_Y; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = cp->x = p1->x; - pe->p[1].y = cp->y = p1->y; - } else { - pe->type = PE_TYPE__CURVETO; - pe->p[0].x = p0->x; - pe->p[0].y = p0->y; - pe->p[1].x = p1->x; - pe->p[1].y = p1->y; - pe->p[2].x = cp->x = p2->x; - pe->p[2].y = cp->y = p2->y; - } - - return 0; -} - -#if 0 -#define QB_TWO_THIRD (2.0/3.0) -#define QB_ONE_THIRD (1.0/3.0) - -static int -pdf_path__curveto_QB (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *p0, - const pdf_coord *p1 - ) -{ - pdf_coord q0, q1; - - q0.x = cp->x + QB_TWO_THIRD * (p0->x - cp->x); - q0.y = cp->y + QB_TWO_THIRD * (p0->y - cp->y); - q1.x = p0->x + QB_ONE_THIRD * (p1->x - p0->x); - q1.y = p0->y + QB_ONE_THIRD * (p1->y - p0->y); - /* q2 == p1 */ - - return pdf_path__curveto(pa, cp, &q0, &q1, p1); -} -#endif - - -/* This isn't specified as cp to somewhere. */ -static int -pdf_path__elliptarc (pdf_path *pa, - pdf_coord *cp, - const pdf_coord *ca, /* ellipsis center */ - double r_x, /* x radius */ - double r_y, /* y radius */ - double xar, /* x-axis-rotation (deg!) */ - double a_0, /* start angle */ - double a_1, /* stop angle */ - int a_d /* arc orientation */ - ) -{ - double b, b_x, b_y; - double d_a, q; - pdf_coord p0, p1, p2, p3; - pdf_coord e0, e1; - pdf_tmatrix T; - int n_c; /* number of segments */ - int i, error = 0; - - if (fabs(r_x) < 1.e-8 || - fabs(r_y) < 1.e-8) - return -1; - - if (a_d < 0) { - for ( ; a_1 > a_0; a_1 -= 360.0); - } else { - for ( ; a_1 < a_0; a_0 -= 360.0); - } - - d_a = a_1 - a_0; - for (n_c = 1; fabs(d_a) > 90.0 * n_c; n_c++); - d_a /= n_c; - if (fabs(d_a) < 1.e-8) - return -1; - - a_0 *= M_PI / 180.0; - a_1 *= M_PI / 180.0; - d_a *= M_PI / 180.0; - xar *= M_PI / 180.0; - T.a = cos(xar); T.c = -sin(xar); - T.b = -T.c ; T.d = T.a; - T.e = 0.0 ; T.f = 0.0; - - /* A parameter that controls cb-curve (off-curve) points */ - b = 4.0 * (1.0 - cos(.5 * d_a)) / (3.0 * sin(.5 * d_a)); - b_x = r_x * b; - b_y = r_y * b; - - p0.x = r_x * cos(a_0); - p0.y = r_y * sin(a_0); - pdf_coord__transform(&p0, &T); - p0.x += ca->x; p0.y += ca->y; - if (PA_LENGTH(pa) == 0) { - pdf_path__moveto(pa, cp, &p0); - } else if (!COORD_EQUAL(cp, &p0)) { - pdf_path__lineto(pa, cp, &p0); /* add line seg */ - } - for (i = 0; !error && i < n_c; i++) { - q = a_0 + i * d_a; - e0.x = cos(q); e0.y = sin(q); - e1.x = cos(q + d_a); e1.y = sin(q + d_a); - - /* Condition for tangent vector requirs - * d1 = p1 - p0 = f ( sin a, -cos a) - * d2 = p2 - p3 = g ( sin b, -cos b) - * and from symmetry - * g^2 = f^2 - */ - p0.x = r_x * e0.x; /* s.p. */ - p0.y = r_y * e0.y; - p3.x = r_x * e1.x; /* e.p. */ - p3.y = r_y * e1.y; - - p1.x = -b_x * e0.y; - p1.y = b_y * e0.x; - p2.x = b_x * e1.y; - p2.y = -b_y * e1.x; - - pdf_coord__transform(&p0, &T); - pdf_coord__transform(&p1, &T); - pdf_coord__transform(&p2, &T); - pdf_coord__transform(&p3, &T); - p0.x += ca->x; p0.y += ca->y; - p3.x += ca->x; p3.y += ca->y; - p1.x += p0.x ; p1.y += p0.y ; - p2.x += p3.x ; p2.y += p3.y ; - - error = pdf_path__curveto(pa, &p0, &p1, &p2, &p3); - cp->x = p3.x; cp->y = p3.y; - } - - return error; -} - -static int -pdf_path__closepath (pdf_path *pa, pdf_coord *cp /* no arg */) -{ - pa_elem *pe = NULL; - int i; - - /* search for start point of the last subpath */ - for (i = PA_LENGTH(pa) - 1; i >= 0; i--) { - pe = &pa->path[i]; - if (pe->type == PE_TYPE__MOVETO) - break; - } - - if (!pe || i < 0) - return -1; /* No path or no start point(!) */ - - cp->x = pe->p[0].x; - cp->y = pe->p[0].y; - - pdf_path__growpath(pa, PA_LENGTH(pa) + 1); - - /* NOTE: - * Manually closed path without closepath is not - * affected by linejoin. A path with coincidental - * starting and ending point is not the same as - * 'closed' path. - */ - pe = &pa->path[pa->num_paths++]; - pe->type = PE_TYPE__CLOSEPATH; - - return 0; -} - -/* - * x y width height re - * - * is equivalent to - * - * x y m - * (x + width) y l - * (x + width) (y + height) l - * x (y + height) l - * h - */ -/* Just for quick test */ -static /* __inline__ */ int -pdf_path__isarect (pdf_path *pa, - int f_ir /* fill-rule is ignorable */ - ) -{ - pa_elem *pe0, *pe1, *pe2, *pe3, *pe4; - - if (PA_LENGTH(pa) == 5) { - pe0 = &(pa->path[0]); - pe1 = &(pa->path[1]); - pe2 = &(pa->path[2]); - pe3 = &(pa->path[3]); - pe4 = &(pa->path[4]); - if (pe0->type == PE_TYPE__MOVETO && - pe1->type == PE_TYPE__LINETO && - pe2->type == PE_TYPE__LINETO && - pe3->type == PE_TYPE__LINETO && - pe4->type == PE_TYPE__CLOSEPATH) { - if (pe1->p[0].y - pe0->p[0].y == 0 && - pe2->p[0].x - pe1->p[0].x == 0 && - pe3->p[0].y - pe2->p[0].y == 0) { - if (pe1->p[0].x - pe0->p[0].x - == pe2->p[0].x - pe3->p[0].x) { - return 1; - } - /* Winding number is different but ignore it here. */ - } else if (f_ir && - pe1->p[0].x - pe0->p[0].x == 0 && - pe2->p[0].y - pe1->p[0].y == 0 && - pe3->p[0].x - pe2->p[0].x == 0) { - if (pe1->p[0].y - pe0->p[0].y - == pe2->p[0].y - pe3->p[0].y) { - return 1; - } - } - } - } - - return 0; -} - -/* Path Painting */ -/* F is obsoleted */ -#define PT_OP_VALID(c) ( \ - (c) == 'f' || (c) == 'F' || \ - (c) == 's' || (c) == 'S' || \ - (c) == 'b' || (c) == 'B' || \ - (c) == 'W' || (c) == ' ' \ -) - -static /* __inline__ */ int -INVERTIBLE_MATRIX (const pdf_tmatrix *M) -{ - if (fabs(detP(M)) < 1.e-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; - } - return 0; -} - -/* rectfill, rectstroke, rectclip, recteoclip - * - * Draw isolated rectangle without actually doing - * gsave/grestore operation. - * - * TODO: - * linestyle, fill-opacity, stroke-opacity,.... - * As this routine draw a single graphics object - * each time, there should be options for specifying - * various drawing styles, which might inherite - * current graphcs state parameter. - */ -static int -pdf_dev__rectshape (pdf_dev *P, - const pdf_rect *r, - const pdf_tmatrix *M, - char opchr - ) -{ - char *buf = FORMAT_BUFF_PTR(P); - int len = 0; - int isclip = 0; - pdf_coord p; - double wd, ht; - - ASSERT(r && PT_OP_VALID(opchr)); - - isclip = (opchr == 'W' || opchr == ' ') ? 1 : 0; - - /* disallow matrix for clipping. - * q ... clip Q does nothing and - * n M cm ... clip n alter CTM. - */ - if (M && (isclip || - !INVERTIBLE_MATRIX(M))) - return -1; - - graphics_mode(); - - buf[len++] = ' '; - if (!isclip) { - buf[len++] = 'q'; - if (M) { - buf[len++] = ' '; - len += pdf_sprint_matrix(buf + len, M); - buf[len++] = ' '; - buf[len++] = 'c'; buf[len++] = 'm'; - } - buf[len++] = ' '; - } - buf[len++] = 'n'; - - p.x = r->llx; p.y = r->lly; - wd = r->urx - r->llx; - ht = r->ury - r->lly; - buf[len++] = ' '; - len += pdf_sprint_coord (buf + len, &p); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, wd); - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, ht); - buf[len++] = ' '; - buf[len++] = 'r'; buf[len++] = 'e'; - - if (opchr != ' ') { - buf[len++] = ' '; - buf[len++] = opchr; - - buf[len++] = ' '; - buf[len++] = isclip ? 'n' : 'Q'; - } - - pdf_doc_add_page_content(buf, len); /* op: q cm n re Q */ - - return 0; -} - -static int path_added = 0; - -/* FIXME */ -static int -pdf_dev__flushpath (pdf_dev *P, - pdf_path *pa, - char opchr, - int rule, - int ignore_rule) -{ - pa_elem *pe, *pe1; - char *b = FORMAT_BUFF_PTR(P); - long b_len = FORMAT_BUFF_LEN(P); - pdf_rect r; /* FIXME */ - pdf_coord *pt; - int n_pts, n_seg; - int len = 0; - int isclip = 0; - int isrect, i, j; - - ASSERT(pa && PT_OP_VALID(opchr)); - - 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) { - pe = &(pa->path[0]); - pe1 = &(pa->path[2]); - - r.llx = pe->p[0].x; - r.lly = pe->p[0].y; - r.urx = pe1->p[0].x - pe->p[0].x; /* width... */ - r.ury = pe1->p[0].y - pe->p[0].y; /* height... */ - - b[len++] = ' '; - len += pdf_sprint_rect(b + len, &r); - b[len++] = ' '; - b[len++] = 'r'; - b[len++] = 'e'; - pdf_doc_add_page_content(b, len); /* op: re */ - len = 0; - } else { - n_seg = PA_LENGTH(pa); - for (i = 0, len = 0, pe = &pa->path[0]; - i < n_seg; pe++, i++) { - n_pts = PE_N_PTS(pe); - for (j = 0, pt = &pe->p[0]; - j < n_pts; j++, pt++) { - b[len++] = ' '; - len += pdf_sprint_coord(b + len, pt); - } - b[len++] = ' '; - b[len++] = PE_OPCHR(pe); - if (len + 128 > b_len) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - if (len > 0) { - pdf_doc_add_page_content(b, len); /* op: m l c v y h */ - len = 0; - } - } - - b[len++] = ' '; - 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); /* op: f F s S b B W f* F* s* S* b* B* W* */ - - return 0; -} - - -/* Graphics State */ -typedef struct pdf_gstate_ -{ - pdf_coord cp; - - pdf_tmatrix matrix; /* cm, - */ - - pdf_color strokecolor; - pdf_color fillcolor; - /* colorspace here */ - - struct { - int num_dash; - double pattern[PDF_DASH_SIZE_MAX]; - double offset; - } linedash; /* d, D */ - - double linewidth; /* w, LW */ - - int linecap; /* J, LC */ - int linejoin; /* j, LJ */ - double miterlimit; /* M, ML */ - - int flatness; /* i, FL, 0 to 100 (0 for use device-default) */ - - /* internal */ - pdf_path path; - long flags; - /* bookkeeping the origin of the last transform applied */ - pdf_coord pt_fixee; -} pdf_gstate; - - -typedef struct m_stack_elem -{ - void *data; - struct m_stack_elem *prev; -} m_stack_elem; - -typedef struct m_stack -{ - int size; - m_stack_elem *top; - m_stack_elem *bottom; -} m_stack; - -static void -m_stack_init (m_stack *stack) -{ - ASSERT(stack); - - stack->size = 0; - stack->top = NULL; - stack->bottom = NULL; - - return; -} - -static void -m_stack_push (m_stack *stack, void *data) -{ - m_stack_elem *elem; - - ASSERT(stack); - - elem = NEW(1, m_stack_elem); - elem->prev = stack->top; - elem->data = data; - - stack->top = elem; - if (stack->size == 0) - stack->bottom = elem; - - stack->size++; - - return; -} - -static void * -m_stack_pop (m_stack *stack) -{ - m_stack_elem *elem; - void *data; - - ASSERT(stack); - - if (stack->size == 0) - return NULL; - - data = stack->top->data; - elem = stack->top; - stack->top = elem->prev; - if (stack->size == 1) - stack->bottom = NULL; - RELEASE(elem); - - stack->size--; - - return data; -} - -static void * -m_stack_top (m_stack *stack) -{ - void *data; - - ASSERT(stack); - - if (stack->size == 0) - return NULL; - - data = stack->top->data; - - return data; -} - -#define m_stack_depth(s) ((s)->size) - -static m_stack gs_stack; - -static void -init_a_gstate (pdf_gstate *gs) -{ - gs->cp.x = 0.0; - gs->cp.y = 0.0; - - pdf_setmatrix(&gs->matrix, 1.0, 0.0, 0.0, 1.0, 0.0, 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; - gs->linecap = 0; - gs->linejoin = 0; - gs->linewidth = 1.0; - gs->miterlimit = 10.0; - - gs->flatness = 1; /* default to 1 in PDF */ - - /* Internal variables */ - gs->flags = 0; - init_a_path(&gs->path); - gs->pt_fixee.x = 0; - gs->pt_fixee.y = 0; - - return; -} - -static void -clear_a_gstate (pdf_gstate *gs) -{ - clear_a_path(&gs->path); - memset(gs, 0, sizeof(pdf_gstate)); - - return; -} - -static void -copy_a_gstate (pdf_gstate *gs1, pdf_gstate *gs2) -{ - int i; - - ASSERT(gs1 && gs2); - - gs1->cp.x = gs2->cp.x; - gs1->cp.y = gs2->cp.y; - - pdf_copymatrix(&gs1->matrix, &gs2->matrix); - - /* TODO: - * Path should be linked list and gsave only - * record starting point within path rather than - * copying whole path. - */ - pdf_path__copypath(&gs1->path, &gs2->path); - - gs1->linedash.num_dash = gs2->linedash.num_dash; - for (i = 0; i < gs2->linedash.num_dash; i++) { - gs1->linedash.pattern[i] = gs2->linedash.pattern[i]; - } - gs1->linedash.offset = gs2->linedash.offset; - - gs1->linecap = gs2->linecap; - gs1->linejoin = gs2->linejoin; - gs1->linewidth = gs2->linewidth; - gs1->miterlimit = gs2->miterlimit; - gs1->flatness = gs2->flatness; - - 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; -} - -void -pdf_dev_init_gstates (void) -{ - pdf_gstate *gs; - - m_stack_init(&gs_stack); - - gs = NEW(1, pdf_gstate); - init_a_gstate(gs); - - m_stack_push(&gs_stack, gs); /* Initial state */ - - return; -} - -void -pdf_dev_clear_gstates (void) -{ - pdf_gstate *gs; - - 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(&gs_stack)) != NULL) { - clear_a_gstate(gs); - RELEASE(gs); - } - return; -} - -int -pdf_dev_gsave (void) -{ - pdf_gstate *gs0, *gs1; - pdf_color *sc, *fc; - - 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_doc_add_page_content(" q", 2); /* op: q */ - - return 0; -} - -int -pdf_dev_grestore (void) -{ - pdf_gstate *gs; - - if (m_stack_depth(&gs_stack) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = m_stack_pop(&gs_stack); - clear_a_gstate(gs); - RELEASE(gs); - - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - - pdf_dev_reset_fonts(); - - return 0; -} - - -int -pdf_dev_push_gstate (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs0; - - gs0 = NEW(1, pdf_gstate); - - init_a_gstate(gs0); - - m_stack_push(gss, gs0); - - return 0; -} - - -int -pdf_dev_pop_gstate (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs; - - if (m_stack_depth(gss) <= 1) { /* Initial state at bottom */ - WARN("Too many grestores."); - return -1; - } - - gs = m_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - - return 0; -} - - -int -pdf_dev_current_depth (void) -{ - return (m_stack_depth(&gs_stack) - 1); /* 0 means initial state */ -} - -void -pdf_dev_grestore_to (int depth) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs; - - ASSERT(depth >= 0); - - if (m_stack_depth(gss) > depth + 1) { - WARN("Closing pending transformations at end of page/XObject."); - } - - while (m_stack_depth(gss) > depth + 1) { - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - gs = m_stack_pop(gss); - clear_a_gstate(gs); - RELEASE(gs); - } - pdf_dev_reset_fonts(); - - return; -} - -int -pdf_dev_currentpoint (pdf_coord *p) -{ - m_stack *gss = &gs_stack; - 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 = &gs_stack; - 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) -{ - 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 */ - -#ifndef XETEX -/* - * mask == 0 means stroking color, mask == 0x20 nonstroking color - * - * force == 1 means that operators will be generated even if - * the color is the same as the current graphics state color - */ -void -pdf_dev_set_color (const pdf_color *color, char mask, int force) -{ - int len; - - pdf_gstate *gs = m_stack_top(&gs_stack); - pdf_color *current = mask ? &gs->fillcolor : &gs->strokecolor; - - ASSERT(pdf_color_is_valid(color)); - - if (!(pdf_dev_get_param(PDF_DEV_PARAM_COLORMODE) && - (force || pdf_color_compare(color, current)))) - /* If "color" is already the current color, then do nothing - * unless a color operator is forced - */ - return; - - graphics_mode(); - len = pdf_color_to_string(color, fmt_buf); - fmt_buf[len++] = ' '; - switch (pdf_color_type(color)) { - case PDF_COLORSPACE_TYPE_RGB: - fmt_buf[len++] = 'R' | mask; - fmt_buf[len++] = 'G' | mask; - break; - case PDF_COLORSPACE_TYPE_CMYK: - fmt_buf[len++] = 'K' | mask; - break; - case PDF_COLORSPACE_TYPE_GRAY: - fmt_buf[len++] = 'G' | mask; - break; - default: /* already verified the given color */ - break; - } - pdf_doc_add_page_content(fmt_buf, len); /* op: RG K G rg k g */ - - pdf_color_copycolor(current, color); -} - -void -pdf_dev_reset_color (int force) -{ - pdf_color *sc, *fc; - - pdf_color_get_current(&sc, &fc); - pdf_dev_set_color(sc, 0, force); - pdf_dev_set_color(fc, 0x20, force); -} -#endif - -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); /* op: cm */ - - pdf_concatmatrix(CTM, M); - } - inversematrix(&W, M); - - pdf_path__transform (cpa, &W); - pdf_coord__transform(cpt, &W); - - return 0; -} - -/* - * num w LW linewidth (g.t. 0) - * int J LC linecap - * int j LJ linejoin - * num M ML miter limit (g.t. 0) - * array num d D line dash - * int ri RI renderint intnet - * int i FL flatness tolerance (0-100) - * name gs -- name: res. name of ExtGState dict. - */ -int -pdf_dev_setmiterlimit (double mlimit) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->miterlimit != mlimit) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, mlimit); - buf[len++] = ' '; - buf[len++] = 'M'; - pdf_doc_add_page_content(buf, len); /* op: M */ - gs->miterlimit = mlimit; - } - - return 0; -} - -int -pdf_dev_setlinecap (int capstyle) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linecap != capstyle) { - len = sprintf(buf, " %d J", capstyle); - pdf_doc_add_page_content(buf, len); /* op: J */ - gs->linecap = capstyle; - } - - return 0; -} - -int -pdf_dev_setlinejoin (int joinstyle) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linejoin != joinstyle) { - len = sprintf(buf, " %d j", joinstyle); - pdf_doc_add_page_content(buf, len); /* op: j */ - gs->linejoin = joinstyle; - } - - return 0; -} - -int -pdf_dev_setlinewidth (double width) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (gs->linewidth != width) { - buf[len++] = ' '; - len += pdf_sprint_length(buf + len, width); - buf[len++] = ' '; - buf[len++] = 'w'; - pdf_doc_add_page_content(buf, len); /* op: w */ - gs->linewidth = width; - } - - return 0; -} - -int -pdf_dev_setdash (int count, double *pattern, double offset) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - int i; - - gs->linedash.num_dash = count; - gs->linedash.offset = offset; - pdf_doc_add_page_content(" [", 2); /* op: */ - for (i = 0; i < count; i++) { - buf[0] = ' '; - len = pdf_sprint_length (buf + 1, pattern[i]); - pdf_doc_add_page_content(buf, len + 1); /* op: */ - gs->linedash.pattern[i] = pattern[i]; - } - pdf_doc_add_page_content("] ", 2); /* op: */ - len = pdf_sprint_length (buf, offset); - pdf_doc_add_page_content(buf, len); /* op: */ - pdf_doc_add_page_content(" d", 2); /* op: d */ - - return 0; -} - -#if 0 -int -pdf_dev_setflat (int flatness) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - int len = 0; - char *buf = FORMAT_BUFF_PTR(NULL); - - if (flatness < 0 || flatness > 100) - return -1; - - if (gs->flatness != flatness) { - gs->flatness = flatness; - len = sprintf(buf, " %d i", flatness); - pdf_doc_add_page_content(buf, len); /* op: i */ - } - - return 0; -} -#endif - -/* ZSYUEDVEDEOF */ -int -pdf_dev_clip (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_NONZERO, 0); -} - -int -pdf_dev_eoclip (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - - return pdf_dev__flushpath(NULL, cpa, 'W', PDF_FILL_RULE_EVENODD, 0); -} - -int -pdf_dev_flushpath (char p_op, int fill_rule) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - int error = 0; - - /* last arg 'ignore_rule' is only for single object - * that can be converted to a rect where fill rule - * is inessential. - */ - error = pdf_dev__flushpath(NULL, cpa, p_op, fill_rule, 1); - pdf_path__clearpath(cpa); - - gs->flags &= ~GS_FLAG_CURRENTPOINT_SET; - - return error; -} - -int -pdf_dev_newpath (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *p = &gs->path; - - if (PA_LENGTH(p) > 0) { - pdf_path__clearpath (p); - } - /* The following is required for "newpath" operator in mpost.c. */ - pdf_doc_add_page_content(" n", 2); /* op: n */ - - return 0; -} - -int -pdf_dev_moveto (double x, double y) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = x; p.y = y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_rmoveto (double x, double y) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p; - - p.x = cpt->x + x; - p.y = cpt->y + y; - return pdf_path__moveto(cpa, cpt, &p); /* cpt updated */ -} - -int -pdf_dev_lineto (double x, double y) -{ - 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; - - p0.x = x; p0.y = y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_rlineto (double x, double y) -{ - 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; - - p0.x = x + cpt->x; p0.y = y + cpt->y; - - return pdf_path__lineto(cpa, cpt, &p0); -} - -int -pdf_dev_curveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - 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, p2; - - p0.x = x0; p0.y = y0; - p1.x = x1; p1.y = y1; - p2.x = x2; p2.y = y2; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - -#ifdef XETEX -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); -} -#endif - -int -pdf_dev_rcurveto (double x0, double y0, - double x1, double y1, - double x2, double y2) -{ - 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, p2; - - p0.x = x0 + cpt->x; p0.y = y0 + cpt->y; - p1.x = x1 + cpt->x; p1.y = y1 + cpt->y; - p2.x = x2 + cpt->x; p2.y = y2 + cpt->y; - - return pdf_path__curveto(cpa, cpt, &p0, &p1, &p2); -} - - -int -pdf_dev_closepath (void) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_coord *cpt = &gs->cp; - pdf_path *cpa = &gs->path; - - return pdf_path__closepath(cpa, cpt); -} - - -void -pdf_dev_dtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__dtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_idtransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__idtransform(p, (M ? M : CTM)); - - return; -} - -void -pdf_dev_transform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__transform(p, (M ? M : CTM)); - - return; -} - -#if 0 -void -pdf_dev_itransform (pdf_coord *p, const pdf_tmatrix *M) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_tmatrix *CTM = &gs->matrix; - - ASSERT(p); - - pdf_coord__itransform(p, (M ? M : CTM)); - - return; -} -#endif - -int -pdf_dev_arc (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, +1); -} - -/* *negative* arc */ -int -pdf_dev_arcn (double c_x , double c_y, double r, - double a_0 , double a_1) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r, r, 0.0, a_0, a_1, -1); -} - -int -pdf_dev_arcx (double c_x , double c_y, - double r_x , double r_y, - double a_0 , double a_1, - int a_d , - double xar) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord c; - - c.x = c_x; c.y = c_y; - - return pdf_path__elliptarc(cpa, cpt, &c, r_x, r_y, xar, a_0, a_1, a_d); -} - -/* Required by Tpic */ -int -pdf_dev_bspline (double x0, double y0, - double x1, double y1, double x2, double y2) -{ - m_stack *gss = &gs_stack; - pdf_gstate *gs = m_stack_top(gss); - pdf_path *cpa = &gs->path; - pdf_coord *cpt = &gs->cp; - pdf_coord p1, p2, p3; - - p1.x = x0 + 2.0 * (x1 - x0) / 3.0; - p1.y = y0 + 2.0 * (y1 - y0) / 3.0; - p2.x = x1 + (x2 - x1) / 3.0; - p2.y = y1 + (y2 - y1) / 3.0; - p3.x = x2; - p3.y = y2; - - return pdf_path__curveto(cpa, cpt, &p1, &p2, &p3); -} - -#if 0 -int -pdf_dev_rectstroke (double x, double y, - double w, double h, - const pdf_tmatrix *M /* optional */ - ) -{ - pdf_rect r; - - r.llx = x; - r.lly = y; - r.urx = x + w; - r.ury = y + h; - - return pdf_dev__rectshape(NULL, &r, M, 'S'); -} -#endif - -int -pdf_dev_rectfill (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; - - return pdf_dev__rectshape(NULL, &r, NULL, 'f'); -} - -int -pdf_dev_rectclip (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; - - return pdf_dev__rectshape(NULL, &r, NULL, 'W'); -} - -#ifdef XETEX -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; -} -#endif diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfnames.c b/Build/source/texk/dvipdfm-x/xsrc/pdfnames.c deleted file mode 100644 index c898dedfb31..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfnames.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "numbers.h" - -/* Hash */ -#include "dpxutil.h" - -#include "pdfobj.h" - -#include "pdfnames.h" - -struct obj_data -{ - pdf_obj *object_ref; - pdf_obj *object; - int reserve; /* 1 if object is not actually defined. */ -}; - -char * -printable_key (const char *key, int keylen) -{ -#define MAX_KEY 32 - static char pkey[MAX_KEY+4]; - int i, len; - unsigned char hi, lo; - - for (i = 0, len = 0; - i < keylen && len < MAX_KEY; i++) { - if (isprint(key[i])) { - pkey[len++] = key[i]; - } else { - hi = (key[i] >> 4) & 0xff; - lo = key[i] & 0xff; - pkey[len++] = '#'; - pkey[len++] = (hi < 10) ? hi + '0' : (hi - 10) + 'A'; - pkey[len++] = (lo < 10) ? lo + '0' : (lo - 10) + 'A'; - } - } - pkey[len] = '\0'; - - return (char *) pkey; -} - -#ifdef XETEX -static void -flush_objects (struct ht_table *ht_tab) -{ - struct ht_iter iter; - - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - if (value->reserve) { - WARN("Unresolved object reference \"%s\" found!!!", - printable_key(key, keylen)); - } - if (value->object) { - pdf_release_obj(value->object); - } - if (value->object_ref) { - pdf_release_obj(value->object_ref); - } - value->object = NULL; - value->object_ref = NULL; - value->reserve = 0; - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } -} -#endif - -static void CDECL -hval_free (void *hval) -{ - struct obj_data *value; - - value = (struct obj_data *) hval; - if (value->object) - pdf_release_obj(value->object); - if (value->object_ref) - pdf_release_obj(value->object_ref); - - value->object = NULL; - value->object_ref = NULL; - value->reserve = 0; - - RELEASE(value); - - return; -} - -struct ht_table * -pdf_new_name_tree (void) -{ - struct ht_table *names; - - names = NEW(1, struct ht_table); - ht_init_table(names, hval_free); - - return names; -} - -#ifndef XETEX -static void -check_objects_defined (struct ht_table *ht_tab) -{ - struct ht_iter iter; - - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - ASSERT(value->object); - if (PDF_OBJ_UNDEFINED(value->object)) { - pdf_names_add_object(ht_tab, key, keylen, pdf_new_null()); - WARN("Object @%s used, but not defined. Replaced by null.", - printable_key(key, keylen)); - } - } while (ht_iter_next(&iter) >= 0); - ht_clear_iter(&iter); - } -} -#endif - -void -pdf_delete_name_tree (struct ht_table **names) -{ - ASSERT(names && *names); - - flush_objects (*names); - ht_clear_table(*names); - RELEASE(*names); - *names = NULL; -} - -int -pdf_names_add_object (struct ht_table *names, - const void *key, int keylen, pdf_obj *object) -{ - struct obj_data *value; - - ASSERT(names && object); - - if (!key || keylen < 1) { - WARN("Null string used for name tree key."); - return -1; - } - - value = ht_lookup_table(names, key, keylen); - if (!value) { - value = NEW(1, struct obj_data); - value->object = object; - value->object_ref = NULL; - value->reserve = 0; - ht_append_table(names, key, keylen, value); - } else { - if (value->reserve) { - /* null object is used for undefined objects */ - pdf_copy_object(value->object, object); - pdf_release_obj(object); /* PLEASE FIX THIS!!! */ - } else { - if (value->object || value->object_ref) { - if (pdf_obj_get_verbose()) { - WARN("Object reference with key \"%s\" is in use.", printable_key(key, keylen)); - } - pdf_release_obj(object); - return -1; - } else { - value->object = object; - } - } - value->reserve = 0; - } - - return 0; -} - -#ifdef XETEX -int -pdf_names_add_reference (struct ht_table *names, - const void *key, int keylen, pdf_obj *object_ref) -{ - struct obj_data *value; - - ASSERT(names); - - if (!PDF_OBJ_INDIRECTTYPE(object_ref)) { - WARN("Invalid type: @%s is not reference...", - printable_key(key, keylen)); - return -1; - } - - value = ht_lookup_table(names, key, keylen); - if (!value) { - value = NEW(1, struct obj_data); - value->object = NULL; - value->object_ref = object_ref; - value->reserve = 0; - ht_append_table(names, key, keylen, value); - } else { - if (value->object || value->object_ref) { - WARN("Object reference \"%s\" is in use.", - printable_key(key, keylen)); - WARN("Please close it before redefining."); - return -1; - } else { - value->object = NULL; - value->object_ref = object_ref; - } - value->reserve = 0; - } - - return 0; -} -#endif - -/* - * The following routine returns copies, not the original object. - */ -pdf_obj * -pdf_names_lookup_reference (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - /* Reserve object label */ - if (!value) { - value = NEW(1, struct obj_data); - value->object = pdf_new_null(); /* dummy */ - value->object_ref = NULL; - value->reserve = 1; - ht_append_table(names, key, keylen, value); - } - - if (!value->object_ref) { - if (value->object) - value->object_ref = pdf_ref_obj(value->object); - else { - WARN("Object @%s not defined or already closed.", - printable_key(key, keylen)); - } - } - - return pdf_link_obj(value->object_ref); -} - -pdf_obj * -pdf_names_lookup_object (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - if (!value) - return NULL; - else if (!value->object) { - WARN("Object @%s not defined or already closed.", - printable_key(key, keylen)); - } - - return value->object; -} - -int -pdf_names_close_object (struct ht_table *names, - const void *key, int keylen) -{ - struct obj_data *value; - - ASSERT(names); - - value = ht_lookup_table(names, key, keylen); - if (!value) { - WARN("Tried to release nonexistent reference: %s", - printable_key(key, keylen)); - return -1; - } - - if (value->object) { - pdf_release_obj(value->object); - value->object = NULL; - } else { - WARN("Trying to close object @%s twice?", - printable_key(key, keylen)); - return -1; - } - - return 0; -} - -struct named_object -{ - char *key; - int keylen; - pdf_obj *value; -}; - -static int CDECL -cmp_key (const void *d1, const void *d2) -{ - const struct named_object *sd1, *sd2; - int keylen, cmp; - - sd1 = (const struct named_object *) d1; - sd2 = (const struct named_object *) d2; - - if (!sd1->key) - cmp = -1; - else if (!sd2->key) - cmp = 1; - else { - keylen = MIN(sd1->keylen, sd2->keylen); - cmp = memcmp(sd1->key, sd2->key, keylen); - if (!cmp) { - cmp = sd1->keylen - sd2->keylen; - } - } - - return cmp; -} - -#define NAME_CLUSTER 4 -static pdf_obj * -build_name_tree (struct named_object *first, long num_leaves, int is_root) -{ - pdf_obj *result; - int i; - - result = pdf_new_dict(); - /* - * According to PDF Refrence, Third Edition (p.101-102), a name tree - * always has exactly one root node, which contains a SINGLE entry: - * either Kids or Names but not both. If the root node has a Names - * entry, it is the only node in the tree. If it has a Kids entry, - * then each of the remaining nodes is either an intermediate node, - * containing a Limits entry and a Kids entry, or a leaf node, - * containing a Limits entry and a Names entry. - */ - if (!is_root) { - struct named_object *last; - pdf_obj *limits; - - limits = pdf_new_array(); - last = &first[num_leaves - 1]; - pdf_add_array(limits, pdf_new_string(first->key, first->keylen)); - pdf_add_array(limits, pdf_new_string(last->key , last->keylen )); - pdf_add_dict (result, pdf_new_name("Limits"), limits); - } - - if (num_leaves > 0 && - num_leaves <= 2 * NAME_CLUSTER) { - pdf_obj *names; - - /* Create leaf nodes. */ - names = pdf_new_array(); - for (i = 0; i < num_leaves; i++) { - struct named_object *cur; - - cur = &first[i]; - pdf_add_array(names, pdf_new_string(cur->key, cur->keylen)); - switch (PDF_OBJ_TYPEOF(cur->value)) { - case PDF_ARRAY: - case PDF_DICT: - case PDF_STREAM: - case PDF_STRING: - pdf_add_array(names, pdf_ref_obj(cur->value)); - break; - case PDF_OBJ_INVALID: - ERROR("Invalid object...: %s", printable_key(cur->key, cur->keylen)); - break; - default: - pdf_add_array(names, pdf_link_obj(cur->value)); - break; - } - pdf_release_obj(cur->value); - cur->value = NULL; - } - pdf_add_dict(result, pdf_new_name("Names"), names); - } else if (num_leaves > 0) { - pdf_obj *kids; - - /* Intermediate node */ - kids = pdf_new_array(); - for (i = 0; i < NAME_CLUSTER; i++) { - pdf_obj *subtree; - long start, end; - - start = (i*num_leaves) / NAME_CLUSTER; - end = ((i+1)*num_leaves) / NAME_CLUSTER; - subtree = build_name_tree(&first[start], (end - start), 0); - pdf_add_array (kids, pdf_ref_obj(subtree)); - pdf_release_obj(subtree); - } - pdf_add_dict(result, pdf_new_name("Kids"), kids); - } - - return result; -} - -static struct named_object * -flat_table (struct ht_table *ht_tab, long *num_entries, - struct ht_table *filter) -{ - struct named_object *objects; - struct ht_iter iter; - long count; - - ASSERT(ht_tab); - - *num_entries = count = ht_tab->count; - objects = NEW(count, struct named_object); - if (ht_set_iter(ht_tab, &iter) >= 0) { - do { - char *key; - int keylen; - struct obj_data *value; - - count--; - key = ht_iter_getkey(&iter, &keylen); - value = ht_iter_getval(&iter); - if (value->reserve) { - WARN("Named object \"%s\" not defined!!!", - printable_key(key, keylen)); - WARN("Replacing with null."); - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_new_null(); - } else if (value->object_ref) { - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_link_obj(value->object_ref); - } else if (value->object) { - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_link_obj(value->object); - } else { - WARN("Named object \"%s\" not defined!!!", - printable_key(key, keylen)); - WARN("Replacing with null."); - objects[count].key = (char *) key; - objects[count].keylen = keylen; - objects[count].value = pdf_new_null(); - } - } while (ht_iter_next(&iter) >= 0 && count > 0); - ht_clear_iter(&iter); - } - - return objects; -} - -pdf_obj * -pdf_names_create_tree (struct ht_table *names, long *count, - struct ht_table *filter) -{ - pdf_obj *name_tree; - struct named_object *flat; - - flat = flat_table(names, count, filter); - if (!flat) - name_tree = NULL; - else { - if (*count < 1) - name_tree = NULL; - else { - qsort(flat, *count, sizeof(struct named_object), cmp_key); - name_tree = build_name_tree(flat, *count, 1); - } - RELEASE(flat); - } - - return name_tree; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfobj.c b/Build/source/texk/dvipdfm-x/xsrc/pdfobj.c deleted file mode 100644 index 3f97ee28928..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfobj.c +++ /dev/null @@ -1,3244 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "dpxutil.h" -#include "pdflimits.h" -#include "pdfencrypt.h" -#include "pdfparse.h" - -#ifdef HAVE_ZLIB -#include -#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 -{ - int type; - - unsigned long label; /* Only used for indirect objects - 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; -}; - -struct pdf_boolean -{ - char value; -}; - -struct pdf_number -{ - double value; -}; - -struct pdf_string -{ - unsigned char *string; - unsigned short length; -}; - -struct pdf_name -{ - char *name; -}; - -struct pdf_array -{ - unsigned long max; - unsigned long size; - struct pdf_obj **values; -}; - -struct pdf_dict -{ - struct pdf_obj *key; - struct pdf_obj *value; - struct pdf_dict *next; -}; - -struct pdf_stream -{ - struct pdf_obj *dict; - unsigned char *stream; - long *objstm_data; /* used for object streams */ - unsigned long stream_length; - unsigned long max_length; - unsigned char _flags; -}; - -struct pdf_indirect -{ - pdf_file *pf; - unsigned long label; - unsigned short generation; -}; - -typedef void pdf_null; -typedef struct pdf_boolean pdf_boolean; -typedef struct pdf_number pdf_number; -typedef struct pdf_string pdf_string; -typedef struct pdf_name pdf_name; -typedef struct pdf_array pdf_array; -typedef struct pdf_dict pdf_dict; -typedef struct pdf_stream pdf_stream; -typedef struct pdf_indirect pdf_indirect; - -static FILE *pdf_output_file = NULL; - -static long pdf_output_file_position = 0; -static long pdf_output_line_position = 0; -static long compression_saved = 0; - -#define FORMAT_BUF_SIZE 4096 -static char format_buffer[FORMAT_BUF_SIZE]; - -typedef struct xref_entry -{ - unsigned char type; /* object storage type */ - unsigned long field2; /* offset in file or object stream */ - unsigned short field3; /* generation or index */ - pdf_obj *direct; /* used for imported objects */ - pdf_obj *indirect; /* used for imported objects */ -} xref_entry; - -static xref_entry *output_xref; - -static unsigned long pdf_max_ind_objects; -static unsigned long next_label; - -static unsigned long startxref; - -struct pdf_file -{ - FILE *file; - pdf_obj *trailer; - xref_entry *xref_table; - pdf_obj *catalog; - long num_obj; - long file_size; - int version; -}; - -static pdf_obj *output_stream; - -#define OBJSTM_MAX_OBJS 200 -/* the limit is only 100 for linearized PDF */ - -static int enc_mode; -static int doc_enc_mode; - -static pdf_obj *trailer_dict; -static pdf_obj *xref_stream; - -/* Internal static routines */ - -static int check_for_pdf_version (FILE *file); - -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 set_objstm_data (pdf_obj *objstm, long *data); -static long *get_objstm_data (pdf_obj *objstm); -static void release_objstm (pdf_obj *objstm); - -static void pdf_out_char (FILE *file, char c); -static void pdf_out (FILE *file, const void *buffer, long length); - -static void release_indirect (pdf_indirect *data); -static void write_indirect (pdf_indirect *indirect, FILE *file); - -static void release_boolean (pdf_obj *data); -static void write_boolean (pdf_boolean *data, FILE *file); - -static void release_null (pdf_null *data); -static void write_null (pdf_null *data, FILE *file); - -static void release_number (pdf_number *number); -static void write_number (pdf_number *number, FILE *file); - -static void write_string (pdf_string *str, FILE *file); -static void release_string (pdf_string *str); - -static void write_name (pdf_name *name, FILE *file); -static void release_name (pdf_name *name); - -static void write_array (pdf_array *array, FILE *file); -static void release_array (pdf_array *array); - -static void write_dict (pdf_dict *dict, FILE *file); -static void release_dict (pdf_dict *dict); - -static void write_stream (pdf_stream *stream, FILE *file); -static void release_stream (pdf_stream *stream); - -static int verbose = 0; -static char compression_level = 9; - -void -pdf_set_compression (int level) -{ -#ifndef HAVE_ZLIB - ERROR("You don't have compression compiled in. Possibly libz wasn't found by configure."); -#else -#ifndef HAVE_ZLIB_COMPRESS2 - if (level != 0) - WARN("Unable to set compression level -- your zlib doesn't have compress2()."); -#endif - if (level >= 0 && level <= 9) - compression_level = level; - else { - ERROR("set_compression: invalid compression level: %d", level); - } -#endif /* !HAVE_ZLIB */ - - return; -} - -static unsigned pdf_version = PDF_VERSION_DEFAULT; - -void -pdf_set_version (unsigned version) -{ - /* Don't forget to update CIDFont_stdcc_def[] in cid.c too! */ - if (version >= PDF_VERSION_MIN && version <= PDF_VERSION_MAX) { - pdf_version = version; - } -} - -unsigned -pdf_get_version (void) -{ - return pdf_version; -} - -int -pdf_obj_get_verbose(void) -{ - return verbose; -} - -void -pdf_obj_set_verbose(void) -{ - verbose++; -} - -static pdf_obj *current_objstm = NULL; -static int do_objstm; - -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, xref_entry); - } - - output_xref[label].type = type; - output_xref[label].field2 = field2; - output_xref[label].field3 = field3; - output_xref[label].direct = NULL; - output_xref[label].indirect = NULL; -} - -#define BINARY_MARKER "%\344\360\355\370\n" -void -pdf_out_init (const char *filename, int do_encryption) -{ - char v; - - 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")); - do_objstm = 1; - } else { - xref_stream = NULL; - trailer_dict = pdf_new_dict(); - do_objstm = 0; - } - - 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); - else - ERROR("Unable to open file."); - } - pdf_out(pdf_output_file, "%PDF-1.", strlen("%PDF-1.")); - v = '0' + pdf_version; - 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_table (void) -{ - long length; - unsigned long i; - - 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); - - /* - * 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. - */ - 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); - } -} - -static void -dump_trailer_dict (void) -{ - pdf_out(pdf_output_file, "trailer\n", 8); - enc_mode = 0; - write_dict(trailer_dict->data, pdf_output_file); - pdf_release_obj(trailer_dict); - pdf_out_char(pdf_output_file, '\n'); -} - -/* - * 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; - - /* 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; - unsigned short f3; - buf[0] = output_xref[i].type; - pos = output_xref[i].field2; - for (j = poslen; j--; ) { - buf[1+j] = (unsigned char) pos; - pos >>= 8; - } - 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_release_obj(xref_stream); -} - -void -pdf_out_flush (void) -{ - if (pdf_output_file) { - long length; - - /* Flush current object stream */ - if (current_objstm) { - release_objstm(current_objstm); - current_objstm =NULL; - } - - /* - * Label xref stream - we need the number of correct objects - * for the xref stream dictionary (= trailer). - * Labelling it in pdf_out_init (with 1) does not work (why?). - */ - if (xref_stream) - pdf_label_obj(xref_stream); - - /* 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 (xref_stream) - 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 saved %ld bytes%s\n", compression_saved, - pdf_version < 5 ? ". Try \"-V 5\" for better compression" : ""); - } - } - MESG("%ld bytes written", pdf_output_file_position); - - MFCLOSE(pdf_output_file); - } -} - -void -pdf_error_cleanup (void) -{ - /* - * This routine is the cleanup required for an abnormal exit. - * For now, simply close the file. - */ - if (pdf_output_file) - MFCLOSE(pdf_output_file); -} - - -void -pdf_set_root (pdf_obj *object) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("Root"), pdf_ref_obj(object))) { - ERROR("Root object already set!"); - } - /* 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_add_dict(trailer_dict, pdf_new_name("Info"), pdf_ref_obj(object))) { - ERROR ("Info object already set!"); - } -} - -void -pdf_set_id (pdf_obj *id) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("ID"), id)) { - ERROR ("ID already set!"); - } -} - -void -pdf_set_encrypt (pdf_obj *encrypt) -{ - if (pdf_add_dict(trailer_dict, pdf_new_name("Encrypt"), pdf_ref_obj(encrypt))) { - ERROR("Encrypt object already set!"); - } - encrypt->flags |= OBJ_NO_ENCRYPT; -} - -static -void pdf_out_char (FILE *file, char c) -{ - 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; - } - } -} - -static char xchar[] = "0123456789abcdef"; - -#define pdf_out_xchar(f,c) do {\ - pdf_out_char((f), xchar[((c) >> 4) & 0x0f]);\ - pdf_out_char((f), xchar[(c) & 0x0f]);\ -} while (0) - -static -void pdf_out (FILE *file, const void *buffer, long length) -{ - 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 && - ((const char *)buffer)[length-1] == '\n') - 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) -{ - if (file == pdf_output_file && pdf_output_line_position >= 80) { - pdf_out_char(file, '\n'); - } else { - pdf_out_char(file, ' '); - } -} - -#define TYPECHECK(o,t) if (!(o) || (o)->type != (t)) {\ - ERROR("typecheck: Invalid object type: %d %d (line %d)", (o) ? (o)->type : -1, (t), __LINE__);\ -} - -#define INVALIDOBJ(o) ((o) == NULL || (o)->type <= 0 || (o)->type > PDF_UNDEFINED) - -static pdf_obj * -pdf_new_obj(int type) -{ - pdf_obj *result; - - if (type >= PDF_UNDEFINED || type < 0) - ERROR("Invalid object type: %d", type); - - result = NEW(1, pdf_obj); - result->type = type; - result->data = NULL; - result->label = 0; - result->generation = 0; - result->refcount = 1; - result->flags = 0; - - return result; -} - -int -pdf_obj_typeof (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - return PDF_OBJ_INVALID; - - return object->type; -} - -static void -pdf_label_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_label_obj(): passed invalid object."); - - /* - * Don't change label on an already labeled object. Ignore such calls. - */ - if (object->label == 0) { - object->label = next_label++; - object->generation = 0; - } -} - -#ifndef XETEX -/* - * Transfer the label assigned to the object src to the object dst. - * The object dst must not yet have been labeled. - */ -void -pdf_transfer_label (pdf_obj *dst, pdf_obj *src) -{ - ASSERT(dst && !dst->label && src); - - dst->label = src->label; - dst->generation = src->generation; - src->label = 0; - src->generation = 0; -} -#endif - -/* - * This doesn't really copy the object, but allows it to be used without - * fear that somebody else will free it. - */ -pdf_obj * -pdf_link_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_link_obj(): passed invalid object."); - - object->refcount += 1; - - return object; -} - - -pdf_obj * -pdf_ref_obj (pdf_obj *object) -{ - if (INVALIDOBJ(object)) - ERROR("pdf_ref_obj(): passed invalid object."); - - if (object->refcount == 0) { - MESG("\nTrying to refer already released object!!!\n"); - pdf_write_obj(object, stderr); - ERROR("Cannot continue..."); - } - - if (PDF_OBJ_INDIRECTTYPE(object)) { - return pdf_link_obj(object); - } else { - if (object->label == 0) { - pdf_label_obj(object); - } - return pdf_new_indirect(NULL, object->label, object->generation); - } -} - -static void -release_indirect (pdf_indirect *data) -{ - RELEASE(data); -} - -static void -write_indirect (pdf_indirect *indirect, FILE *file) -{ - long length; - - ASSERT(!indirect->pf); - - length = sprintf(format_buffer, "%lu %hu R", indirect->label, indirect->generation); - pdf_out(file, format_buffer, length); -} - -#ifndef XETEX -/* The undefined object is used as a placeholder in pdfnames.c - * for objects which are referenced before they are defined. - */ -pdf_obj * -pdf_new_undefined (void) -{ - pdf_obj *result; - - result = pdf_new_obj(PDF_UNDEFINED); - result->data = NULL; - - return result; -} -#endif - -pdf_obj * -pdf_new_null (void) -{ - pdf_obj *result; - - result = pdf_new_obj(PDF_NULL); - result->data = NULL; - - return result; -} - -static void -release_null (pdf_null *obj) -{ - return; -} - -static void -write_null (pdf_null *obj, FILE *file) -{ - pdf_out(file, "null", 4); -} - -pdf_obj * -pdf_new_boolean (char value) -{ - pdf_obj *result; - pdf_boolean *data; - - result = pdf_new_obj(PDF_BOOLEAN); - data = NEW(1, pdf_boolean); - data->value = value; - result->data = data; - - return result; -} - -static void -release_boolean (pdf_obj *data) -{ - RELEASE (data); -} - -static void -write_boolean (pdf_boolean *data, FILE *file) -{ - if (data->value) { - pdf_out(file, "true", 4); - } else { - pdf_out(file, "false", 5); - } -} - -#ifdef XETEX -void -pdf_set_boolean (pdf_obj *object, char value) -{ - pdf_boolean *data; - - TYPECHECK(object, PDF_BOOLEAN); - - data = object->data; - data->value = value; -} -#endif - -char -pdf_boolean_value (pdf_obj *object) -{ - pdf_boolean *data; - - TYPECHECK(object, PDF_BOOLEAN); - - data = object->data; - - return data->value; -} - -pdf_obj * -pdf_new_number (double value) -{ - pdf_obj *result; - pdf_number *data; - - result = pdf_new_obj(PDF_NUMBER); - data = NEW(1, pdf_number); - data->value = value; - result->data = data; - - return result; -} - -static void -release_number (pdf_number *data) -{ - RELEASE (data); -} - -static void -write_number (pdf_number *number, FILE *file) -{ - int count; - - count = pdf_sprint_number(format_buffer, number->value); - - pdf_out(file, format_buffer, count); -} - - -void -pdf_set_number (pdf_obj *object, double value) -{ - pdf_number *data; - - TYPECHECK(object, PDF_NUMBER); - - data = object->data; - data->value = value; -} - -double -pdf_number_value (pdf_obj *object) -{ - pdf_number *data; - - TYPECHECK(object, PDF_NUMBER); - - data = object->data; - - return data->value; -} - -pdf_obj * -pdf_new_string (const void *str, unsigned length) -{ - pdf_obj *result; - pdf_string *data; - - result = pdf_new_obj(PDF_STRING); - data = NEW(1, pdf_string); - result->data = data; - if (length != 0) { - data->length = length; - data->string = NEW(length+1, unsigned char); - memcpy(data->string, str, length); - /* Shouldn't assume NULL terminated. */ - data->string[length] = '\0'; - } else { - data->length = 0; - data->string = NULL; - } - - return result; -} - -void * -pdf_string_value (pdf_obj *object) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - - return data->string; -} - -unsigned -pdf_string_length (pdf_obj *object) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - - return (unsigned) (data->length); -} - -/* - * This routine escapes non printable characters and control - * characters in an output string. - */ -int -pdfobj_escape_str (char *buffer, int bufsize, const unsigned char *s, int len) -{ - int result = 0; - int i; - - for (i = 0; i < len; i++) { - unsigned char ch; - - ch = s[i]; - if (result > bufsize - 4) - ERROR("pdfobj_escape_str: Buffer overflow"); - - /* - * We always write three octal digits. Optimization only gives few Kb - * smaller size for most documents when zlib compressed. - */ - if (ch < 32 || ch > 126) { - buffer[result++] = '\\'; -#if 0 - if (i < len - 1 && !isdigit(s[i+1])) - result += sprintf(buffer+result, "%o", ch); - else - result += sprintf(buffer+result, "%03o", ch); -#endif - result += sprintf(buffer+result, "%03o", ch); - } else { - switch (ch) { - case '(': - buffer[result++] = '\\'; - buffer[result++] = '('; - break; - case ')': - buffer[result++] = '\\'; - buffer[result++] = ')'; - break; - case '\\': - buffer[result++] = '\\'; - buffer[result++] = '\\'; - break; - default: - buffer[result++] = ch; - break; - } - } - } - - return result; -} - -static void -write_string (pdf_string *str, FILE *file) -{ - unsigned char *s; - char wbuf[FORMAT_BUF_SIZE]; /* Shouldn't use format_buffer[]. */ - int nescc = 0, i, count; - - s = str->string; - - if (enc_mode) - pdf_encrypt_data(s, str->length); - - /* - * Count all ASCII non-printable characters. - */ - for (i = 0; i < str->length; i++) { - if (!isprint(s[i])) - nescc++; - } - /* - * If the string contains much escaped chars, then we write it as - * ASCII hex string. - */ - if (nescc > str->length / 3) { - pdf_out_char(file, '<'); - for (i = 0; i < str->length; i++) { - pdf_out_xchar(file, s[i]); - } - pdf_out_char(file, '>'); - } else { - pdf_out_char(file, '('); - /* - * This section of code probably isn't speed critical. Escaping the - * characters in the string one at a time may seem slow, but it's - * safe if the formatted string length exceeds FORMAT_BUF_SIZE. - * Occasionally you see some long strings in PDF. pdfobj_escape_str - * is also used for strings of text with no kerning. These must be - * handled as quickly as possible since there are so many of them. - */ - for (i = 0; i < str->length; i++) { - count = pdfobj_escape_str(wbuf, FORMAT_BUF_SIZE, &(s[i]), 1); - pdf_out(file, wbuf, count); - } - pdf_out_char(file, ')'); - } -} - -static void -release_string (pdf_string *data) -{ - if (data->string != NULL) { - RELEASE(data->string); - data->string = NULL; - } - RELEASE(data); -} - -void -pdf_set_string (pdf_obj *object, unsigned char *str, unsigned length) -{ - pdf_string *data; - - TYPECHECK(object, PDF_STRING); - - data = object->data; - if (data->string != 0) { - RELEASE(data->string); - } - if (length != 0) { - data->length = length; - data->string = NEW(length + 1, unsigned char); - memcpy(data->string, str, length); - data->string[length] = '\0'; - } else { - data->length = 0; - data->string = NULL; - } -} - -/* Name does *not* include the /. */ -pdf_obj * -pdf_new_name (const char *name) -{ - pdf_obj *result; - unsigned length; - pdf_name *data; - - result = pdf_new_obj(PDF_NAME); - data = NEW (1, pdf_name); - result->data = data; - length = strlen(name); - if (length != 0) { - data->name = NEW(length+1, char); - memcpy(data->name, name, length); - data->name[length] = '\0'; - } else { - data->name = NULL; - } - - return result; -} - -static void -write_name (pdf_name *name, FILE *file) -{ - char *s; - int i, length; - - s = name->name; - length = name->name ? strlen(name->name) : 0; - /* - * From PDF Reference, 3rd ed., p.33: - * - * Beginning with PDF 1.2, any character except null (character code 0) - * may be included in a name by writing its 2-digit hexadecimal code, - * preceded bythe number sign character (#); see implementation notes 3 - * and 4 in Appendix H. This syntax is required in order to represent - * any of the delimiter or white-space characters or the number sign - * character itself; it is recommended but not required for characters - * whose codes are outside the range 33 (!) to 126 (~). - */ -#ifndef is_delim - /* Avoid '{' and '}' for PostScript compatibility? */ -#define is_delim(c) ((c) == '(' || (c) == '/' || \ - (c) == '<' || (c) == '>' || \ - (c) == '[' || (c) == ']' || \ - (c) == '{' || (c) == '}' || \ - (c) == '%') -#endif - pdf_out_char(file, '/'); - for (i = 0; i < length; i++) { - if (s[i] < '!' || s[i] > '~' || s[i] == '#' || is_delim(s[i])) { - /* ^ "space" is here. */ - pdf_out_char (file, '#'); - pdf_out_xchar(file, s[i]); - } else { - pdf_out_char (file, s[i]); - } - } -} - -static void -release_name (pdf_name *data) -{ - if (data->name != NULL) { - RELEASE(data->name); - data->name = NULL; - } - RELEASE(data); -} - -#ifdef XETEX -void -pdf_set_name (pdf_obj *object, const char *name) -{ - pdf_name *data; - unsigned length; - - TYPECHECK(object, PDF_NAME); - - length = strlen(name); - data = object->data; - if (data->name != NULL) { - RELEASE(data->name); - } - if (length != 0) { - data->name = NEW(length+1, char); - memcpy(data->name, name, length); - data->name[length] = 0; - } else { - data->name = NULL; - } -} -#endif - -char * -pdf_name_value (pdf_obj *object) -{ - pdf_name *data; - - TYPECHECK(object, PDF_NAME); - - data = object->data; - - return data->name; -} - -/* - * We do not have pdf_name_length() since '\0' is not allowed - * in PDF name object. - */ - -pdf_obj * -pdf_new_array (void) -{ - pdf_obj *result; - pdf_array *data; - - result = pdf_new_obj(PDF_ARRAY); - data = NEW(1, pdf_array); - data->values = NULL; - data->max = 0; - data->size = 0; - result->data = data; - - return result; -} - -static void -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 (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_out_char(file, ']'); -} - -pdf_obj * -pdf_get_array (pdf_obj *array, long idx) -{ - pdf_obj *result = NULL; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (idx < 0) - result = data->values[idx + data->size]; - else if (idx < data->size) { - result = data->values[idx]; - } - - return result; -} - -unsigned int -pdf_array_length (pdf_obj *array) -{ - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = (pdf_array *) array->data; - - return (unsigned int) data->size; -} - -static void -release_array (pdf_array *data) -{ - unsigned long i; - - if (data->values) { - for (i = 0; i < data->size; i++) { - pdf_release_obj(data->values[i]); - data->values[i] = NULL; - } - RELEASE(data->values); - data->values = NULL; - } - RELEASE(data); -} - -/* - * The name pdf_add_array is misleading. It behaves differently than - * pdf_add_dict(). This should be pdf_push_array(). - */ -void -pdf_add_array (pdf_obj *array, pdf_obj *object) -{ - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size >= data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - data->values[data->size] = object; - data->size++; - - return; -} - -#if 0 -void -pdf_put_array (pdf_obj *array, unsigned idx, pdf_obj *object) -{ - pdf_array *data; - long i; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (idx + 1 > data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - /* - * Rangecheck error in PostScript interpreters if - * idx > data->size - 1. But pdf_new_array() doesn't set - * array size, pdf_add_array() dynamically increases size - * of array. This might confusing... - */ - if (idx + 1 > data->size) { - for (i = data->size; i < idx; i++) - data->values[i] = pdf_new_null(); /* release_array() won't work without this */ - data->values[idx] = object; - data->size = idx + 1; - } else { - if (data->values[idx]) - pdf_release_obj(data->values[idx]); - data->values[idx] = object; - } -} - -/* Easily leaks memory... */ -pdf_obj * -pdf_shift_array (pdf_obj *array) -{ - pdf_obj *result = NULL; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size > 0) { - int i; - - result = data->values[0]; - for (i = 1; i < data->size; i++) - data->values[i-1] = data->values[i]; - data->size--; - } - - return result; -} -#endif - -/* Prepend an object to an array */ -void -pdf_unshift_array (pdf_obj *array, pdf_obj *object) -{ - pdf_array *data; - int i; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size >= data->max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW(data->values, data->max, pdf_obj *); - } - for (i = 0; i < data->size; i++) - data->values[i+1] = data->values[i]; - data->values[0] = object; - data->size++; -} - -#if 0 -pdf_obj * -pdf_pop_array (pdf_obj *array) -{ - pdf_obj *result; - pdf_array *data; - - TYPECHECK(array, PDF_ARRAY); - - data = array->data; - if (data->size > 0) { - result = data->values[data->size - 1]; - data->size--; - } else { - result = NULL; - } - - return result; -} -#endif - -static void -write_dict (pdf_dict *dict, FILE *file) -{ -#ifdef XETEX - pdf_out (file, "<<\n", 3); /* dropping \n saves few kb. */ -#else - pdf_out (file, "<<", 2); -#endif - while (dict->key != NULL) { - pdf_write_obj(dict->key, file); - if (pdf_need_white(PDF_NAME, (dict->value)->type)) { - pdf_out_white(file); - } - pdf_write_obj(dict->value, file); -#ifdef XETEX - pdf_out_char (file, '\n'); /* removing this saves few kb. */ -#endif - dict = dict->next; - } - pdf_out(file, ">>", 2); -} - -pdf_obj * -pdf_new_dict (void) -{ - pdf_obj *result; - pdf_dict *data; - - result = pdf_new_obj(PDF_DICT); - data = NEW(1, pdf_dict); - data->key = NULL; - data->value = NULL; - data->next = NULL; - result->data = data; - - return result; -} - -static void -release_dict (pdf_dict *data) -{ - pdf_dict *next; - - while (data != NULL && data->key != NULL) { - pdf_release_obj(data->key); - pdf_release_obj(data->value); - data->key = NULL; - data->value = NULL; - next = data->next; - RELEASE(data); - data = next; - } - RELEASE(data); -} - -/* Array is ended by a node with NULL this pointer */ -/* 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, *new_node; - - TYPECHECK(dict, PDF_DICT); - TYPECHECK(key, PDF_NAME); - - /* It seems that NULL is sometimes used for null object... */ - if (value != NULL && INVALIDOBJ(value)) - ERROR("pdf_add_dict(): Passed invalid value"); - - /* If this key already exists, simply replace the value */ - 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; - return 1; - } - } - /* - * We didn't find the key. We build a new "end" node and add - * the new key just before the end - */ - 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; -} - -#if 0 -void -pdf_put_dict (pdf_obj *dict, const char *key, pdf_obj *value) -{ - pdf_dict *data; - - TYPECHECK(dict, PDF_DICT); - - if (!key) { - ERROR("pdf_put_dict(): Passed invalid key."); - } - /* It seems that NULL is sometimes used for null object... */ - if (value != NULL && INVALIDOBJ(value)) { - ERROR("pdf_add_dict(): Passed invalid value."); - } - - data = dict->data; - - while (data->key != NULL) { - if (!strcmp(key, pdf_name_value(data->key))) { - pdf_release_obj(data->value); - data->value = value; - break; - } - data = data->next; - } - - /* - * If we didn't find the key, 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 = pdf_new_name(key); - data->value = value; - } -} -#endif - -/* pdf_merge_dict makes a link for each item in dict2 before stealing it */ -void -pdf_merge_dict (pdf_obj *dict1, pdf_obj *dict2) -{ - pdf_dict *data; - - TYPECHECK(dict1, PDF_DICT); - TYPECHECK(dict2, PDF_DICT); - - data = dict2->data; - while (data->key != NULL) { - pdf_add_dict(dict1, pdf_link_obj(data->key), pdf_link_obj(data->value)); - data = data->next; - } -} - -int -pdf_foreach_dict (pdf_obj *dict, - int (*proc) (pdf_obj *, pdf_obj *, void *), void *pdata) -{ - int error = 0; - pdf_dict *data; - - ASSERT(proc); - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - while (!error && - data->key != NULL) { - error = proc(data->key, data->value, pdata); - data = data->next; - } - - return error; -} - -#define pdf_match_name(o,s) ((o) && (s) && !strcmp(((pdf_name *)(o)->data)->name, (s))) -pdf_obj * -pdf_lookup_dict (pdf_obj *dict, const char *name) -{ - pdf_dict *data; - - ASSERT(name); - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - while (data->key != NULL) { - if (!strcmp(name, pdf_name_value(data->key))) { - return data->value; - } - data = data->next; - } - - return NULL; -} - -/* Returns array of dictionary keys */ -pdf_obj * -pdf_dict_keys (pdf_obj *dict) -{ - pdf_obj *keys; - pdf_dict *data; - - TYPECHECK(dict, PDF_DICT); - - keys = pdf_new_array(); - for (data = dict->data; (data && - data->key != NULL); data = data->next) { - /* We duplicate name object rather than linking keys. - * If we forget to free keys, broken PDF is generated. - */ - pdf_add_array(keys, pdf_new_name(pdf_name_value(data->key))); - } - - return keys; -} - -void -pdf_remove_dict (pdf_obj *dict, const char *name) -{ - pdf_dict *data, **data_p; - - TYPECHECK(dict, PDF_DICT); - - data = dict->data; - data_p = (pdf_dict **) (void *) &(dict->data); - while (data->key != NULL) { - if (pdf_match_name(data->key, name)) { - pdf_release_obj(data->key); - pdf_release_obj(data->value); - *data_p = data->next; - RELEASE(data); - break; - } - data_p = &(data->next); - data = data->next; - } -} - -pdf_obj * -pdf_new_stream (int flags) -{ - pdf_obj *result; - pdf_stream *data; - - result = pdf_new_obj(PDF_STREAM); - data = NEW(1, pdf_stream); - /* - * Although we are using an arbitrary pdf_object here, it must have - * type=PDF_DICT and cannot be an indirect reference. This will be - * checked by the output routine. - */ - data->dict = pdf_new_dict(); - data->_flags = flags; - data->stream = NULL; - data->stream_length = 0; - data->max_length = 0; - data->objstm_data = NULL; - - result->data = data; - result->flags |= OBJ_NO_OBJSTM; - - return result; -} - -static void -write_stream (pdf_stream *stream, FILE *file) -{ - unsigned char *filtered; - unsigned long filtered_length; - unsigned long buffer_length; - unsigned char *buffer; - - /* - * Always work from a copy of the stream. All filters read from - * "filtered" and leave their result in "filtered". - */ -#if 0 - filtered = NEW(stream->stream_length + 1, unsigned char); -#endif - filtered = NEW(stream->stream_length, unsigned char); - memcpy(filtered, stream->stream, stream->stream_length); - filtered_length = stream->stream_length; - -#if 0 - if (stream->stream_length < 10) - stream->_flags &= ^STREAM_COMPRESS; -#endif - -#ifdef HAVE_ZLIB - /* Apply compression filter if requested */ - if (stream->stream_length > 0 && - (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 *filter_name = pdf_new_name("FlateDecode"); - - 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, - filtered_length, compression_level)) { - ERROR("Zlib error"); - } -#else - if (compress(buffer, &buffer_length, filtered, - filtered_length)) { - ERROR ("Zlib error"); - } -#endif /* HAVE_ZLIB_COMPRESS2 */ - RELEASE(filtered); - compression_saved += filtered_length - buffer_length - - (filters ? strlen("/FlateDecode "): strlen("/Filter/FlateDecode\n")); - - filtered = buffer; - filtered_length = buffer_length; - } -#endif /* HAVE_ZLIB */ - -#if 0 - /* - * An optional end-of-line marker preceding the "endstream" is - * not part of stream data. See, PDF Reference 4th ed., p. 38. - */ - /* Add a '\n' if the last character wasn't one */ - if (filtered_length > 0 && - filtered[filtered_length-1] != '\n') { - filtered[filtered_length] = '\n'; - filtered_length++; - } -#endif - pdf_add_dict(stream->dict, - pdf_new_name("Length"), pdf_new_number(filtered_length)); - - pdf_write_obj(stream->dict, file); - - pdf_out(file, "\nstream\n", 8); - - if (enc_mode) - pdf_encrypt_data(filtered, filtered_length); - - if (filtered_length > 0) { - pdf_out(file, filtered, filtered_length); - } - RELEASE(filtered); - - /* - * This stream length "object" gets reset every time write_stream is - * called for the stream object. - * If this stream gets written more than once with different - * filters, this could be a problem. - */ - - pdf_out(file, "\n", 1); - pdf_out(file, "endstream", 9); -} - -static void -release_stream (pdf_stream *stream) -{ - pdf_release_obj(stream->dict); - stream->dict = NULL; - - if (stream->stream) { - RELEASE(stream->stream); - stream->stream = NULL; - } - - if (stream->objstm_data) { - RELEASE(stream->objstm_data); - stream->objstm_data = NULL; - } - - RELEASE(stream); -} - -pdf_obj * -pdf_stream_dict (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return data->dict; -} - -const void * -pdf_stream_dataptr (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return (const void *) data->stream; -} - -long -pdf_stream_length (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return (long) data->stream_length; -} - -static void -set_objstm_data (pdf_obj *objstm, long *data) { - TYPECHECK(objstm, PDF_STREAM); - - ((pdf_stream *) objstm->data)->objstm_data = data; -} - -static long * -get_objstm_data (pdf_obj *objstm) { - TYPECHECK(objstm, PDF_STREAM); - - return ((pdf_stream *) objstm->data)->objstm_data; -} - -void -pdf_add_stream (pdf_obj *stream, const void *stream_data, long length) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - if (length < 1) - return; - data = stream->data; - if (data->stream_length + length > data->max_length) { - data->max_length += length + STREAM_ALLOC_SIZE; - data->stream = RENEW(data->stream, data->max_length, unsigned char); - } - memcpy(data->stream + data->stream_length, stream_data, length); - data->stream_length += length; -} - -#if HAVE_ZLIB -#define WBUF_SIZE 4096 -int -pdf_add_stream_flate (pdf_obj *dst, const void *data, long len) -{ - z_stream z; - Bytef wbuf[WBUF_SIZE]; - - z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - z.next_in = (Bytef *) data; z.avail_in = len; - z.next_out = (Bytef *) wbuf; z.avail_out = WBUF_SIZE; - - if (inflateInit(&z) != Z_OK) { - WARN("inflateInit() failed."); - return -1; - } - - for (;;) { - int status; - status = inflate(&z, Z_NO_FLUSH); - if (status == Z_STREAM_END) - break; - else if (status != Z_OK) { - WARN("inflate() failed. Broken PDF file?"); - inflateEnd(&z); - return -1; - } - - if (z.avail_out == 0) { - pdf_add_stream(dst, wbuf, WBUF_SIZE); - z.next_out = wbuf; - z.avail_out = WBUF_SIZE; - } - } - - if (WBUF_SIZE - z.avail_out > 0) - pdf_add_stream(dst, wbuf, WBUF_SIZE - z.avail_out); - - return (inflateEnd(&z) == Z_OK ? 0 : -1); -} -#endif - - -int -pdf_concat_stream (pdf_obj *dst, pdf_obj *src) -{ - const char *stream_data; - long stream_length; - pdf_obj *stream_dict; - pdf_obj *filter; - - if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src)) - ERROR("Invalid type."); - - stream_data = pdf_stream_dataptr(src); - stream_length = pdf_stream_length (src); - stream_dict = pdf_stream_dict (src); - - if (pdf_lookup_dict(stream_dict, "DecodeParms")) { - WARN("Streams with DecodeParams not supported."); - return -1; - } - - filter = pdf_lookup_dict(stream_dict, "Filter"); - if (!filter) { - pdf_add_stream(dst, stream_data, stream_length); - return 0; -#if HAVE_ZLIB - } else { - char *filter_name; - if (PDF_OBJ_NAMETYPE(filter)) { - filter_name = pdf_name_value(filter); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return pdf_add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } else if (PDF_OBJ_ARRAYTYPE(filter)) { - if (pdf_array_length(filter) > 1) { - WARN("Multiple DecodeFilter not supported."); - return -1; - } else { - filter_name = pdf_name_value(pdf_get_array(filter, 0)); - if (filter_name && !strcmp(filter_name, "FlateDecode")) - return pdf_add_stream_flate(dst, stream_data, stream_length); - else { - WARN("DecodeFilter \"%s\" not supported.", filter_name); - return -1; - } - } - } else - ERROR("Broken PDF file?"); -#endif /* HAVE_ZLIB */ - } - - return -1; -} - -static pdf_obj * -pdf_stream_uncompress (pdf_obj *src) { - pdf_obj *dst = pdf_new_stream(0); - - TYPECHECK(src, PDF_STREAM); - - pdf_merge_dict(pdf_stream_dict(dst), pdf_stream_dict(src)); - pdf_remove_dict(pdf_stream_dict(dst), "Length"); - pdf_concat_stream(dst, src); - - return dst; -} - -#if 0 -void -pdf_stream_set_flags (pdf_obj *stream, int flags) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - data->_flags = flags; -} - -int -pdf_stream_get_flags (pdf_obj *stream) -{ - pdf_stream *data; - - TYPECHECK(stream, PDF_STREAM); - - data = stream->data; - - return data->_flags; -} -#endif - -static void -pdf_write_obj (pdf_obj *object, FILE *file) -{ - if (object == NULL) { - write_null(NULL, file); - return; - } - - if (INVALIDOBJ(object) || PDF_OBJ_UNDEFINED(object)) - ERROR("pdf_write_obj: Invalid object, type = %d\n", object->type); - - if (file == stderr) - fprintf(stderr, "{%d}", object->refcount); - - switch (object->type) { - case PDF_BOOLEAN: - write_boolean(object->data, file); - break; - case PDF_NUMBER: - write_number (object->data, file); - break; - case PDF_STRING: - write_string (object->data, file); - break; - case PDF_NAME: - write_name(object->data, file); - break; - case PDF_ARRAY: - write_array(object->data, file); - break; - case PDF_DICT: - write_dict (object->data, file); - break; - case PDF_STREAM: - write_stream(object->data, file); - break; - case PDF_NULL: - write_null(NULL, file); - break; - case PDF_INDIRECT: - write_indirect(object->data, file); - break; - } -} - -/* Write the object to the file */ -static void -pdf_flush_obj (pdf_obj *object, FILE *file) -{ - long length; - - /* - * Record file position - */ - 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); - pdf_write_obj(object, file); - pdf_out(file, "\nendobj\n", 8); -} - -static long -pdf_add_objstm (pdf_obj *objstm, pdf_obj *object) -{ - long *data, pos; - - TYPECHECK(objstm, PDF_STREAM); - - data = get_objstm_data(objstm); - pos = ++data[0]; - - data[2*pos] = object->label; - data[2*pos+1] = pdf_stream_length(objstm); - - add_xref_entry(object->label, 2, objstm->label, pos-1); - - /* redirect output into objstm */ - output_stream = objstm; - enc_mode = 0; - pdf_write_obj(object, pdf_output_file); - pdf_out_char(pdf_output_file, '\n'); - output_stream = NULL; - - return pos; -} - -static void -release_objstm (pdf_obj *objstm) -{ - long *data = get_objstm_data(objstm); - long pos = data[0]; - pdf_obj *dict; - pdf_stream *stream; - unsigned char *old_buf; - unsigned long old_length; - stream = (pdf_stream *) objstm->data; - - /* Precede stream data by offset table */ - old_buf = stream->stream; - 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; - - { - long i = 2*pos, *val = data+2; - while (i--) { - long length = sprintf(format_buffer, "%ld ", *(val++)); - pdf_add_stream(objstm, format_buffer, length); - } - } - - dict = pdf_stream_dict(objstm); - 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(objstm, old_buf, old_length); - RELEASE(old_buf); - pdf_release_obj(objstm); -} - -void -pdf_release_obj (pdf_obj *object) -{ - if (object == NULL) - return; - if (INVALIDOBJ(object) || object->refcount <= 0) { - MESG("\npdf_release_obj: object=%p, type=%d, refcount=%d\n", - object, object->type, object->refcount); - pdf_write_obj(object, stderr); - ERROR("pdf_release_obj: Called with invalid object."); - } - object->refcount -= 1; - if (object->refcount == 0) { - /* - * 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) { - if (!do_objstm || object->flags & OBJ_NO_OBJSTM - || (doc_enc_mode && object->flags & OBJ_NO_ENCRYPT) - || object->generation) - pdf_flush_obj(object, pdf_output_file); - else { - if (!current_objstm) { - long *data = NEW(2*OBJSTM_MAX_OBJS+2, long); - data[0] = data[1] = 0; - current_objstm = pdf_new_stream(STREAM_COMPRESS); - set_objstm_data(current_objstm, data); - pdf_label_obj(current_objstm); - } - if (pdf_add_objstm(current_objstm, object) == OBJSTM_MAX_OBJS) { - release_objstm(current_objstm); - current_objstm = NULL; - } - } - } - switch (object->type) { - case PDF_BOOLEAN: - release_boolean(object->data); - break; - case PDF_NULL: - release_null(object->data); - break; - case PDF_NUMBER: - release_number(object->data); - break; - case PDF_STRING: - release_string(object->data); - break; - case PDF_NAME: - release_name(object->data); - break; - case PDF_ARRAY: - release_array(object->data); - break; - case PDF_DICT: - release_dict(object->data); - break; - case PDF_STREAM: - release_stream(object->data); - break; - case PDF_INDIRECT: - release_indirect(object->data); - break; - } - /* This might help detect freeing already freed objects */ - object->type = -1; - object->data = NULL; - RELEASE(object); - } -} - -#ifdef XETEX -/* Copy object data without changing object label. */ -void -pdf_copy_object (pdf_obj *dst, pdf_obj *src) -{ - if (!dst || !src) - return; - - switch (dst->type) { - case PDF_BOOLEAN: release_boolean(dst->data); break; - case PDF_NULL: release_null(dst->data); break; - case PDF_NUMBER: release_number(dst->data); break; - case PDF_STRING: release_string(dst->data); break; - case PDF_NAME: release_name(dst->data); break; - case PDF_ARRAY: release_array(dst->data); break; - case PDF_DICT: release_dict(dst->data); break; - case PDF_STREAM: release_stream(dst->data); break; - case PDF_INDIRECT: release_indirect(dst->data); break; - } - - dst->type = src->type; - switch (src->type) { - case PDF_BOOLEAN: - dst->data = NEW(1, pdf_boolean); - pdf_set_boolean(dst, pdf_boolean_value(src)); - break; - case PDF_NULL: - dst->data = NULL; - break; - case PDF_NUMBER: - dst->data = NEW(1, pdf_number); - pdf_set_number(dst, pdf_number_value(src)); - break; - case PDF_STRING: - dst->data = NEW(1, pdf_string); - pdf_set_string(dst, - pdf_string_value(src), - pdf_string_length(src)); - break; - case PDF_NAME: - dst->data = NEW(1, pdf_name); - pdf_set_name(dst, pdf_name_value(src)); - break; - case PDF_ARRAY: - { - pdf_array *data; - unsigned long i; - - dst->data = data = NEW(1, pdf_array); - data->size = 0; - data->max = 0; - data->values = NULL; - for (i = 0; i < pdf_array_length(src); i++) { - pdf_add_array(dst, pdf_link_obj(pdf_get_array(src, i))); - } - } - break; - case PDF_DICT: - { - pdf_dict *data; - - dst->data = data = NEW(1, pdf_dict); - data->key = NULL; - data->value = NULL; - data->next = NULL; - pdf_merge_dict(dst, src); - } - break; - case PDF_STREAM: - { - pdf_stream *data; - - dst->data = data = NEW(1, pdf_stream); - data->dict = pdf_new_dict(); - data->_flags = ((pdf_stream *)src->data)->_flags; - data->stream_length = 0; - data->max_length = 0; - - pdf_add_stream(dst, pdf_stream_dataptr(src), pdf_stream_length(src)); - pdf_merge_dict(data->dict, pdf_stream_dict(src)); - } - break; - case PDF_INDIRECT: - { - pdf_indirect *data; - - dst->data = data = NEW(1, pdf_indirect); - data->pf = ((pdf_indirect *) (src->data))->pf; - data->label = ((pdf_indirect *) (src->data))->label; - data->generation = ((pdf_indirect *) (src->data))->generation; - } - break; - } - - return; -} -#endif - -static int -backup_line (FILE *pdf_input_file) -{ - int ch = -1; - - /* - * Note: this code should work even if \r\n is eol. It could fail on a - * machine where \n is eol and there is a \r in the stream --- Highly - * unlikely in the last few bytes where this is likely to be used. - */ - if (tell_position(pdf_input_file) > 1) - do { - seek_relative (pdf_input_file, -2); - } while (tell_position(pdf_input_file) > 0 && - (ch = fgetc(pdf_input_file)) >= 0 && - (ch != '\n' && ch != '\r' )); - if (ch < 0) { - return 0; - } - - return 1; -} - -static long -find_xref (FILE *pdf_input_file) -{ - long xref_pos; - int tries = 10; - - do { - long currentpos; - - if (!backup_line(pdf_input_file)) { - tries = 0; - break; - } - currentpos = tell_position(pdf_input_file); - fread(work_buffer, sizeof(char), strlen("startxref"), pdf_input_file); - seek_absolute(pdf_input_file, currentpos); - tries--; - } while (tries > 0 && - strncmp(work_buffer, "startxref", strlen("startxref"))); - if (tries <= 0) - return 0; - - /* Skip rest of this line */ - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - /* Next line of input file should contain actual xref location */ - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - - { - const char *start, *end; - char *number; - - start = work_buffer; - end = start + strlen(work_buffer); - skip_white(&start, end); - number = parse_number(&start, end); - xref_pos = (long) atof(number); - RELEASE(number); - } - - return xref_pos; -} - -/* - * This routine must be called with the file pointer located - * at the start of the trailer. - */ -static pdf_obj * -parse_trailer (pdf_file *pf) -{ - pdf_obj *result; - /* - * Fill work_buffer and hope trailer fits. This should - * be made a bit more robust sometime. - */ - if (fread(work_buffer, sizeof(char), - WORK_BUFFER_SIZE, pf->file) == 0 || - strncmp(work_buffer, "trailer", strlen("trailer"))) { - WARN("No trailer. Are you sure this is a PDF file?"); - WARN("buffer:\n->%s<-\n", work_buffer); - result = NULL; - } else { - const char *p = work_buffer + strlen("trailer"); - skip_white(&p, work_buffer + WORK_BUFFER_SIZE); - result = parse_pdf_dict(&p, work_buffer + WORK_BUFFER_SIZE, pf); - } - - return result; -} - -/* - * This routine tries to estimate an upper bound for character position - * of the end of the object, so it knows how big the buffer must be. - * The parsing routines require that the entire object be read into - * memory. It would be a major pain to rewrite them. The worst case - * is that an object before an xref table will grab the whole table - * :-( - */ -static long -next_object_offset (pdf_file *pf, unsigned long obj_num) -{ - long next = pf->file_size; /* Worst case */ - long i, curr; - - curr = pf->xref_table[obj_num].field2; - /* Check all other type 1 objects to find next one */ - for (i = 0; i < pf->num_obj; i++) { - if (pf->xref_table[i].type == 1 && - pf->xref_table[i].field2 > curr && - pf->xref_table[i].field2 < next) - next = pf->xref_table[i].field2; - } - - return next; -} - -#define checklabel(pf, n, g) ((n) > 0 && (n) < (pf)->num_obj && ( \ - ((pf)->xref_table[(n)].type == 1 && (pf)->xref_table[(n)].field3 == (g)) || \ - ((pf)->xref_table[(n)].type == 2 && !(g)))) - -pdf_obj * -pdf_new_indirect (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) -{ - pdf_obj *result; - pdf_indirect *indirect; - - indirect = NEW(1, pdf_indirect); - indirect->pf = pf; - indirect->label = obj_num; - indirect->generation = obj_gen; - - result = pdf_new_obj(PDF_INDIRECT); - result->data = indirect; - - return result; -} - -static pdf_obj * -pdf_read_object (unsigned long obj_num, unsigned short obj_gen, - pdf_file *pf, long offset, long limit) -{ - long length; - char *buffer; - const char *p, *endptr; - pdf_obj *result; - - length = limit - offset; - - if (length <= 0) - return NULL; - - buffer = NEW(length + 1, char); - - seek_absolute(pf->file, offset); - fread(buffer, sizeof(char), length, pf->file); - - p = buffer; - endptr = p + length; - - /* Check for obj_num and obj_gen */ - { - const char *q = p; /* <== p */ - char *sp; - unsigned long n, g; - - skip_white(&q, endptr); - sp = parse_unsigned(&q, endptr); - if (!sp) { - RELEASE(buffer); - return NULL; - } - n = strtoul(sp, NULL, 10); - RELEASE(sp); - - skip_white(&q, endptr); - sp = parse_unsigned(&q, endptr); - if (!sp) { - RELEASE(buffer); - return NULL; - } - g = strtoul(sp, NULL, 10); - RELEASE(sp); - - if (obj_num && (n != obj_num || g != obj_gen)) { - RELEASE(buffer); - return NULL; - } - - p = q; /* ==> p */ - } - - - skip_white(&p, endptr); - if (memcmp(p, "obj", strlen("obj"))) { - WARN("Didn't find \"obj\"."); - RELEASE(buffer); - return NULL; - } - p += strlen("obj"); - - result = parse_pdf_object(&p, endptr, pf); - - skip_white(&p, endptr); - if (memcmp(p, "endobj", strlen("endobj"))) { - WARN("Didn't find \"endobj\"."); - if (result) - pdf_release_obj(result); - result = NULL; - } - RELEASE(buffer); - - return result; -} - -static pdf_obj * -read_objstm (pdf_file *pf, unsigned long num) -{ - unsigned long offset = pf->xref_table[num].field2; - unsigned short gen = pf->xref_table[num].field3; - long limit = next_object_offset(pf, num), n, first, *header = NULL; - char *data = NULL, *q; - const char *p, *endptr; - int i; - - pdf_obj *objstm, *dict, *type, *n_obj, *first_obj; - - objstm = pdf_read_object(num, gen, pf, offset, limit); - - if (!PDF_OBJ_STREAMTYPE(objstm)) - goto error; - - { - pdf_obj *tmp = pdf_stream_uncompress(objstm); - if (!tmp) - goto error; - pdf_release_obj(objstm); - objstm = tmp; - } - - dict = pdf_stream_dict(objstm); - - type = pdf_lookup_dict(dict, "Type"); - if (!PDF_OBJ_NAMETYPE(type) || - strcmp(pdf_name_value(type), "ObjStm")) - goto error; - - n_obj = pdf_lookup_dict(dict, "N"); - if (!PDF_OBJ_NUMBERTYPE(n_obj)) - goto error; - n = (long) pdf_number_value(n_obj); - - first_obj = pdf_lookup_dict(dict, "First"); - if (!PDF_OBJ_NUMBERTYPE(first_obj)) - goto error; - first = (long) pdf_number_value(first_obj); - /* reject object streams without object data */ - if (first >= pdf_stream_length(objstm)) - goto error; - - header = NEW(2*(n+1), long); - set_objstm_data(objstm, header); - *(header++) = n; - *(header++) = first; - - /* avoid parsing beyond offset table */ - data = NEW(first + 1, char); - memcpy(data, pdf_stream_dataptr(objstm), first); - data[first] = 0; - - p = data; - endptr = p + first; - i = 2*n; - while (i--) { - *(header++) = strtoul(p, &q, 10); - if (q == p) - goto error; - p = q; - } - - /* Any garbage after last entry? */ - skip_white(&p, endptr); - if (p != endptr) - goto error; - RELEASE(data); - - return pf->xref_table[num].direct = objstm; - - error: - WARN("Cannot parse object stream."); - if (data) - RELEASE(data); - if (objstm) - pdf_release_obj(objstm); - return NULL; -} - -/* Label without corresponding object definition are replaced by the - * null object, as required by the PDF spec. This is important to parse - * several cross-reference sections. - */ -static pdf_obj * -pdf_get_object (pdf_file *pf, unsigned long obj_num, unsigned short obj_gen) -{ - pdf_obj *result; - - if (!checklabel(pf, obj_num, obj_gen)) { - WARN("Trying to read nonexistent or deleted object: %lu %u", - obj_num, obj_gen); - return pdf_new_null(); - } - - if ((result = pf->xref_table[obj_num].direct)) { - return pdf_link_obj(result); - } - - if (pf->xref_table[obj_num].type == 1) { - /* type == 1 */ - unsigned long offset; - long limit; - offset = pf->xref_table[obj_num].field2; - limit = next_object_offset(pf, obj_num); - result = pdf_read_object(obj_num, obj_gen, pf, offset, limit); - } else { - /* type == 2 */ - unsigned long objstm_num = pf->xref_table[obj_num].field2; - unsigned short index = pf->xref_table[obj_num].field3; - pdf_obj *objstm; - long *data, n, first, length; - const char *p, *q; - - if (objstm_num >= pf->num_obj || - pf->xref_table[objstm_num].type != 1 || - !((objstm = pf->xref_table[objstm_num].direct) || - (objstm = read_objstm(pf, objstm_num)))) - goto error; - - data = get_objstm_data(objstm); - n = *(data++); - first = *(data++); - - if (index >= n || data[2*index] != obj_num) - goto error; - - length = pdf_stream_length(objstm); - p = (const char *) pdf_stream_dataptr(objstm) + first + data[2*index+1]; - q = p + (index == n-1 ? length : first+data[2*index+3]); - result = parse_pdf_object(&p, q, pf); - if (!result) - goto error; - } - - /* Make sure the caller doesn't free this object */ - pf->xref_table[obj_num].direct = pdf_link_obj(result); - - return result; - - error: - WARN("Could not read object from object stream."); - return pdf_new_null(); -} - -#define OBJ_FILE(o) (((pdf_indirect *)((o)->data))->pf) -#define OBJ_NUM(o) (((pdf_indirect *)((o)->data))->label) -#define OBJ_GEN(o) (((pdf_indirect *)((o)->data))->generation) - -/* pdf_deref_obj always returns a link instead of the original */ -/* It never return the null object, but the NULL pointer instead */ -pdf_obj * -pdf_deref_obj (pdf_obj *obj) -{ - if (obj) - obj = pdf_link_obj(obj); - - while (PDF_OBJ_INDIRECTTYPE(obj)) { - pdf_file *pf = OBJ_FILE(obj); - unsigned long obj_num = OBJ_NUM(obj); - unsigned short obj_gen = OBJ_GEN(obj); - if (!pf) - ERROR("Tried to deref a non-file object"); - pdf_release_obj(obj); - obj = pdf_get_object(pf, obj_num, obj_gen); - } - - if (PDF_OBJ_NULLTYPE(obj)) { - pdf_release_obj(obj); - return NULL; - } else - return obj; -} - -static void -extend_xref (pdf_file *pf, long new_size) -{ - unsigned long i; - - pf->xref_table = RENEW(pf->xref_table, new_size, xref_entry); - for (i = pf->num_obj; i < new_size; i++) { - pf->xref_table[i].direct = NULL; - pf->xref_table[i].indirect = NULL; - pf->xref_table[i].type = 0; - pf->xref_table[i].field3 = 0; - pf->xref_table[i].field2 = 0L; - } - pf->num_obj = new_size; -} - -static int -parse_xref_table (pdf_file *pf, long xref_pos) -{ - FILE *pdf_input_file = pf->file; - unsigned long first, size; - unsigned long i, offset; - unsigned int obj_gen; - char flag; - int r; - - /* - * This routine reads one xref segment. It may be called multiple times - * on the same file. xref tables sometimes come in pieces. - */ - - seek_absolute(pf->file, xref_pos); - - mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - if (memcmp(work_buffer, "xref", strlen("xref"))) { - /* Might be an xref stream and not an xref table */ - return 0; - } - /* Next line in file has first item and size of table */ - for (;;) { - unsigned long current_pos; - - current_pos = tell_position(pdf_input_file); - if (mfgets(work_buffer, WORK_BUFFER_SIZE, pdf_input_file) == NULL) { - WARN("Premature end of PDF file while parsing xref table."); - return -1; - } - if (!strncmp(work_buffer, "trailer", strlen ("trailer"))) { - /* - * Backup... This is ugly, but it seems like the safest thing to - * do. It is possible the trailer dictionary starts on the same - * logical line as the word trailer. In that case, the mfgets - * call might have started to read the trailer dictionary and - * parse_trailer would fail. - */ - seek_absolute(pdf_input_file, current_pos); - break; - } - sscanf(work_buffer, "%lu %lu", &first, &size); - if (pf->num_obj < first + size) { - extend_xref(pf, first + size); - } - - for (i = first; i < first + size; i++) { - fread(work_buffer, sizeof(char), 20, pdf_input_file); - /* - * Don't overwrite positions that have already been set by a - * modified xref table. We are working our way backwards - * through the reference table, so we only set "position" - * if it hasn't been set yet. - */ - work_buffer[19] = 0; - offset = 0UL; obj_gen = 0; flag = 0; - r = sscanf(work_buffer, "%010lu %05u %c", &offset, &obj_gen, &flag); - if ( r != 3 || - ((flag != 'n' && flag != 'f') || - (flag == 'n' && - (offset >= pf->file_size || (offset > 0 && offset < 4))))) { - WARN("Invalid xref table entry [%lu]. PDF file is corrupt...", i); - return -1; - } - if (!pf->xref_table[i].field2) { - pf->xref_table[i].type = (flag == 'n'); - pf->xref_table[i].field2 = offset; - pf->xref_table[i].field3 = obj_gen; - } - } - } - - return 1; -} - -static unsigned long -parse_xrefstm_field (const char **p, int length, unsigned long def) -{ - unsigned long val = 0; - - if (!length) - return def; - - while (length--) { - val <<= 8; - val |= (unsigned char) *((*p)++); - } - - return val; -} - -static int -parse_xrefstm_subsec (pdf_file *pf, - const char **p, long *length, - int *W, int wsum, - long first, long size) { - xref_entry *e; - - if ((*length -= wsum*size) < 0) - return -1; - - if (pf->num_obj < first+size) - extend_xref(pf, first+size); /* TODO: change! why? */ - - e = pf->xref_table + first; - while (size--) { - unsigned char type; - unsigned long field2; - unsigned short field3; - - type = (unsigned char) parse_xrefstm_field(p, W[0], 1); - if (type > 2) - WARN("Unknown cross-reference stream entry type."); - else if (!W[1] || (type != 1 && !W[2])) - return -1; - - field2 = (unsigned long) parse_xrefstm_field(p, W[1], 0); - field3 = (unsigned short) parse_xrefstm_field(p, W[2], 0); - - if (!e->field2) { - e->type = type; - e->field2 = field2; - e->field3 = field3; - } - e++; - } - - return 0; -} - -static int -parse_xref_stream (pdf_file *pf, long xref_pos, pdf_obj **trailer) -{ - pdf_obj *xrefstm, *size_obj, *W_obj, *index_obj; - unsigned long size; - long length; - int W[3], i, wsum = 0; - const char *p; - - xrefstm = pdf_read_object(0, 0, pf, xref_pos, pf->file_size); - if (!PDF_OBJ_STREAMTYPE(xrefstm)) - goto error; - - { - pdf_obj *tmp = pdf_stream_uncompress(xrefstm); - if (!tmp) - goto error; - pdf_release_obj(xrefstm); - xrefstm = tmp; - } - - *trailer = pdf_link_obj(pdf_stream_dict(xrefstm)); - - size_obj = pdf_lookup_dict(*trailer, "Size"); - if (!PDF_OBJ_NUMBERTYPE(size_obj)) - goto error; - size = (unsigned long) pdf_number_value(size_obj); - - length = pdf_stream_length(xrefstm); - - W_obj = pdf_lookup_dict(*trailer, "W"); - if (!PDF_OBJ_ARRAYTYPE(W_obj) || pdf_array_length(W_obj) != 3) - goto error; - - for (i = 0; i < 3; i++) { - pdf_obj *tmp = pdf_get_array(W_obj, i); - if (!PDF_OBJ_NUMBERTYPE(tmp)) - goto error; - wsum += (W[i] = (int) pdf_number_value(tmp)); - } - - p = pdf_stream_dataptr(xrefstm); - - index_obj = pdf_lookup_dict(*trailer, "Index"); - if (index_obj) { - unsigned int index_len; - if (!PDF_OBJ_ARRAYTYPE(index_obj) || - ((index_len = pdf_array_length(index_obj)) % 2 )) - goto error; - - i = 0; - while (i < index_len) { - pdf_obj *first = pdf_get_array(index_obj, i++); - size_obj = pdf_get_array(index_obj, i++); - if (!PDF_OBJ_NUMBERTYPE(first) || - !PDF_OBJ_NUMBERTYPE(size_obj) || - parse_xrefstm_subsec(pf, &p, &length, W, wsum, - (long) pdf_number_value(first), - (long) pdf_number_value(size_obj))) - goto error; - } - } else if (parse_xrefstm_subsec(pf, &p, &length, W, wsum, 0, size)) - goto error; - - if (length) - WARN("Garbage in xref stream."); - - pdf_release_obj(xrefstm); - - return 1; - - error: - WARN("Cannot parse cross-reference stream."); - if (xrefstm) - pdf_release_obj(xrefstm); - if (*trailer) { - pdf_release_obj(*trailer); - *trailer = NULL; - } - return 0; -} - -/* TODO: parse Version entry */ -static pdf_obj * -read_xref (pdf_file *pf) -{ - pdf_obj *trailer = NULL, *main_trailer = NULL; - long xref_pos; - - if (!(xref_pos = find_xref(pf->file))) - goto error; - - while (xref_pos) { - pdf_obj *prev; - - int res = parse_xref_table(pf, xref_pos); - if (res > 0) { - /* cross-reference table */ - pdf_obj *xrefstm; - - if (!(trailer = parse_trailer(pf))) - goto error; - - if (!main_trailer) - main_trailer = pdf_link_obj(trailer); - - if ((xrefstm = pdf_lookup_dict(trailer, "XRefStm"))) { - pdf_obj *new_trailer = NULL; - if (PDF_OBJ_NUMBERTYPE(xrefstm) && - parse_xref_stream(pf, (long) pdf_number_value(xrefstm), - &new_trailer)) - pdf_release_obj(new_trailer); - else - WARN("Skipping hybrid reference section."); - /* Many PDF 1.5 xref streams use DecodeParms, which we cannot - parse. This way we can use at least xref tables in hybrid - documents. Or should we better stop parsing the file? - */ - } - - } else if (!res && parse_xref_stream(pf, xref_pos, &trailer)) { - /* cross-reference stream */ - if (!main_trailer) - main_trailer = pdf_link_obj(trailer); - } else - goto error; - - if ((prev = pdf_lookup_dict(trailer, "Prev"))) { - if (PDF_OBJ_NUMBERTYPE(prev)) - xref_pos = (long) pdf_number_value(prev); - else - goto error; - } else - xref_pos = 0; - - pdf_release_obj(trailer); - } - -#if 0 - if (!pdf_lookup_dict(main_trailer, "Root")) { - WARN("Trailer doesn't have catalog. Is this a correct PDF file?"); - goto error; - } -#endif - - return main_trailer; - - error: - WARN("Error while parsing PDF file."); - if (trailer) - pdf_release_obj(trailer); - if (main_trailer) - pdf_release_obj(main_trailer); - return NULL; -} - -static struct ht_table *pdf_files = NULL; - -static pdf_file * -pdf_file_new (FILE *file) -{ - pdf_file *pf; - ASSERT(file); - pf = NEW(1, pdf_file); - pf->file = file; - pf->trailer = NULL; - pf->xref_table = NULL; - pf->catalog = NULL; - pf->num_obj = 0; - pf->version = 0; - - seek_end(file); - pf->file_size = tell_position(file); - - return pf; -} - -static void -pdf_file_free (pdf_file *pf) -{ - unsigned long i; - - if (!pf) { - return; - } - - for (i = 0; i < pf->num_obj; i++) { - if (pf->xref_table[i].direct) - pdf_release_obj(pf->xref_table[i].direct); - if (pf->xref_table[i].indirect) - pdf_release_obj(pf->xref_table[i].indirect); - } - - RELEASE(pf->xref_table); - if (pf->trailer) { - pdf_release_obj(pf->trailer); - pf->trailer = NULL; - } - - RELEASE(pf); -} - -void -pdf_files_init (void) -{ - pdf_files = NEW(1, struct ht_table); - ht_init_table(pdf_files, (void (*)(void *)) pdf_file_free); -} - -int -pdf_file_get_version (pdf_file *pf) -{ - ASSERT(pf); - return pf->version; -} - -#ifdef XETEX -pdf_obj * -pdf_file_get_trailer (pdf_file *pf) -{ - ASSERT(pf); - return pdf_link_obj(pf->trailer); -} -#endif - -pdf_obj * -pdf_file_get_catalog (pdf_file *pf) -{ - ASSERT(pf); - return pf->catalog; -} - -pdf_file * -pdf_open (const char *ident, FILE *file) -{ - pdf_file *pf = NULL; - - ASSERT(pdf_files); - - if (ident) - pf = (pdf_file *) ht_lookup_table(pdf_files, ident, strlen(ident)); - - if (pf) { - pf->file = file; - } else { - int version = check_for_pdf_version(file); - - if (version < 0 || version > 5) { - WARN("pdf_open: Not a PDF 1.[1-5] file."); - return NULL; - } - - pf = pdf_file_new(file); - pf->version = version; - - if (!(pf->trailer = read_xref(pf))) { - pdf_file_free(pf); - return NULL; - } - - if (ident) - ht_append_table(pdf_files, ident, strlen(ident), pf); - } - - return pf; -} - -void -pdf_close (pdf_file *pf) -{ - if (pf) - pf->file = NULL; -} - -void -pdf_files_close (void) -{ - ASSERT(pdf_files); - ht_clear_table(pdf_files); - RELEASE(pdf_files); -} - -static int -check_for_pdf_version (FILE *file) -{ - unsigned int minor; - - rewind(file); - - return (ungetc(fgetc(file), file) == '%' && - fscanf(file, "%%PDF-1.%u", &minor) == 1) ? minor : -1; -} - -int -check_for_pdf (FILE *file) -{ - int version = check_for_pdf_version(file); - - if (version < 0) /* not a PDF file */ - return 0; - - if (version <= pdf_version) - return 1; - - WARN("Version of PDF file (1.%c) is newer than version limit specification.", - pdf_version); - return 0; -} - -static int CDECL -import_dict (pdf_obj *key, pdf_obj *value, void *pdata) -{ - pdf_obj *copy; - pdf_obj *tmp; - - copy = (pdf_obj *) pdata; - - tmp = pdf_import_object(value); - if (!tmp) { - return -1; - } - pdf_add_dict(copy, pdf_link_obj(key), tmp); - - return 0; -} - -static pdf_obj * -pdf_import_indirect (pdf_obj *object) -{ - pdf_file *pf = OBJ_FILE(object); - unsigned long obj_num = OBJ_NUM(object); - unsigned short obj_gen = OBJ_GEN(object); - - pdf_obj *ref; - - ASSERT(pf); - - if (!checklabel(pf, obj_num, obj_gen)) { - WARN("Can't resolve object: %lu %u", obj_num, obj_gen); - return pdf_new_null(); - } - - if ((ref = pf->xref_table[obj_num].indirect)) { - return pdf_link_obj(ref); - } else { - pdf_obj *obj, *tmp; - - obj = pdf_get_object(pf, obj_num, obj_gen); - if (!obj) { - WARN("Could not read object: %lu %u", obj_num, obj_gen); - return NULL; - } - - tmp = pdf_import_object(obj); - - pf->xref_table[obj_num].indirect = ref = pdf_ref_obj(tmp); - - pdf_release_obj(tmp); - pdf_release_obj(obj); - - return pdf_link_obj(ref); - } -} - -/* - * pdf_import_object recursively copies the object and those - * referenced by it and changes the indirect references so that - * they refer to the current output file. New indirect references - * are remembered, which avoids duplicating objects when they - * are imported several times. - */ -pdf_obj * -pdf_import_object (pdf_obj *object) -{ - pdf_obj *imported; - pdf_obj *tmp; - int i; - - switch (pdf_obj_typeof(object)) { - - case PDF_INDIRECT: - if (OBJ_FILE(object)) { - imported = pdf_import_indirect(object); - } else { - imported = pdf_link_obj(object); - } - break; - - case PDF_STREAM: - { - pdf_obj *stream_dict; - - tmp = pdf_import_object(pdf_stream_dict(object)); - if (!tmp) - return NULL; - - imported = pdf_new_stream(0); - stream_dict = pdf_stream_dict(imported); - pdf_merge_dict(stream_dict, tmp); - pdf_release_obj(tmp); - pdf_add_stream(imported, - pdf_stream_dataptr(object), - pdf_stream_length(object)); - } - break; - - case PDF_DICT: - - imported = pdf_new_dict(); - if (pdf_foreach_dict(object, import_dict, imported) < 0) { - pdf_release_obj(imported); - return NULL; - } - - break; - - case PDF_ARRAY: - - imported = pdf_new_array(); - for (i = 0; i < pdf_array_length(object); i++) { - tmp = pdf_import_object(pdf_get_array(object, i)); - if (!tmp) { - pdf_release_obj(imported); - return NULL; - } - pdf_add_array(imported, tmp); - } - break; - - default: - imported = pdf_link_obj(object); - } - - return imported; -} - - -/* returns 0 if indirect references point to the same object */ -int -pdf_compare_reference (pdf_obj *ref1, pdf_obj *ref2) -{ - pdf_indirect *data1, *data2; - - ASSERT(PDF_OBJ_INDIRECTTYPE(ref1) && PDF_OBJ_INDIRECTTYPE(ref2)); - - data1 = (pdf_indirect *) ref1->data; - data2 = (pdf_indirect *) ref2->data; - - return data1->pf != data2->pf || data1->label != data2->label - || data1->generation != data2->generation; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/pdfximage.c b/Build/source/texk/dvipdfm-x/xsrc/pdfximage.c deleted file mode 100644 index 13efb1136a8..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/pdfximage.c +++ /dev/null @@ -1,957 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "error.h" -#include "mem.h" - -#include "dpxfile.h" - -#include "pdfobj.h" - -#include "pdfdoc.h" -#include "pdfdev.h" -#include "pdfdraw.h" - -#include "epdf.h" -#include "mpost.h" -#include "pngimage.h" -#include "jpegimage.h" -#include "bmpimage.h" - -#include "pdfximage.h" - -/* From psimage.h */ -static int check_for_ps (FILE *fp); -static int ps_include_page (pdf_ximage *ximage, const char *file_name); - - -#define IMAGE_TYPE_UNKNOWN -1 -#define IMAGE_TYPE_PDF 0 -#define IMAGE_TYPE_JPEG 1 -#define IMAGE_TYPE_PNG 2 -#define IMAGE_TYPE_MPS 4 -#define IMAGE_TYPE_EPS 5 -#define IMAGE_TYPE_BMP 6 - - -struct attr_ -{ - long width, height; - double xdensity, ydensity; - pdf_rect bbox; -}; - -struct pdf_ximage_ -{ - char *ident; - char res_name[16]; - long page_no, page_count; - - int subtype; - - struct attr_ attr; - - char *filename; - pdf_obj *reference; - pdf_obj *resource; - pdf_obj *attr_dict; - - char tempfile; -}; - - -/* verbose, verbose, verbose... */ -struct opt_ -{ - int verbose; - char *cmdtmpl; -}; - -static struct opt_ _opts = { - 0, NULL -}; - -void pdf_ximage_set_verbose (void) { _opts.verbose++; } - - -struct ic_ -{ - int count, capacity; - pdf_ximage *ximages; -}; - -static struct ic_ _ic = { - 0, 0, NULL -}; - -static void -pdf_init_ximage_struct (pdf_ximage *I, - const char *ident, const char *filename, - long page_no, pdf_obj *dict) -{ - if (ident) { - I->ident = NEW(strlen(ident)+1, char); - strcpy(I->ident, ident); - } else - I ->ident = NULL; - I->page_no = page_no; - I->page_count = 0; - if (filename) { - I->filename = NEW(strlen(filename)+1, char); - strcpy(I->filename, filename); - } else - I->filename = NULL; - I->subtype = -1; - memset(I->res_name, 0, 16); - I->reference = NULL; - I->resource = NULL; - I->attr_dict = dict; - - 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->tempfile = 0; -} - -static void -pdf_set_ximage_tempfile (pdf_ximage *I, const char *filename) -{ - if (I->filename) - RELEASE(I->filename); - I->filename = NEW(strlen(filename)+1, char); - strcpy(I->filename, filename); - I->tempfile = 1; -} - -static void -pdf_clean_ximage_struct (pdf_ximage *I) -{ - if (I->ident) - RELEASE(I->ident); - if (I->filename) - RELEASE(I->filename); - if (I->reference) - pdf_release_obj(I->reference); - if (I->resource) - pdf_release_obj(I->resource); - if (I->attr_dict) - pdf_release_obj(I->attr_dict); - pdf_init_ximage_struct(I, NULL, NULL, 0, NULL); -} - - -void -pdf_init_images (void) -{ - struct ic_ *ic = &_ic; - ic->count = 0; - ic->capacity = 0; - ic->ximages = NULL; -} - -void -pdf_close_images (void) -{ - struct ic_ *ic = &_ic; - if (ic->ximages) { - int i; - for (i = 0; i < ic->count; i++) { - pdf_ximage *I = ic->ximages+i; - if (I->tempfile) { - /* - * It is important to remove temporary files at the end because - * we cache file names. Since we use mkstemp to create them, we - * might get the same file name again if delete the first file. - * (This happens on NetBSD, reported by Jukka Salmi.) - * We also use this to convert a PS file only once if multiple - * pages are imported from that file. - */ - if (_opts.verbose > 1 && keep_cache != 1) - MESG("pdf_image>> deleting temporary file \"%s\"\n", I->filename); - dpx_delete_temp_file(I->filename, false); /* temporary filename freed here */ - I->filename = NULL; - } - pdf_clean_ximage_struct(I); - } - RELEASE(ic->ximages); - ic->ximages = NULL; - ic->count = ic->capacity = 0; - } - - if (_opts.cmdtmpl) - RELEASE(_opts.cmdtmpl); - _opts.cmdtmpl = NULL; -} - -static int -source_image_type (FILE *fp) -{ - int format = IMAGE_TYPE_UNKNOWN; - - rewind(fp); - /* - * Make sure we check for PS *after* checking for MP since - * MP is a special case of PS. - */ - if (check_for_jpeg(fp)) - { - format = IMAGE_TYPE_JPEG; - } -#ifdef HAVE_LIBPNG - else if (check_for_png(fp)) - { - format = IMAGE_TYPE_PNG; - } -#endif - else if (check_for_bmp(fp)) - { - format = IMAGE_TYPE_BMP; - } else if (check_for_pdf(fp)) { - format = IMAGE_TYPE_PDF; - } else if (check_for_mp(fp)) { - format = IMAGE_TYPE_MPS; - } else if (check_for_ps(fp)) { - format = IMAGE_TYPE_EPS; - } else { - format = IMAGE_TYPE_UNKNOWN; - } - rewind(fp); - - return format; -} - -static int -load_image (const char *ident, const char *fullname, int format, FILE *fp, - long page_no, pdf_obj *dict) -{ - struct ic_ *ic = &_ic; - int id = -1; /* ret */ - pdf_ximage *I; - - id = ic->count; - if (ic->count >= ic->capacity) { - ic->capacity += 16; - ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); - } - - I = &ic->ximages[id]; - pdf_init_ximage_struct(I, ident, fullname, page_no, dict); - - switch (format) { - case IMAGE_TYPE_JPEG: - if (_opts.verbose) - MESG("[JPEG]"); - if (jpeg_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; -#ifdef HAVE_LIBPNG - case IMAGE_TYPE_PNG: - if (_opts.verbose) - MESG("[PNG]"); - if (png_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; -#endif - case IMAGE_TYPE_BMP: - if (_opts.verbose) - MESG("[BMP]"); - if (bmp_include_image(I, fp) < 0) - goto error; - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - break; - case IMAGE_TYPE_PDF: - if (_opts.verbose) - MESG("[PDF]"); - if (pdf_include_page(I, fp, NULL) < 0) - goto error; - if (_opts.verbose) - MESG(",Page:%ld", I->page_no); - I->subtype = PDF_XOBJECT_TYPE_FORM; - break; - // case IMAGE_TYPE_EPS: - default: - if (_opts.verbose) - MESG(format == IMAGE_TYPE_EPS ? "[PS]" : "[UNKNOWN]"); - if (ps_include_page(I, fullname) < 0) - goto error; - if (_opts.verbose) - MESG(",Page:%ld", I->page_no); - I->subtype = PDF_XOBJECT_TYPE_FORM; - } - - switch (I->subtype) { - case PDF_XOBJECT_TYPE_IMAGE: - sprintf(I->res_name, "Im%d", id); - break; - case PDF_XOBJECT_TYPE_FORM: - sprintf(I->res_name, "Fm%d", id); - break; - default: - ERROR("Unknown XObject subtype: %d", I->subtype); - goto error; - } - - ic->count++; - - return id; - - error: - pdf_clean_ximage_struct(I); - return -1; -} - - -#define dpx_find_file(n,d,s) (kpse_find_pict((n))) -#define dpx_fopen(n,m) (MFOPEN((n),(m))) -#define dpx_fclose(f) (MFCLOSE((f))) - -int -pdf_ximage_findresource (const char *ident, long page_no, pdf_obj *dict) -{ - struct ic_ *ic = &_ic; - int id = -1; - pdf_ximage *I; - char *fullname; - int format; - FILE *fp; - - for (id = 0; id < ic->count; id++) { - I = &ic->ximages[id]; - if (I->ident && !strcmp(ident, I->ident) && - I->page_no == page_no + (page_no < 0 ? I->page_count+1 : 0) && - I->attr_dict == dict) { - return id; - } - } - - /* try loading image */ - fullname = dpx_find_file(ident, "_pic_", ""); - if (!fullname) { - WARN("Error locating image file \"%s\"", ident); - return -1; - } - - fp = dpx_fopen(fullname, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Error opening image file \"%s\"", fullname); - RELEASE(fullname); - return -1; - } - if (_opts.verbose) { - MESG("(Image:%s", ident); - if (_opts.verbose > 1) - MESG("[%s]", fullname); - } - - format = source_image_type(fp); - switch (format) { - case IMAGE_TYPE_MPS: - if (_opts.verbose) - MESG("[MPS]"); - id = mps_include_page(ident, fp); - if (id < 0) { - WARN("Try again with the distiller."); - format = IMAGE_TYPE_EPS; - rewind(fp); - } else - break; - default: - id = load_image(ident, fullname, format, fp, page_no, dict); - break; - } - dpx_fclose(fp); - - RELEASE(fullname); - - if (_opts.verbose) - MESG(")"); - - if (id < 0) - WARN("pdf: image inclusion failed for \"%s\".", ident); - - 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) -{ - info->flags = 0; - info->bbox.llx = 0; - info->bbox.lly = 0; - info->bbox.urx = 0; - info->bbox.ury = 0; - info->matrix.a = 1.0; - info->matrix.b = 0.0; - info->matrix.c = 0.0; - info->matrix.d = 1.0; - info->matrix.e = 0.0; - 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) -{ - info->flags = 0; - info->width = 0; - info->height = 0; - info->bits_per_component = 0; - info->num_components = 0; - info->min_dpi = 0; - info->xdensity = info->ydensity = 1.0; -} - -#ifdef XETEX -char * -pdf_ximage_get_ident (pdf_ximage *I) -{ - return I->ident; -} -#endif - -void -pdf_ximage_set_image (pdf_ximage *I, void *image_info, pdf_obj *resource) -{ - pdf_obj *dict; - ximage_info *info = image_info; - - if (!PDF_OBJ_STREAMTYPE(resource)) - ERROR("Image XObject must be of stream type."); - - I->subtype = PDF_XOBJECT_TYPE_IMAGE; - - 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); - - dict = pdf_stream_dict(resource); - pdf_add_dict(dict, pdf_new_name("Type"), pdf_new_name("XObject")); - pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image")); - pdf_add_dict(dict, pdf_new_name("Width"), pdf_new_number(info->width)); - pdf_add_dict(dict, pdf_new_name("Height"), pdf_new_number(info->height)); - pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), - pdf_new_number(info->bits_per_component)); - if (I->attr_dict) - pdf_merge_dict(dict, I->attr_dict); - - pdf_release_obj(resource); /* Caller don't know we are using reference. */ - I->resource = NULL; -} - -void -pdf_ximage_set_form (pdf_ximage *I, void *form_info, pdf_obj *resource) -{ - 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; -} - -#define CHECK_ID(c,n) do {\ - if ((n) < 0 || (n) >= (c)->count) {\ - ERROR("Invalid XObject ID: %d", (n));\ - }\ -} while (0) -#define GET_IMAGE(c,n) (&((c)->ximages[(n)])) - -pdf_obj * -pdf_ximage_get_reference (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - if (!I->reference) - I->reference = pdf_ref_obj(I->resource); - - 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; - - id = ic->count; - if (ic->count >= ic->capacity) { - ic->capacity += 16; - ic->ximages = RENEW(ic->ximages, ic->capacity, pdf_ximage); - } - - I = &ic->ximages[id]; - - pdf_init_ximage_struct(I, ident, NULL, 0, NULL); - - switch (subtype) { - case PDF_XOBJECT_TYPE_IMAGE: - pdf_ximage_set_image(I, info, resource); - sprintf(I->res_name, "Im%d", id); - break; - case PDF_XOBJECT_TYPE_FORM: - pdf_ximage_set_form (I, info, resource); - sprintf(I->res_name, "Fm%d", id); - break; - default: - ERROR("Unknown XObject subtype: %d", subtype); - } - ic->count++; - - return id; -} - - -char * -pdf_ximage_get_resname (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - - return I->res_name; -} - -#ifndef XETEX -int -pdf_ximage_get_subtype (int id) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - - return I->subtype; -} - -void -pdf_ximage_set_attr (int id, long width, long height, double xdensity, double ydensity, double llx, double lly, double urx, double ury) -{ - struct ic_ *ic = &_ic; - pdf_ximage *I; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, id); - I->attr.width = width; - I->attr.height = height; - I->attr.xdensity = xdensity; - I->attr.ydensity = ydensity; - I->attr.bbox.llx = llx; - I->attr.bbox.lly = lly; - I->attr.bbox.urx = urx; - I->attr.bbox.ury = ury; -} -#endif - -/* 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 - -static void -scale_to_fit_I (pdf_tmatrix *T, - transform_info *p, - pdf_ximage *I) -{ - double s_x, s_y, d_x, d_y; - double wd0, ht0, dp, xscale, yscale; - - 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; - } - - if (wd0 == 0.0) { - WARN("Image width=0.0!"); - wd0 = 1.0; - } - if (ht0 == 0.0) { - WARN("Image height=0.0!"); - ht0 = 1.0; - } - - if ( (p->flags & INFO_HAS_WIDTH ) && - (p->flags & INFO_HAS_HEIGHT) ) { - 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) * yscale; - s_x = s_y * ((double)I->attr.width / I->attr.height); - dp = p->depth * yscale; - } else { - 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 = d_x * s_x / xscale; T->f = d_y * s_y / yscale - dp; - - return; -} - - -static void -scale_to_fit_F (pdf_tmatrix *T, - transform_info *p, - pdf_ximage *I) -{ - double s_x, s_y, d_x, d_y; - double wd0, ht0, dp; - - if (p->flags & INFO_HAS_USER_BBOX) { - wd0 = p->bbox.urx - p->bbox.llx; - ht0 = p->bbox.ury - p->bbox.lly; - d_x = -p->bbox.llx; - d_y = -p->bbox.lly; - } else { - wd0 = I->attr.bbox.urx - I->attr.bbox.llx; - ht0 = I->attr.bbox.ury - I->attr.bbox.lly; - d_x = 0.0; - d_y = 0.0; - } - - if (wd0 == 0.0) { - WARN("Image width=0.0!"); - wd0 = 1.0; - } - if (ht0 == 0.0) { - WARN("Image height=0.0!"); - ht0 = 1.0; - } - - if ( (p->flags & INFO_HAS_WIDTH ) && - (p->flags & INFO_HAS_HEIGHT) ) { - s_x = p->width / wd0; - s_y = (p->height + p->depth) / ht0; - dp = p->depth; - } else if ( p->flags & INFO_HAS_WIDTH ) { - s_x = p->width / wd0; - s_y = s_x; - dp = 0.0; - } else if ( p->flags & INFO_HAS_HEIGHT) { - s_y = (p->height + p->depth) / ht0; - s_x = s_y; - dp = p->depth; - } else { - s_x = s_y = 1.0; - dp = 0.0; - } - - T->a = s_x; T->c = 0.0; - T->b = 0.0; T->d = s_y; - T->e = s_x * d_x; T->f = s_y * d_y - dp; - - return; -} - - -/* called from pdfdev.c and spc_html.c */ -int -pdf_ximage_scale_image (int id, - 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; - - CHECK_ID(ic, id); - - I = GET_IMAGE(ic, 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); - 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) { - r->llx = p->bbox.llx; - r->lly = p->bbox.lly; - r->urx = p->bbox.urx; - r->ury = p->bbox.ury; - } 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; - r->ury = I->attr.bbox.ury; - } - break; - } - - return 0; -} - - -/* Migrated from psimage.c */ - -void set_distiller_template (char *s) -{ - if (_opts.cmdtmpl) - RELEASE(_opts.cmdtmpl); - if (!s || *s == '\0') - _opts.cmdtmpl = NULL; - else { - _opts.cmdtmpl = NEW(strlen(s) + 1, char); - strcpy(_opts.cmdtmpl, s); - } - return; -} - -#ifdef XETEX -char *get_distiller_template (void) -{ - return _opts.cmdtmpl; -} -#endif - -static int -ps_include_page (pdf_ximage *ximage, const char *filename) -{ - char *distiller_template = _opts.cmdtmpl; - char *temp; - FILE *fp; - int error = 0; - struct stat stat_o, stat_t; - - if (!distiller_template) { - WARN("No image converter available for converting file \"%s\" to PDF format.", filename); - WARN(">> Please check if you have 'D' option in config file."); - return -1; - } - - temp = dpx_create_fix_temp_file(filename); - if (!temp) { - WARN("Failed to create temporary file for image conversion: %s", filename); - return -1; - } - -#ifdef MIKTEX - { - char *p; - for (p = (char *)filename; *p; p++) { - if (*p == '\\') *p = '/'; - } - for (p = (char *)temp; *p; p++) { - if (*p == '\\') *p = '/'; - } - } -#endif - if (keep_cache != -1 && stat(temp, &stat_t)==0 && stat(filename, &stat_o)==0 - && stat_t.st_mtime > stat_o.st_mtime) { - /* cache exist */ - /*printf("\nLast file modification: %s", ctime(&stat_o.st_mtime)); - printf("Last file modification: %s", ctime(&stat_t.st_mtime));*/ - ; - } else { - if (_opts.verbose > 1) { - MESG("\n"); - MESG("pdf_image>> Converting file \"%s\" --> \"%s\" via:\n", filename, temp); - MESG("pdf_image>> %s\n", distiller_template); - MESG("pdf_image>> ..."); - } - error = dpx_file_apply_filter(distiller_template, filename, temp, - (unsigned char) pdf_get_version()); - if (error) { - WARN("Image format conversion for \"%s\" failed...", filename); - dpx_delete_temp_file(temp, true); - return error; - } - } - - fp = MFOPEN(temp, FOPEN_RBIN_MODE); - if (!fp) { - WARN("Could not open conversion result \"%s\" for image \"%s\". Why?", temp, filename); - dpx_delete_temp_file(temp, true); - return -1; - } - pdf_set_ximage_tempfile(ximage, temp); -#if 0 - error = pdf_include_page(ximage, fp, 0, pdfbox_crop); -#endif - error = pdf_include_page(ximage, fp, NULL); - MFCLOSE(fp); - - /* See pdf_close_images for why we cannot delete temporary files here. */ - - RELEASE(temp); - - if (error) { - WARN("Failed to include image file \"%s\"", filename); - WARN(">> Please check if"); - WARN(">> %s", distiller_template); - WARN(">> %%o = output filename, %%i = input filename, %%b = input filename without suffix"); - WARN(">> can really convert \"%s\" to PDF format image.", filename); - } - - return error; -} - -static int check_for_ps (FILE *image_file) -{ - rewind (image_file); - mfgets (work_buffer, WORK_BUFFER_SIZE, image_file); - if (!strncmp (work_buffer, "%!", 2)) - return 1; - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/spc_pdfm.c b/Build/source/texk/dvipdfm-x/xsrc/spc_pdfm.c deleted file mode 100644 index f522fbeb7eb..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/spc_pdfm.c +++ /dev/null @@ -1,2125 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" - -#include "numbers.h" - -#include "fontmap.h" -#include "dpxfile.h" -#include "dpxutil.h" - -#include "pdfobj.h" -#include "pdfparse.h" - -#include "pdfdoc.h" - -#include "pdfximage.h" -#include "pdfdraw.h" -#include "pdfcolor.h" -#include "pdfdev.h" - -#include "specials.h" - -#include "spc_util.h" -#include "spc_pdfm.h" - -#include "dvipdfmx.h" - -#define ENABLE_TOUNICODE 1 - - -/* PLEASE REMOVE THIS */ -struct resource_map { - int type; - int res_id; -}; - -#ifdef ENABLE_TOUNICODE -struct tounicode { - int cmap_id; - int unescape_backslash; - pdf_obj *taintkeys; /* An array of PDF names. */ -}; -#endif /* ENABLE_TOUNICODE */ - -struct spc_pdf_ -{ - pdf_obj *annot_dict; /* pending annotation dict */ - int lowest_level; /* current min level of outlines */ - struct ht_table *resourcemap; /* see remark below (somewhere) */ -#ifdef ENABLE_TOUNICODE - struct tounicode cd; /* For to-UTF16-BE conversion :( */ -#endif /* ENABLE_TOUNICODE */ -}; - -#if 1 -static struct spc_pdf_ _pdf_stat = { - NULL, - 255, - NULL, -#ifdef ENABLE_TOUNICODE - { -1, 0, NULL } -#endif /* ENABLE_TOUNICODE */ -}; -#endif - -/* PLEASE REMOVE THIS */ -static void -hval_free (void *vp) -{ - RELEASE(vp); -} - - -static int -addresource (struct spc_pdf_ *sd, const char *ident, int res_id) -{ - struct resource_map *r; - - if (!ident || res_id < 0) - return -1; - - r = NEW(1, struct resource_map); - r->type = 0; /* unused */ - r->res_id = res_id; - - ht_append_table(sd->resourcemap, ident, strlen(ident), r); - spc_push_object(ident, pdf_ximage_get_reference(res_id)); - - return 0; -} - -static int -findresource (struct spc_pdf_ *sd, const char *ident) -{ - struct resource_map *r; - - if (!ident) - return -1; - - r = ht_lookup_table(sd->resourcemap, ident, strlen(ident)); - - return (r ? r->res_id : -1); -} - - -static int -spc_handler_pdfm__init (struct spc_env *spe, struct spc_arg *ap, void *dp) -{ - struct spc_pdf_ *sd = dp; -#ifdef ENABLE_TOUNICODE - static const char *default_taintkeys[] = { - "Title", "Author", "Subject", "Keywords", - "Creator", "Producer", "Contents", "Subj", - "TU", "T", "TM", NULL /* EOD */ - }; - int i; -#endif /* ENABLE_TOUNICODE */ - - sd->annot_dict = NULL; - sd->lowest_level = 255; - sd->resourcemap = NEW(1, struct ht_table); - ht_init_table(sd->resourcemap, hval_free); - -#ifdef ENABLE_TOUNICODE - sd->cd.taintkeys = pdf_new_array(); - for (i = 0; default_taintkeys[i] != NULL; i++) { - pdf_add_array(sd->cd.taintkeys, - pdf_new_name(default_taintkeys[i])); - } -#endif /* ENABLE_TOUNICODE */ - - return 0; -} - -static int -spc_handler_pdfm__clean (struct spc_env *spe, struct spc_arg *ap, void *dp) -{ - struct spc_pdf_ *sd = dp; - - if (sd->annot_dict) { - WARN("Unbalanced bann and eann found."); - pdf_release_obj(sd->annot_dict); - } - sd->lowest_level = 255; - sd->annot_dict = NULL; - if (sd->resourcemap) { - ht_clear_table(sd->resourcemap); - RELEASE(sd->resourcemap); - } - sd->resourcemap = NULL; - -#ifdef ENABLE_TOUNICODE - if (sd->cd.taintkeys) - pdf_release_obj(sd->cd.taintkeys); - sd->cd.taintkeys = NULL; -#endif /* ENABLE_TOUNICODE */ - - return 0; -} - - -int -spc_pdfm_at_begin_document (void) -{ - struct spc_pdf_ *sd = &_pdf_stat; - return spc_handler_pdfm__init(NULL, NULL, sd); -} - -int -spc_pdfm_at_end_document (void) -{ - struct spc_pdf_ *sd = &_pdf_stat; - return spc_handler_pdfm__clean(NULL, NULL, sd); -} - - -/* Dvipdfm specials */ -static int -spc_handler_pdfm_bop (struct spc_env *spe, struct spc_arg *args) -{ - if (args->curptr < args->endptr) { - pdf_doc_set_bop_content(args->curptr, - (long) (args->endptr - args->curptr)); - } - - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_eop (struct spc_env *spe, struct spc_arg *args) -{ - if (args->curptr < args->endptr) { - pdf_doc_set_eop_content(args->curptr, - (long) (args->endptr - args->curptr)); - } - - args->curptr = args->endptr; - - return 0; -} - -#define streamfiltered(o) \ - (pdf_lookup_dict(pdf_stream_dict((o)), "Filter") ? 1 : 0) - -/* Why should we have this kind of things? */ -static int -safeputresdent (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - char *key; - - ASSERT(kp && vp && dp); - - key = pdf_name_value(kp); - if (pdf_lookup_dict(dp, key)) - WARN("Object \"%s\" already defined in dict! (ignored)", key); - else { - pdf_add_dict(dp, - pdf_link_obj(kp), pdf_link_obj(vp)); - } - return 0; -} - -#ifndef pdf_obj_isaref -#define pdf_obj_isaref(o) (pdf_obj_typeof((o)) == PDF_INDIRECT) -#endif - -static int -safeputresdict (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - char *key; - pdf_obj *dict; - - ASSERT(kp && vp && dp); - - key = pdf_name_value(kp); - dict = pdf_lookup_dict(dp, key); - - if (pdf_obj_isaref(vp)) { - pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); - } else if (pdf_obj_typeof(vp) == PDF_DICT) { - if (dict) - pdf_foreach_dict(vp, safeputresdent, dict); - else { - pdf_add_dict(dp, pdf_new_name(key), pdf_link_obj(vp)); - } - } else { - WARN("Invalid type (not DICT) for page/form resource dict entry: key=\"%s\"", key); - return -1; - } - - return 0; -} - - -/* Think what happens if you do - * - * pdf:put @resources << /Font << >> >> - * - */ -static int -spc_handler_pdfm_put (struct spc_env *spe, struct spc_arg *ap) -{ - pdf_obj *obj1, *obj2; /* put obj2 into obj1 */ - char *ident; - int error = 0; - - skip_white(&ap->curptr, ap->endptr); - - ident = parse_opt_ident(&ap->curptr, ap->endptr); - if (!ident) { - spc_warn(spe, "Missing object identifier."); - return -1; - } - obj1 = spc_lookup_object(ident); - if (!obj1) { - spc_warn(spe, "Specified object not exist: %s", ident); - RELEASE(ident); - return -1; - } - skip_white(&ap->curptr, ap->endptr); - - obj2 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); - if (!obj2) { - spc_warn(spe, "Missing (an) object(s) to put into \"%s\"!", ident); - RELEASE(ident); - return -1; - } - - switch (pdf_obj_typeof(obj1)) { - case PDF_DICT: - if (pdf_obj_typeof(obj2) != PDF_DICT) { - spc_warn(spe, "Inconsistent object type for \"put\" (expecting DICT): %s", ident); - error = -1; - } else { - if (!strcmp(ident, "resources")) - error = pdf_foreach_dict(obj2, safeputresdict, obj1); - else { - pdf_merge_dict(obj1, obj2); - } - } - break; - - case PDF_STREAM: - if (pdf_obj_typeof(obj2) == PDF_DICT) - pdf_merge_dict(pdf_stream_dict(obj1), obj2); - else if (pdf_obj_typeof(obj2) == PDF_STREAM) -#if 0 - { - pdf_merge_dict(pdf_stream_dict(obj1), pdf_stream_dict(obj2)); - pdf_add_stream(obj1, pdf_stream_dataptr(obj2), pdf_stream_length(obj2)); - } -#else - { - spc_warn(spe, "\"put\" operation not supported for STREAM <- STREAM: %s", ident); - error = -1; - } -#endif - else { - spc_warn(spe, "Invalid type: expecting a DICT or STREAM: %s", ident); - error = -1; - } - break; - - case PDF_ARRAY: - /* dvipdfm */ - pdf_add_array(obj1, pdf_link_obj(obj2)); - while (ap->curptr < ap->endptr) { - pdf_obj *obj3 = parse_pdf_object(&ap->curptr, ap->endptr, NULL); - if (!obj3) - break; - pdf_add_array(obj1, obj3); - skip_white(&ap->curptr, ap->endptr); - } - break; - - default: - spc_warn(spe, "Can't \"put\" object into non-DICT/STREAM/ARRAY type object: %s", ident); - error = -1; - break; - } - pdf_release_obj(obj2); - RELEASE(ident); - - return error; -} - - -#ifdef ENABLE_TOUNICODE - -/* For pdf:tounicode support - * This feature is provided for convenience. TeX can't do - * input encoding conversion. - */ -#include "cmap.h" - -static int -reencodestring (CMap *cmap, pdf_obj *instring) -{ -#define WBUF_SIZE 4096 - unsigned char wbuf[WBUF_SIZE]; - unsigned char *obufcur; - const unsigned char *inbufcur; - long inbufleft, obufleft; - - if (!cmap || !instring) - return 0; - - inbufleft = pdf_string_length(instring); - inbufcur = pdf_string_value (instring); - - wbuf[0] = 0xfe; - wbuf[1] = 0xff; - obufcur = wbuf + 2; - obufleft = WBUF_SIZE - 2; - - CMap_decode(cmap, - &inbufcur, &inbufleft, - &obufcur, &obufleft); - - if (inbufleft > 0) { - return -1; - } - - pdf_set_string(instring, wbuf, WBUF_SIZE - obufleft); - - return 0; -} - -#ifdef XETEX -/* tables/values used in UTF-8 interpretation - - code is based on ConvertUTF.[ch] sample code - published by the Unicode consortium */ -static unsigned long -offsetsFromUTF8[6] = { - 0x00000000UL, - 0x00003080UL, - 0x000E2080UL, - 0x03C82080UL, - 0xFA082080UL, - 0x82082080UL -}; - -static unsigned char -bytesFromUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -static int -maybe_reencode_utf8(pdf_obj *instring) -{ - unsigned char* inbuf; - int inlen; - int non_ascii = 0; - unsigned char* cp; - unsigned char* op; - unsigned char wbuf[WBUF_SIZE]; - - if (!instring) - return 0; - - inlen = pdf_string_length(instring); - inbuf = pdf_string_value(instring); - - /* check if the input string is strictly ASCII */ - for (cp = inbuf; cp < inbuf + inlen; ++cp) { - if (*cp > 127) { - non_ascii = 1; - } - } - if (non_ascii == 0) - return 0; /* no need to reencode ASCII strings */ - - cp = inbuf; - op = wbuf; - *op++ = 0xfe; - *op++ = 0xff; - while (cp < inbuf + inlen) { - unsigned long usv = *cp++; - int extraBytes = bytesFromUTF8[usv]; - if (cp + extraBytes > inbuf + inlen) - return -1; /* ill-formed, so give up reencoding */ - switch (extraBytes) { /* note: code falls through cases! */ - case 5: usv <<= 6; usv += *cp++; - case 4: usv <<= 6; usv += *cp++; - case 3: usv <<= 6; usv += *cp++; - case 2: usv <<= 6; usv += *cp++; - case 1: usv <<= 6; usv += *cp++; - case 0: ; - }; - usv -= offsetsFromUTF8[extraBytes]; - if (usv > 0x10FFFF) - return -1; /* out of valid Unicode range, give up */ - if (usv > 0xFFFF) { - /* supplementary-plane character: generate high surrogate */ - unsigned long hi = 0xdc00 + (usv - 0x10000) % 0x0400; - if (op > wbuf + WBUF_SIZE - 2) - return -1; /* out of space */ - *op++ = hi / 256; - *op++ = hi % 256; - usv = 0xd800 + (usv - 0x10000) / 0x0400; - /* remaining value in usv is the low surrogate */ - } - if (op > wbuf + WBUF_SIZE - 2) - return -1; /* out of space */ - *op++ = usv / 256; - *op++ = usv % 256; - } - - pdf_set_string(instring, wbuf, op - wbuf); - - return 0; -} -#endif - -static int -needreencode (pdf_obj *kp, pdf_obj *vp, struct tounicode *cd) -{ - int r = 0, i; - pdf_obj *tk; - - ASSERT( cd && cd->taintkeys ); - ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); - ASSERT( pdf_obj_typeof(vp) == PDF_STRING ); - - for (i = 0; i < pdf_array_length(cd->taintkeys); i++) { - tk = pdf_get_array(cd->taintkeys, i); - ASSERT( tk && pdf_obj_typeof(tk) == PDF_NAME ); - if (!strcmp(pdf_name_value(kp), pdf_name_value(tk))) { - r = 1; - break; - } - } - if (r) { - /* Check UTF-16BE BOM. */ - if (pdf_string_length(vp) >= 2 && - !memcmp(pdf_string_value(vp), "\xfe\xff", 2)) - r = 0; - } - - return r; -} - -static int modstrings (pdf_obj *key, pdf_obj *value, void *pdata); - -static int -modstrings (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - int r = 0; /* continue */ - struct tounicode *cd = dp; - - ASSERT( pdf_obj_typeof(kp) == PDF_NAME ); - - switch (pdf_obj_typeof(vp)) { - case PDF_STRING: - { - CMap *cmap; - - if (cd && cd->cmap_id >= 0 && cd->taintkeys) { - cmap = CMap_cache_get(cd->cmap_id); - if (needreencode(kp, vp, cd)) { - r = reencodestring(cmap, vp); - } - } - else { - r = maybe_reencode_utf8(vp); - } - if (r < 0) /* error occured... */ - WARN("Failed to convert input string to UTF16..."); - } - break; - case PDF_DICT: - r = pdf_foreach_dict(vp, modstrings, dp); - break; - case PDF_STREAM: - r = pdf_foreach_dict(pdf_stream_dict(vp), modstrings, dp); - break; - } - - return r; -} - -static pdf_obj * -my_parse_pdf_dict (const char **pp, const char *endptr, struct tounicode *cd) -{ - pdf_obj *dict; - -#ifdef XETEX -/* disable this test, as we do utf8 reencoding with no cmap */ -#else - if (cd->cmap_id < 0) - return parse_pdf_dict(pp, endptr, NULL); -#endif - - /* :( */ - if (cd && cd->unescape_backslash) - dict = parse_pdf_tainted_dict(pp, endptr); - else { - dict = parse_pdf_dict(pp, endptr, NULL); - } - if (dict) - pdf_foreach_dict(dict, modstrings, cd); - - return dict; -} - -#endif /* ENABLE_TOUNICODE */ - - -static int -spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *annot_dict; - pdf_rect rect; - char *ident = NULL; - pdf_coord cp; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] == '@') { - ident = parse_opt_ident(&args->curptr, args->endptr); - skip_white(&args->curptr, args->endptr); - } - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - if (ident) - RELEASE(ident); - return -1; - } - - if ((ti.flags & INFO_HAS_USER_BBOX) && - ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { - spc_warn(spe, "You can't specify both bbox and width/height."); - if (ident) - RELEASE(ident); - return -1; - } - -#ifdef ENABLE_TOUNICODE - annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!annot_dict) { - spc_warn(spe, "Could not find dictionary object."); - if (ident) - RELEASE(ident); - return -1; - } else if (!PDF_OBJ_DICTTYPE(annot_dict)) { - spc_warn(spe, "Invalid type: not dictionary object."); - if (ident) - RELEASE(ident); - pdf_release_obj(annot_dict); - return -1; - } - - cp.x = spe->x_user; cp.y = spe->y_user; - pdf_dev_transform(&cp, NULL); - if (ti.flags & INFO_HAS_USER_BBOX) { - rect.llx = ti.bbox.llx + cp.x; - rect.lly = ti.bbox.lly + cp.y; - rect.urx = ti.bbox.urx + cp.x; - rect.ury = ti.bbox.ury + cp.y; - } else { - rect.llx = cp.x; - rect.lly = cp.y - spe->mag * ti.depth; - rect.urx = cp.x + spe->mag * ti.width; - rect.ury = cp.y + spe->mag * ti.height; - } - - /* Order is important... */ - if (ident) - spc_push_object(ident, pdf_link_obj(annot_dict)); - /* This add reference. */ - pdf_doc_add_annot(pdf_doc_current_page_number(), &rect, annot_dict, 0); - - if (ident) { - spc_flush_object(ident); - RELEASE(ident); - } - pdf_release_obj(annot_dict); - - return 0; -} - -/* NOTE: This can't have ident. See "Dvipdfm User's Manual". */ -static int -spc_handler_pdfm_bann (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int error = 0; - - if (sd->annot_dict) { - spc_warn(spe, "Can't begin an annotation when one is pending."); - return -1; - } - - skip_white(&args->curptr, args->endptr); - -#ifdef ENABLE_TOUNICODE - sd->annot_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - sd->annot_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!sd->annot_dict) { - spc_warn(spe, "Ignoring annotation with invalid dictionary."); - return -1; - } else if (!PDF_OBJ_DICTTYPE(sd->annot_dict)) { - spc_warn(spe, "Invalid type: not a dictionary object."); - pdf_release_obj(sd->annot_dict); - sd->annot_dict = NULL; - return -1; - } - - error = spc_begin_annot(spe, sd->annot_dict); - - return error; -} - -static int -spc_handler_pdfm_eann (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int error = 0; - - if (!sd->annot_dict) { - spc_warn(spe, "Tried to end an annotation without starting one!"); - return -1; - } - - error = spc_end_annot(spe); - - pdf_release_obj(sd->annot_dict); - sd->annot_dict = NULL; - - return error; -} - - -/* Color:.... */ -static int -spc_handler_pdfm_bcolor (struct spc_env *spe, struct spc_arg *ap) -{ - int error; - pdf_color fc, sc; - - error = spc_util_read_colorspec(spe, &fc, ap, 0); - if (!error) { - if (ap->curptr < ap->endptr) { - error = spc_util_read_colorspec(spe, &sc, ap, 0); - } else { - pdf_color_copycolor(&sc, &fc); - } - } - - if (error) - spc_warn(spe, "Invalid color specification?"); - else { - pdf_color_push(&sc, &fc); /* save currentcolor */ - pdf_dev_set_strokingcolor(&sc); - pdf_dev_set_nonstrokingcolor(&fc); - } - - return error; -} - -/* - * This special changes the current color without clearing the color stack. - * It therefore differs from "color rgb 1 0 0". - */ -static int -spc_handler_pdfm_scolor (struct spc_env *spe, struct spc_arg *ap) -{ - int error; - pdf_color fc, sc; - - error = spc_util_read_colorspec(spe, &fc, ap, 0); - if (!error) { - if (ap->curptr < ap->endptr) { - error = spc_util_read_colorspec(spe, &sc, ap, 0); - } else { - pdf_color_copycolor(&sc, &fc); - } - } - - if (error) - spc_warn(spe, "Invalid color specification?"); - else { - pdf_color_set_default(&fc); /* ????? */ - pdf_dev_set_strokingcolor(&sc); - pdf_dev_set_nonstrokingcolor(&fc); - } - - return error; -} - -static int -spc_handler_pdfm_ecolor (struct spc_env *spe, struct spc_arg *args) -{ - pdf_color_pop(); - return 0; -} - - -static int -spc_handler_pdfm_btrans (struct spc_env *spe, struct spc_arg *args) -{ - pdf_tmatrix M; - transform_info ti; - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - return -1; - } - - /* Create transformation matrix */ - pdf_copymatrix(&M, &(ti.matrix)); - 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); - - pdf_dev_gsave(); - pdf_dev_concat(&M); - - return 0; -} - -static int -spc_handler_pdfm_etrans (struct spc_env *spe, struct spc_arg *args) -{ - pdf_dev_grestore(); - - /* - * Unfortunately, the following line is necessary in case - * of a font or color change inside of the save/restore pair. - * Anything that was done there must be redone, so in effect, - * we make no assumptions about what fonts. We act like we are - * starting a new page. - */ - pdf_dev_reset_fonts(); - pdf_dev_reset_color(); - - return 0; -} - -static int -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, 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, NULL); - if (!tmp) { - spc_warn(spe, "Missing number for outline item depth."); - return -1; - } else if (!PDF_OBJ_NUMBERTYPE(tmp)) { - pdf_release_obj(tmp); - spc_warn(spe, "Expecting number for outline item depth."); - return -1; - } - - item_dict = NULL; - - level = (int) pdf_number_value(tmp); - pdf_release_obj(tmp); - - /* What is this? Starting at level 3 and can go down to level 1? - * - * Here is the original comment: - * Make sure we know where the starting level is - * - * NOTE: added - * We need this for converting pages from 3rd to... :( - */ - sd->lowest_level = MIN(sd->lowest_level, level); - - level += 1 - sd->lowest_level; - -#ifdef ENABLE_TOUNICODE - item_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - item_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!item_dict) { - spc_warn(spe, "Ignoring invalid dictionary."); - return -1; - } - current_depth = pdf_doc_bookmarks_depth(); - if (current_depth > level) { - while (current_depth-- > level) - pdf_doc_bookmarks_up(); - } else if (current_depth < level) { - while (current_depth++ < level) - pdf_doc_bookmarks_down(); - } - - pdf_doc_bookmarks_add(item_dict, is_open); - - return 0; -} - -static int -spc_handler_pdfm_article (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - char *ident; - pdf_obj *info_dict; - - skip_white (&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Article name expected but not found."); - return -1; - } - -#ifdef ENABLE_TOUNICODE - info_dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - info_dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!info_dict) { - spc_warn(spe, "Ignoring article with invalid info dictionary."); - RELEASE(ident); - return -1; - } - - pdf_doc_begin_article(ident, pdf_link_obj(info_dict)); - spc_push_object(ident, info_dict); - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_bead (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *article; - pdf_obj *article_info; - char *article_name; - pdf_rect rect; - long page_no; - transform_info ti; - pdf_coord cp; - - skip_white(&args->curptr, args->endptr); - - if (args->curptr[0] != '@') { - spc_warn(spe, "Article identifier expected but not found."); - return -1; - } - - article_name = parse_opt_ident(&args->curptr, args->endptr); - if (!article_name) { - spc_warn(spe, "Article reference expected but not found."); - return -1; - } - - /* If okay so far, try to get a bounding box */ - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(article_name); - return -1; - } - - if ((ti.flags & INFO_HAS_USER_BBOX) && - ((ti.flags & INFO_HAS_WIDTH) || (ti.flags & INFO_HAS_HEIGHT))) { - spc_warn(spe, "You can't specify both bbox and width/height."); - RELEASE(article_name); - return -1; - } - - cp.x = spe->x_user; cp.y = spe->y_user; - pdf_dev_transform(&cp, NULL); - if (ti.flags & INFO_HAS_USER_BBOX) { - rect.llx = ti.bbox.llx + cp.x; - rect.lly = ti.bbox.lly + cp.y; - rect.urx = ti.bbox.urx + cp.x; - rect.ury = ti.bbox.ury + cp.y; - } else { - rect.llx = cp.x; - rect.lly = cp.y - spe->mag * ti.depth; - rect.urx = cp.x + spe->mag * ti.width; - rect.ury = cp.y + spe->mag * ti.height; - } - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] != '<') { - article_info = pdf_new_dict(); - } else { -#ifdef ENABLE_TOUNICODE - article_info = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - article_info = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!article_info) { - spc_warn(spe, "Error in reading dictionary."); - RELEASE(article_name); - return -1; - } - } - - /* Does this article exist yet */ - article = spc_lookup_object(article_name); - if (article) { - pdf_merge_dict (article, article_info); - pdf_release_obj(article_info); - } else { - pdf_doc_begin_article(article_name, pdf_link_obj(article_info)); - spc_push_object(article_name, article_info); - } - page_no = pdf_doc_current_page_number(); - pdf_doc_add_bead(article_name, NULL, page_no, &rect); - - RELEASE(article_name); - return 0; -} - -static int -spc_handler_pdfm_image (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int xobj_id; - char *ident = NULL; - pdf_obj *fspec, *attr = NULL; - transform_info ti; - long page_no; - - skip_white(&args->curptr, args->endptr); - if (args->curptr[0] == '@') { - ident = parse_opt_ident(&args->curptr, args->endptr); - xobj_id = findresource(sd, ident); - if (xobj_id >= 0) { - spc_warn(spe, "Object reference name for image \"%s\" already used.", ident); - RELEASE(ident); - return -1; - } - } - - transform_info_clear(&ti); - page_no = 1; - if (spc_util_read_dimtrns(spe, &ti, args, &page_no, 0) < 0) { - if (ident) - RELEASE(ident); - return -1; - } - - skip_white(&args->curptr, args->endptr); - fspec = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!fspec) { - spc_warn(spe, "Missing filename string for pdf:image."); - if (ident) - RELEASE(ident); - return -1; - } 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; - } - - skip_white(&args->curptr, args->endptr); - if (args->curptr < args->endptr) { - attr = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!attr || !PDF_OBJ_DICTTYPE(attr)) { - spc_warn(spe, "Ignore invalid attribute dictionary."); - if (attr) pdf_release_obj(attr); - } - } - - xobj_id = pdf_ximage_findresource(pdf_string_value(fspec), page_no, attr); - if (xobj_id < 0) { - spc_warn(spe, "Could not find image resource..."); - pdf_release_obj(fspec); - if (ident) - RELEASE(ident); - return -1; - } - - if (!(ti.flags & INFO_DO_HIDE)) - pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); - - if (ident) { - addresource(sd, ident, xobj_id); - RELEASE(ident); - } - - pdf_release_obj(fspec); - - return 0; -} - -/* Use do_names instead. */ -static int -spc_handler_pdfm_dest (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *name, *array; - - skip_white(&args->curptr, args->endptr); - - name = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!name) { - spc_warn(spe, "PDF string expected for destination name but not found."); - return -1; - } else if (!PDF_OBJ_STRINGTYPE(name)) { - spc_warn(spe, "PDF string expected for destination name but invalid type."); - pdf_release_obj(name); - return -1; - } - -#ifdef XETEX -#ifdef ENABLE_TOUNICODE - if (maybe_reencode_utf8(name) < 0) - WARN("Failed to convert input string to UTF16..."); -#endif -#endif - - array = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!array) { - spc_warn(spe, "No destination specified for pdf:dest."); - pdf_release_obj(name); - return -1; - } else if (!PDF_OBJ_ARRAYTYPE(array)) { - spc_warn(spe, "Destination not specified as an array object!"); - pdf_release_obj(name); - pdf_release_obj(array); - return -1; - } - - pdf_doc_add_names("Dests", - pdf_string_value (name), - pdf_string_length(name), - array); - pdf_release_obj(name); - - return 0; -} - -static int -spc_handler_pdfm_names (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *category, *key, *value, *tmp; - int i, size; - - category = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!category) { - spc_warn(spe, "PDF name expected but not found."); - return -1; - } else if (!PDF_OBJ_NAMETYPE(category)) { - spc_warn(spe, "PDF name expected but not found."); - pdf_release_obj(category); - return -1; - } - - tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "PDF object expected but not found."); - pdf_release_obj(category); - return -1; - } else if (PDF_OBJ_ARRAYTYPE(tmp)) { - size = pdf_array_length(tmp); - if (size % 2 != 0) { - spc_warn(spe, "Array size not multiple of 2 for pdf:names."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } - - for (i = 0; i < size / 2; i++) { - key = pdf_get_array(tmp, 2 * i); - value = pdf_get_array(tmp, 2 * i + 1); - if (!PDF_OBJ_STRINGTYPE(key)) { - spc_warn(spe, "Name tree key must be string."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } else if (pdf_doc_add_names(pdf_name_value(category), - pdf_string_value (key), - pdf_string_length(key), - pdf_link_obj(value)) < 0) { - spc_warn(spe, "Failed to add Name tree entry..."); - pdf_release_obj(category); - pdf_release_obj(tmp); - return -1; - } - } - pdf_release_obj(tmp); - } else if (PDF_OBJ_STRINGTYPE(tmp)) { - key = tmp; - value = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!value) { - pdf_release_obj(category); - pdf_release_obj(key); - spc_warn(spe, "PDF object expected but not found."); - return -1; - } - if (pdf_doc_add_names(pdf_name_value(category), - pdf_string_value (key), - pdf_string_length(key), - value) < 0) { - spc_warn(spe, "Failed to add Name tree entry..."); - pdf_release_obj(category); - pdf_release_obj(key); - return -1; - } - pdf_release_obj(key); - } else { - pdf_release_obj(tmp); - pdf_release_obj(category); - spc_warn(spe, "Invalid object type for pdf:names."); - return -1; - } - pdf_release_obj(category); - - return 0; -} - -static int -spc_handler_pdfm_docinfo (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *docinfo, *dict; - -#ifdef ENABLE_TOUNICODE - dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!dict) { - spc_warn(spe, "Dictionary object expected but not found."); - return -1; - } - - docinfo = pdf_doc_docinfo(); - pdf_merge_dict(docinfo, dict); - pdf_release_obj(dict); - - return 0; -} - -static int -spc_handler_pdfm_docview (struct spc_env *spe, struct spc_arg *args) -{ -#ifdef ENABLE_TOUNICODE - struct spc_pdf_ *sd = &_pdf_stat; -#endif /* ENABLE_TOUNICODE */ - pdf_obj *catalog, *dict; - pdf_obj *pref_old, *pref_add; - -#ifdef ENABLE_TOUNICODE - dict = my_parse_pdf_dict(&args->curptr, args->endptr, &sd->cd); -#else - dict = parse_pdf_dict(&args->curptr, args->endptr, NULL); -#endif /* ENABLE_TOUNICODE */ - if (!dict) { - spc_warn(spe, "Dictionary object expected but not found."); - return -1; - } - - catalog = pdf_doc_catalog(); - /* Avoid overriding whole ViewerPreferences */ - pref_old = pdf_lookup_dict(catalog, "ViewerPreferences"); - pref_add = pdf_lookup_dict(dict, "ViewerPreferences"); - if (pref_old && pref_add) { - pdf_merge_dict (pref_old, pref_add); - pdf_remove_dict(dict, "ViewerPreferences"); - } - pdf_merge_dict (catalog, dict); - pdf_release_obj(dict); - - return 0; -} - -static int -spc_handler_pdfm_close (struct spc_env *spe, struct spc_arg *args) -{ - char *ident; - - skip_white(&args->curptr, args->endptr); - ident = parse_opt_ident(&args->curptr, args->endptr); - if (ident) { - spc_flush_object(ident); - RELEASE(ident); - } else { /* Close all? */ - spc_clear_objects(); - } - - return 0; -} - -static int -spc_handler_pdfm_object (struct spc_env *spe, struct spc_arg *args) -{ - char *ident; - pdf_obj *object; - - skip_white(&args->curptr, args->endptr); - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Could not find a object identifier."); - return -1; - } - - object = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!object) { - spc_warn(spe, "Could not find an object definition for \"%s\".", ident); - RELEASE(ident); - return -1; - } else { - spc_push_object(ident, object); - } - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_content (struct spc_env *spe, struct spc_arg *args) -{ - long len = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr < args->endptr) { - pdf_tmatrix M; - - pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user, spe->y_user); - work_buffer[len++] = ' '; - work_buffer[len++] = 'q'; - work_buffer[len++] = ' '; - len += pdf_sprint_matrix(work_buffer + len, &M); - work_buffer[len++] = ' '; - work_buffer[len++] = 'c'; - work_buffer[len++] = 'm'; - work_buffer[len++] = ' '; - - pdf_doc_add_page_content(work_buffer, len); /* op: q cm */ - len = (long) (args->endptr - args->curptr); - pdf_doc_add_page_content(args->curptr, len); /* op: ANY */ - pdf_doc_add_page_content(" Q", 2); /* op: Q */ - } - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_literal (struct spc_env *spe, struct spc_arg *args) -{ - int direct = 0; - - skip_white(&args->curptr, args->endptr); - while (args->curptr < args->endptr) { - if (args->curptr + 7 <= args->endptr && - !strncmp(args->curptr, "reverse", 7)) { - args->curptr += 7; - WARN("The special \"pdf:literal reverse ...\" is no longer supported.\nIgnore the \"reverse\" option."); - } else if (args->curptr + 6 <= args->endptr && - !strncmp(args->curptr, "direct", 6)) { - direct = 1; - args->curptr += 6; - } else { - break; - } - skip_white(&args->curptr, args->endptr); - } - - if (args->curptr < args->endptr) { - pdf_tmatrix M; - if (!direct) { - M.a = M.d = 1.0; M.b = M.c = 0.0; - M.e = spe->x_user; M.f = spe->y_user; - pdf_dev_concat(&M); - } - pdf_doc_add_page_content(" ", 1); /* op: */ - pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ - if (!direct) { - M.e = -spe->x_user; M.f = -spe->y_user; - pdf_dev_concat(&M); - } - } - - args->curptr = args->endptr; - - return 0; -} - -static int -spc_handler_pdfm_bcontent (struct spc_env *spe, struct spc_arg *args) -{ - pdf_tmatrix M; - double xpos, ypos; - - pdf_dev_gsave(); - pdf_dev_get_coord(&xpos, &ypos); - pdf_setmatrix(&M, 1.0, 0.0, 0.0, 1.0, spe->x_user - xpos, spe->y_user - ypos); - pdf_dev_concat(&M); - pdf_dev_push_coord(spe->x_user, spe->y_user); - return 0; -} - -static int -spc_handler_pdfm_econtent (struct spc_env *spe, struct spc_arg *args) -{ - pdf_dev_pop_coord(); - pdf_dev_grestore(); - return 0; -} - -static int -spc_handler_pdfm_code (struct spc_env *spe, struct spc_arg *args) -{ - skip_white(&args->curptr, args->endptr); - - if (args->curptr < args->endptr) { - pdf_doc_add_page_content(" ", 1); /* op: */ - pdf_doc_add_page_content(args->curptr, (long) (args->endptr - args->curptr)); /* op: ANY */ - args->curptr = args->endptr; - } - - return 0; -} - -static int -spc_handler_pdfm_do_nothing (struct spc_env *spe, struct spc_arg *args) -{ - args->curptr = args->endptr; - return 0; -} - -#define STRING_STREAM 0 -#define FILE_STREAM 1 - -static int -spc_handler_pdfm_stream_with_type (struct spc_env *spe, struct spc_arg *args, int type) -{ - pdf_obj *fstream; - long nb_read; - char *ident, *instring, *fullname; - pdf_obj *tmp; - FILE *fp; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "Missing objname for pdf:(f)stream."); - return -1; - } - - skip_white(&args->curptr, args->endptr); - - tmp = parse_pdf_object(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "Missing input string for pdf:(f)stream."); - RELEASE(ident); - return -1; - } else if (!PDF_OBJ_STRINGTYPE(tmp)) { - spc_warn(spe, "Invalid type of input string for pdf:(f)stream."); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - - instring = pdf_string_value(tmp); - - switch (type) { - case FILE_STREAM: - if (!instring) { - spc_warn(spe, "Missing filename for pdf:fstream."); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - fullname = kpse_find_pict(instring); - if (!fullname) { - spc_warn(spe, "File \"%s\" not found.", instring); - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - fp = DPXFOPEN(fullname, DPX_RES_TYPE_BINARY); - if (!fp) { - spc_warn(spe, "Could not open file: %s", instring); - pdf_release_obj(tmp); - RELEASE(ident); - RELEASE(fullname); - return -1; - } - fstream = pdf_new_stream(STREAM_COMPRESS); - while ((nb_read = - fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0) - pdf_add_stream(fstream, work_buffer, nb_read); - MFCLOSE(fp); - RELEASE(fullname); - break; - case STRING_STREAM: - fstream = pdf_new_stream(STREAM_COMPRESS); - if (instring) - pdf_add_stream(fstream, instring, strlen(instring)); - break; - default: - pdf_release_obj(tmp); - RELEASE(ident); - return -1; - } - pdf_release_obj(tmp); - - /* - * Optional dict. - * - * TODO: check Length, Filter... - */ - skip_white(&args->curptr, args->endptr); - - if (args->curptr[0] == '<') { - pdf_obj *stream_dict; - - stream_dict = pdf_stream_dict(fstream); - - tmp = parse_pdf_dict(&args->curptr, args->endptr, NULL); - if (!tmp) { - spc_warn(spe, "Parsing dictionary failed."); - pdf_release_obj(fstream); - RELEASE(ident); - return -1; - } - if (pdf_lookup_dict(tmp, "Length")) { - pdf_remove_dict(tmp, "Length"); - } else if (pdf_lookup_dict(tmp, "Filter")) { - pdf_remove_dict(tmp, "Filter"); - } - pdf_merge_dict(stream_dict, tmp); - pdf_release_obj(tmp); - } - - /* Users should explicitly close this. */ - spc_push_object(ident, fstream); - RELEASE(ident); - - return 0; -} - -/* - * STREAM: Create a PDF stream object from an input string. - * - * pdf: stream @objname (input_string) [PDF_DICT] - */ -static int -spc_handler_pdfm_stream (struct spc_env *spe, struct spc_arg *args) -{ - return spc_handler_pdfm_stream_with_type (spe, args, STRING_STREAM); -} - -/* - * FSTREAM: Create a PDF stream object from an existing file. - * - * pdf: fstream @objname (filename) [PDF_DICT] - */ -static int -spc_handler_pdfm_fstream (struct spc_env *spe, struct spc_arg *args) -{ - return spc_handler_pdfm_stream_with_type (spe, args, FILE_STREAM); -} - -/* Grab page content as follows: - * - * Reference point = (x_user, y_user) - * - * Case 1. \special{pdf:bxobj @obj width WD height HT depth DP} - * - * Grab the box with the lower-left corner (x_user, y_user-DP) - * and the upper right corner (x_user+WD, y_user+HT). - * - * Case 2. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} - * - * Grab the box with the lower-left corner (x_user+LLX, y_user+LLY) - * and the upper right corner (x_user+URX, y_user+URY). - * - * Note that scale, xscale, yscale, xoffset, yoffset options are ignored. - */ -static int -spc_handler_pdfm_bform (struct spc_env *spe, struct spc_arg *args) -{ - int xobj_id; - char *ident; - pdf_rect cropbox; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "A form XObject must have name."); - return -1; - } - - transform_info_clear(&ti); - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(ident); - return -1; - } - - /* A XForm with zero dimension results in a non-invertible transformation - * matrix. And it may result in unpredictable behaviour. It might be an - * error in Acrobat. Bounding box with zero dimension may cause division - * by zero. - */ - if (ti.flags & INFO_HAS_USER_BBOX) { - if (ti.bbox.urx - ti.bbox.llx == 0.0 || - ti.bbox.ury - ti.bbox.lly == 0.0) { - spc_warn(spe, "Bounding box has a zero dimension."); - RELEASE(ident); - return -1; - } - cropbox.llx = ti.bbox.llx; - cropbox.lly = ti.bbox.lly; - cropbox.urx = ti.bbox.urx; - cropbox.ury = ti.bbox.ury; - } else { - if (ti.width == 0.0 || - ti.depth + ti.height == 0.0) { - spc_warn(spe, "Bounding box has a zero dimension."); - RELEASE(ident); - return -1; - } - cropbox.llx = 0.0; - cropbox.lly = -ti.depth; - cropbox.urx = ti.width; - cropbox.ury = ti.height; - } - - xobj_id = pdf_doc_begin_grabbing(ident, spe->x_user, spe->y_user, &cropbox); - - if (xobj_id < 0) { - RELEASE(ident); - spc_warn(spe, "Couldn't start form object."); - return -1; - } - - spc_push_object(ident, pdf_ximage_get_reference(xobj_id)); - RELEASE(ident); - - return 0; -} - -/* An extra dictionary after exobj must be merged to the form dictionary, - * not resource dictionary. - * Please use pdf:put @resources (before pdf:exobj) instead. - */ -static int -spc_handler_pdfm_eform (struct spc_env *spe, struct spc_arg *args) -{ - pdf_obj *attrib = NULL; - - skip_white(&args->curptr, args->endptr); - - if (args->curptr < args->endptr) { - attrib = parse_pdf_dict(&args->curptr, args->endptr, NULL); - if (attrib && !PDF_OBJ_DICTTYPE(attrib)) { - pdf_release_obj(attrib); - attrib = NULL; - } - } - pdf_doc_end_grabbing(attrib); - - return 0; -} - -/* Saved XObjects can be used as follows: - * - * Reference point = (x_user, y_user) - * - * Case 1. \special{pdf:uxobj @obj width WD height HT depth DP} - * - * Scale the XObject to fit in the box - * [x_user, y_user-DP, x_user+WD, y_user+HT]. - * - * Case 2. \special{pdf:uxobj @obj xscale XS yscale YS} - * - * Scale the XObject with XS and YS. Note that width and xscale - * or height and yscale cannot be used together. - * - * Case 3. \special{pdf:bxobj @obj bbox LLX LLY URX, URY} - * - * Scale the XObject to fit in the box - * [x_user+LLX, y_user+LLY, x_user+URX, y_user+URY]. - * - * Note that xoffset and yoffset moves the reference point where the - * lower-left corner of the XObject will be put. - */ -static int -spc_handler_pdfm_uxobj (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - int xobj_id; - char *ident; - transform_info ti; - - skip_white(&args->curptr, args->endptr); - - ident = parse_opt_ident(&args->curptr, args->endptr); - if (!ident) { - spc_warn(spe, "No object identifier given."); - return -1; - } - - transform_info_clear(&ti); - if (args->curptr < args->endptr) { - if (spc_util_read_dimtrns(spe, &ti, args, NULL, 0) < 0) { - RELEASE(ident); - return -1; - } - } - - /* Dvipdfmx was suddenly changed to use file name to identify - * external images. We can't use ident to find image resource - * here. - */ - xobj_id = findresource(sd, ident); - if (xobj_id < 0) { - xobj_id = pdf_ximage_findresource(ident, 0, NULL); - if (xobj_id < 0) { - spc_warn(spe, "Specified (image) object doesn't exist: %s", ident); - RELEASE(ident); - return -1; - } - } - - pdf_dev_put_image(xobj_id, &ti, spe->x_user, spe->y_user); - RELEASE(ident); - - return 0; -} - -static int -spc_handler_pdfm_link (struct spc_env *spe, struct spc_arg *args) -{ - return spc_resume_annot(spe); -} - -static int -spc_handler_pdfm_nolink (struct spc_env *spe, struct spc_arg *args) -{ - return spc_suspend_annot(spe); -} - - - -/* Handled at BOP */ -static int -spc_handler_pdfm_pagesize (struct spc_env *spe, struct spc_arg *args) -{ - args->curptr = args->endptr; - - return 0; -} - -/* Please remove this. - * This should be handled before processing pages! - */ -static int -spc_handler_pdfm_bgcolor (struct spc_env *spe, struct spc_arg *args) -{ - int error; - pdf_color colorspec; - - error = spc_util_read_colorspec(spe, &colorspec, args, 0); - if (error) - spc_warn(spe, "No valid color specified?"); - else { - pdf_doc_set_bgcolor(&colorspec); - } - - return error; -} - -static int -spc_handler_pdfm_mapline (struct spc_env *spe, struct spc_arg *ap) -{ - fontmap_rec *mrec; - char *map_name, opchr; - int error = 0; - - skip_white(&ap->curptr, ap->endptr); - if (ap->curptr >= ap->endptr) { - spc_warn(spe, "Empty mapline special?"); - return -1; - } - - opchr = ap->curptr[0]; - if (opchr == '-' || opchr == '+') - ap->curptr++; - - skip_white(&ap->curptr, ap->endptr); - - switch (opchr) { - case '-': - map_name = parse_ident(&ap->curptr, ap->endptr); - if (map_name) { - pdf_remove_fontmap_record(map_name); - RELEASE(map_name); - } else { - spc_warn(spe, "Invalid fontmap line: Missing TFM name."); - error = -1; - } - break; - case '+': - mrec = NEW(1, fontmap_rec); - pdf_init_fontmap_record(mrec); - error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); - if (error) - spc_warn(spe, "Invalid fontmap line."); - else { - pdf_append_fontmap_record(mrec->map_name, mrec); - } - pdf_clear_fontmap_record(mrec); - RELEASE(mrec); - break; - default: - mrec = NEW(1, fontmap_rec); - pdf_init_fontmap_record(mrec); - error = pdf_read_fontmap_line(mrec, ap->curptr, (long) (ap->endptr - ap->curptr), is_pdfm_mapline(ap->curptr)); - if (error) - spc_warn(spe, "Invalid fontmap line."); - else { - pdf_insert_fontmap_record(mrec->map_name, mrec); - } - pdf_clear_fontmap_record(mrec); - RELEASE(mrec); - break; - } - if (!error) - ap->curptr = ap->endptr; - - return 0; -} - -static int -spc_handler_pdfm_mapfile (struct spc_env *spe, struct spc_arg *args) -{ - char *mapfile; - int mode, error = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr >= args->endptr) - return 0; - - switch (args->curptr[0]) { - case '-': - mode = FONTMAP_RMODE_REMOVE; - args->curptr++; - break; - case '+': - mode = FONTMAP_RMODE_APPEND; - args->curptr++; - break; - default: - mode = FONTMAP_RMODE_REPLACE; - break; - } - - mapfile = parse_val_ident(&args->curptr, args->endptr); - if (!mapfile) { - spc_warn(spe, "No fontmap file specified."); - return -1; - } else { - error = pdf_load_fontmap_file(mapfile, mode); - } - RELEASE(mapfile); - - return error; -} - - -#ifdef ENABLE_TOUNICODE -static int -spc_handler_pdfm_tounicode (struct spc_env *spe, struct spc_arg *args) -{ - struct spc_pdf_ *sd = &_pdf_stat; - char *cmap_name; - - /* First clear */ - sd->cd.cmap_id = -1; - sd->cd.unescape_backslash = 0; - - skip_white(&args->curptr, args->endptr); - if (args->curptr >= args->endptr) { - spc_warn(spe, "Missing CMap name for pdf:tounicode."); - return -1; - } - - /* _FIXME_ - * Any valid char allowed for PDF name object should be allowed here. - * The argument to this special should be a PDF name obejct. - * But it's too late to change this special. - */ - cmap_name = parse_ident(&args->curptr, args->endptr); - if (!cmap_name) { - spc_warn(spe, "Missing ToUnicode mapping name..."); - 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); - 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 (sd->cd.cmap_id >= 0) { - if (strstr(cmap_name, "RKSJ") || - strstr(cmap_name, "B5") || - strstr(cmap_name, "GBK") || - strstr(cmap_name, "KSC")) - sd->cd.unescape_backslash = 1; - } - RELEASE(cmap_name); - return 0; -} -#endif /* ENABLE_TOUNICODE */ - - -static struct spc_handler pdfm_handlers[] = { - {"annotation", spc_handler_pdfm_annot}, - {"annotate", spc_handler_pdfm_annot}, - {"annot", spc_handler_pdfm_annot}, - {"ann", spc_handler_pdfm_annot}, - - {"outline", spc_handler_pdfm_outline}, - {"out", spc_handler_pdfm_outline}, - - {"article", spc_handler_pdfm_article}, - {"art", spc_handler_pdfm_article}, - - {"bead", spc_handler_pdfm_bead}, - {"thread", spc_handler_pdfm_bead}, - - {"destination", spc_handler_pdfm_dest}, - {"dest", spc_handler_pdfm_dest}, - - - {"object", spc_handler_pdfm_object}, - {"obj", spc_handler_pdfm_object}, - - - {"docinfo", spc_handler_pdfm_docinfo}, - {"docview", spc_handler_pdfm_docview}, - - {"content", spc_handler_pdfm_content}, - {"put", spc_handler_pdfm_put}, - {"close", spc_handler_pdfm_close}, - {"bop", spc_handler_pdfm_bop}, - {"eop", spc_handler_pdfm_eop}, - - {"image", spc_handler_pdfm_image}, - {"img", spc_handler_pdfm_image}, - {"epdf", spc_handler_pdfm_image}, - - {"link", spc_handler_pdfm_link}, - {"nolink", spc_handler_pdfm_nolink}, - - {"begincolor", spc_handler_pdfm_bcolor}, - {"bcolor", spc_handler_pdfm_bcolor}, - {"bc", spc_handler_pdfm_bcolor}, - - {"setcolor", spc_handler_pdfm_scolor}, - {"scolor", spc_handler_pdfm_scolor}, - {"sc", spc_handler_pdfm_scolor}, - - {"endcolor", spc_handler_pdfm_ecolor}, - {"ecolor", spc_handler_pdfm_ecolor}, - {"ec", spc_handler_pdfm_ecolor}, - - {"begingray", spc_handler_pdfm_bcolor}, - {"bgray", spc_handler_pdfm_bcolor}, - {"bg", spc_handler_pdfm_bcolor}, - - {"endgray", spc_handler_pdfm_ecolor}, - {"egray", spc_handler_pdfm_ecolor}, - {"eg", spc_handler_pdfm_ecolor}, - - {"bgcolor", spc_handler_pdfm_bgcolor}, - {"bgc", spc_handler_pdfm_bgcolor}, - {"bbc", spc_handler_pdfm_bgcolor}, - {"bbg", spc_handler_pdfm_bgcolor}, - - {"pagesize", spc_handler_pdfm_pagesize}, - - {"bannot", spc_handler_pdfm_bann}, - {"beginann", spc_handler_pdfm_bann}, - {"bann", spc_handler_pdfm_bann}, - - {"eannot", spc_handler_pdfm_eann}, - {"endann", spc_handler_pdfm_eann}, - {"eann", spc_handler_pdfm_eann}, - - {"btrans", spc_handler_pdfm_btrans}, - {"begintransform", spc_handler_pdfm_btrans}, - {"begintrans", spc_handler_pdfm_btrans}, - {"bt", spc_handler_pdfm_btrans}, - - {"etrans", spc_handler_pdfm_etrans}, - {"endtransform", spc_handler_pdfm_etrans}, - {"endtrans", spc_handler_pdfm_etrans}, - {"et", spc_handler_pdfm_etrans}, - - {"bform", spc_handler_pdfm_bform}, - {"beginxobj", spc_handler_pdfm_bform}, - {"bxobj", spc_handler_pdfm_bform}, - - {"eform", spc_handler_pdfm_eform}, - {"endxobj", spc_handler_pdfm_eform}, - {"exobj", spc_handler_pdfm_eform}, - - {"usexobj", spc_handler_pdfm_uxobj}, - {"uxobj", spc_handler_pdfm_uxobj}, - -#ifdef ENABLE_TOUNICODE - {"tounicode", spc_handler_pdfm_tounicode}, -#endif /* ENABLE_TOUNICODE */ - {"literal", spc_handler_pdfm_literal}, - {"stream", spc_handler_pdfm_stream}, - {"fstream", spc_handler_pdfm_fstream}, - {"names", spc_handler_pdfm_names}, - {"mapline", spc_handler_pdfm_mapline}, - {"mapfile", spc_handler_pdfm_mapfile}, - - {"bcontent", spc_handler_pdfm_bcontent}, - {"econtent", spc_handler_pdfm_econtent}, - {"code", spc_handler_pdfm_code}, - - {"minorversion", spc_handler_pdfm_do_nothing}, - {"encrypt", spc_handler_pdfm_do_nothing}, -}; - -int -spc_pdfm_check_special (const char *buf, long len) -{ - int r = 0; - const char *p, *endptr; - - p = buf; - endptr = p + len; - - skip_white(&p, endptr); - if (p + strlen("pdf:") <= endptr && - !memcmp(p, "pdf:", strlen("pdf:"))) { - r = 1; - } - - return r; -} - -int -spc_pdfm_setup_handler (struct spc_handler *sph, - struct spc_env *spe, struct spc_arg *ap) -{ - int error = -1, i; - char *q; - - ASSERT(sph && spe && ap); - - skip_white(&ap->curptr, ap->endptr); - if (ap->curptr + strlen("pdf:") >= ap->endptr || - memcmp(ap->curptr, "pdf:", strlen("pdf:"))) { - spc_warn(spe, "Not pdf: special???"); - return -1; - } - ap->curptr += strlen("pdf:"); - - skip_white(&ap->curptr, ap->endptr); - q = parse_c_ident(&ap->curptr, ap->endptr); - if (q) { - for (i = 0; - i < sizeof(pdfm_handlers) / sizeof(struct spc_handler); i++) { - if (!strcmp(q, pdfm_handlers[i].key)) { - ap->command = pdfm_handlers[i].key; - sph->key = "pdf:"; - sph->exec = pdfm_handlers[i].exec; - skip_white(&ap->curptr, ap->endptr); - error = 0; - break; - } - } - RELEASE(q); - } - - return error; -} - diff --git a/Build/source/texk/dvipdfm-x/xsrc/spc_tpic.c b/Build/source/texk/dvipdfm-x/xsrc/spc_tpic.c deleted file mode 100644 index 1e5f196e737..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/spc_tpic.c +++ /dev/null @@ -1,1130 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2012 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. -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "numbers.h" -#include "dpxutil.h" - -#include "pdfdoc.h" - -#include "pdfdraw.h" -#include "pdfdev.h" - -#include "specials.h" -#include "spc_tpic.h" - -#define DEBUG 1 -#define ENABLE_SPC_NAMESPACE 1 - -/* - * Following "constant" converts milli-inches to - * device (in this case PDF stream) coordinates. - */ - -#define MI2DEV (0.072/pdf_dev_scale()) - -/* - * Value for 'sh' command 'g' is interpreted as - * - * gray color value 1-g for "solid" - * opacity value g for "opacity" - * shape value g for "shape" - */ -#define TPIC_MODE__FILL_SOLID 0 -#define TPIC_MODE__FILL_OPACITY 1 -#define TPIC_MODE__FILL_SHAPE 2 - -#ifndef ISBLANK -# define ISBLANK(c) ( (c) == ' ' || (c) == '\t' ) -#endif - -static void -skip_blank (const char **pp, const char *endptr) -{ - const char *p = *pp; - for ( ; p < endptr && ISBLANK(*p); p++); - *pp = p; -} - -struct spc_tpic_ -{ - struct { - int fill; - } mode; - - /* state */ - double pen_size; - int fill_shape; /* boolean */ - double fill_color; - - pdf_coord *points; - int num_points; - int max_points; -}; - -#if 1 -static struct spc_tpic_ _tpic_state; -#endif - -/* We use pdf_doc_add_page_content() here - * since we always draw isolated graphics. - */ -static void -tpic__clear (struct spc_tpic_ *tp) -{ - if (tp->points) { - RELEASE(tp->points); - tp->points = NULL; - } - tp->num_points = 0; - tp->max_points = 0; - tp->fill_shape = 0; - tp->fill_color = 0.0; -} - - -static pdf_obj * -create_xgstate (double a /* alpha */, int f_ais /* alpha is shape */) -{ - pdf_obj *dict; - - dict = pdf_new_dict(); - pdf_add_dict(dict, - pdf_new_name("Type"), - pdf_new_name("ExtGState")); - if (f_ais) { - pdf_add_dict(dict, - pdf_new_name("AIS"), - pdf_new_boolean(1)); - } - pdf_add_dict(dict, - pdf_new_name("ca"), - pdf_new_number(a)); - - return dict; -} - -static int -check_resourcestatus (const char *category, const char *resname) -{ - pdf_obj *dict1, *dict2; - - dict1 = pdf_doc_current_page_resources(); - if (!dict1) - return 0; - - dict2 = pdf_lookup_dict(dict1, category); - if (dict2 && - pdf_obj_typeof(dict2) == PDF_DICT) { - if (pdf_lookup_dict(dict2, resname)) - return 1; - } - return 0; -} - -static int -set_linestyle (double pn, double da) -{ - double dp[2]; /* dash pattern */ - - pdf_dev_setlinejoin(1); - pdf_dev_setmiterlimit(1.4); - pdf_dev_setlinewidth(pn); - if (da > 0.0) { - dp[0] = da * 72.0; - pdf_dev_setdash(1, dp, 0); - pdf_dev_setlinecap(0); - } else if (da < 0.0) { - dp[0] = pn; - dp[1] = -da * 72.0; - pdf_dev_setdash(2, dp, 0); - pdf_dev_setlinecap(1); - } else { - pdf_dev_setlinecap(0); - } - pdf_doc_add_page_content(" 0 G", 4); - - return 0; -} - -static int -set_fillstyle (double g, double a, int f_ais) -{ - pdf_obj *dict; - char resname[32]; - char buf[32]; - int alp, len = 0; - - if (a > 0.0) { - alp = round(100.0 * a); - sprintf(resname, "_Tps_a%03d_", alp); - if (!check_resourcestatus("ExtGState", resname)) { - dict = create_xgstate(ROUND(0.01 * alp, 0.01), f_ais); - pdf_doc_add_page_resource("ExtGState", - resname, pdf_ref_obj(dict)); - pdf_release_obj(dict); - } - len += sprintf(buf + len, " /%s gs", resname); - } - len += sprintf(buf + len, " %.2f g", g); - - pdf_doc_add_page_content(buf, len); - - return 0; -} - -static void -set_styles (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_fs, - int f_vp, - double pn, - double da) { - pdf_tmatrix M; - - pdf_setmatrix (&M, 1.0, 0.0, 0.0, -1.0, c->x, c->y); - pdf_dev_concat(&M); - - if (f_vp) - set_linestyle(pn, da); - - if (f_fs) { - double g, a; - int f_ais; - -#ifdef XETEX - switch (tp->mode.fill) { - case TPIC_MODE__FILL_SOLID: - g = 1.0 - tp->fill_color; - a = 0.0; - break; - case TPIC_MODE__FILL_SHAPE: - case TPIC_MODE__FILL_OPACITY: - if (tp->fill_color > 0.0) { - a = tp->fill_color; - g = 0.0; - } else { - a = 0.0; - g = 1.0; - } - break; - default: - g = 0.5; - a = 0.0; - } -#else - if (tp->mode.fill == TPIC_MODE__FILL_SOLID || !tp->fill_color) { - g = 1.0 - tp->fill_color; - a = 0.0; - } else { - g = 0.0; - a = tp->fill_color; - } -#endif - - f_ais = (tp->mode.fill == TPIC_MODE__FILL_SHAPE) ? 1 : 0; - - set_fillstyle(g, a, f_ais); - } -} - -static void -showpath (int f_vp, int f_fs) /* visible_path, fill_shape */ -{ - if (f_vp) { - if (f_fs) - pdf_dev_flushpath('b', PDF_FILL_RULE_NONZERO); - else { - pdf_dev_flushpath('S', PDF_FILL_RULE_NONZERO); - } - } else { - /* - * Acrobat claims 'Q' as illegal operation when there are unfinished - * path (a path without path-painting operator applied)? - */ - if (f_fs) - pdf_dev_flushpath('f', PDF_FILL_RULE_NONZERO); - else { - pdf_dev_newpath(); - } - } -} - -#define CLOSED_PATH(s) (\ - (s)->points[0].x == (s)->points[(s)->num_points-1].x && \ - (s)->points[0].y == (s)->points[(s)->num_points-1].y \ -) - -static int -tpic__polyline (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da) -{ - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - int i, error = 0; - - /* Shading is applied only to closed path. */ - f_fs = CLOSED_PATH(tp) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_moveto(tp->points[0].x, tp->points[0].y); - for (i = 0; i < tp->num_points; i++) - pdf_dev_lineto(tp->points[i].x, tp->points[i].y); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - - tpic__clear(tp); - - return error; -} - -/* - * Accroding to - * "Tpic: Pic for TEX", Tim Morgan, Original by Brian Kernighan, p.20: - * - * A spline is a smooth curve guided by a set of straight lines just - * like the line above. It begins at the same place, ends at the same - * place, and in between is tangent to the mid-point of each guiding - * line. The syntax for a spline is identical to a (path) line except - * for using spline instead of line. - * - * Spline is not a curve drawn by spline-fitting points p0, p1, ..., pn, - * defined by tpic special "pa" command. Instead, a path defined by set - * of points p0, p1, ... is guiding line mentioned above. - * - * Dvipsk draws them as a straight line from p0 to q1 = (p0 + p1)/2, - * followed by a quadratic B-spline curve with starting point q1, (off- - * curve) control point p1, end point q2 = (p1 + p2)/2, ..., and a - * straight line from qn to pn. - */ - -static int -tpic__spline (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da) -{ - double v[6]; - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - int i, error = 0; - - f_fs = CLOSED_PATH(tp) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_moveto(tp->points[0].x, tp->points[0].y); - - v[0] = 0.5 * (tp->points[0].x + tp->points[1].x); - v[1] = 0.5 * (tp->points[0].y + tp->points[1].y); - pdf_dev_lineto(v[0], v[1]); - for (i = 1; i < tp->num_points - 1; i++) { - /* B-spline control points */ - v[0] = 0.5 * (tp->points[i-1].x + tp->points[i].x); - v[1] = 0.5 * (tp->points[i-1].y + tp->points[i].y); - v[2] = tp->points[i].x; - v[3] = tp->points[i].y; - v[4] = 0.5 * (tp->points[i].x + tp->points[i+1].x); - v[5] = 0.5 * (tp->points[i].y + tp->points[i+1].y); - pdf_dev_bspline(v[0], v[1], v[2], v[3], v[4], v[5]); - } - pdf_dev_lineto(tp->points[i].x, tp->points[i].y); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - tpic__clear(tp); - - return error; -} - -static int -tpic__arc (struct spc_tpic_ *tp, - const pdf_coord *c, - int f_vp, - double da, - double *v /* 6 numbers */ ) -{ - double pn = tp->pen_size; - int f_fs = tp->fill_shape; - - f_fs = (round(fabs(v[4] - v[5]) + 0.5) >= 360) ? f_fs : 0; - f_vp = (pn > 0.0) ? f_vp : 0; - - if (f_vp || f_fs) { - pdf_dev_gsave(); - - set_styles(tp, c, f_fs, f_vp, pn, da); - - pdf_dev_arcx(v[0], v[1], v[2], v[3], v[4], v[5], +1, 0.0); - - showpath(f_vp, f_fs); - - pdf_dev_grestore(); - } - tpic__clear(tp); - - return 0; -} - -#if 1 -static int -spc_currentpoint (struct spc_env *spe, long *pg, pdf_coord *cp) -{ - *pg = 0; - cp->x = spe->x_user; - cp->y = spe->y_user; - return 0; -} -#endif - -static int -spc_handler_tpic_pn (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid pen size specified?"); - return -1; - } - tp->pen_size = atof(q) * MI2DEV; - RELEASE(q); - - return 0; -} - -static int -spc_handler_tpic_pa (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - int i; - double v[2]; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 2 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Missing numbers for TPIC \"pa\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 2) { - spc_warn(spe, "Invalid arg for TPIC \"pa\" command."); - return -1; - } - - if (tp->num_points >= tp->max_points) { - tp->max_points += 256; - tp->points = RENEW(tp->points, tp->max_points, pdf_coord); - } - tp->points[tp->num_points].x = v[0] * MI2DEV; - tp->points[tp->num_points].y = v[1] * MI2DEV; - tp->num_points += 1; - - return 0; -} - -static int -spc_handler_tpic_fp (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, 0.0); -} - -static int -spc_handler_tpic_ip (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 0, 0.0); -} - -static int -spc_handler_tpic_da (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = atof(q); - RELEASE(q); - } - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_dt (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = -atof(q); - RELEASE(q); - } - if (tp->num_points <= 1) { - spc_warn(spe, "Too few points (< 2) for polyline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__polyline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_sp (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - double da = 0.0; - pdf_coord cp; - long pg; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - da = atof(q); - RELEASE(q); - } - if (tp->num_points <= 2) { - spc_warn(spe, "Too few points (< 3) for spline path."); - return -1; - } - - spc_currentpoint(spe, &pg, &cp); - - return tpic__spline(tp, &cp, 1, da); -} - -static int -spc_handler_tpic_ar (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - double v[6]; - pdf_coord cp; - long pg; - char *q; - int i; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 6 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid args. in TPIC \"ar\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 6) { - spc_warn(spe, "Invalid arg for TPIC \"ar\" command."); - return -1; - } - - v[0] *= MI2DEV; v[1] *= MI2DEV; - v[2] *= MI2DEV; v[3] *= MI2DEV; - v[4] *= 180.0 / M_PI; - v[5] *= 180.0 / M_PI; - - spc_currentpoint(spe, &pg, &cp); - - return tpic__arc(tp, &cp, 1, 0.0, v); -} - -static int -spc_handler_tpic_ia (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - double v[6]; - pdf_coord cp; - long pg; - char *q; - int i; - - ASSERT(spe && ap && tp); - - skip_blank(&ap->curptr, ap->endptr); - for (i = 0; - i < 6 && ap->curptr < ap->endptr; i++) { - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (!q) { - spc_warn(spe, "Invalid args. in TPIC \"ia\" command."); - return -1; - } - v[i] = atof(q); - RELEASE(q); - skip_blank(&ap->curptr, ap->endptr); - } - if (i != 6) { - spc_warn(spe, "Invalid arg for TPIC \"ia\" command."); - return -1; - } - - v[0] *= MI2DEV; v[1] *= MI2DEV; - v[2] *= MI2DEV; v[3] *= MI2DEV; - v[4] *= 180.0 / M_PI; - v[5] *= 180.0 / M_PI; - - spc_currentpoint(spe, &pg, &cp); - - return tpic__arc(tp, &cp, 0, 0.0, v); -} - -static int -spc_handler_tpic_sh (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - char *q; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 0.5; - - skip_blank(&ap->curptr, ap->endptr); - q = parse_float_decimal(&ap->curptr, ap->endptr); - if (q) { - double g = atof(q); - RELEASE(q); - if (g >= 0.0 && g <= 1.0) - tp->fill_color = g; - else { - WARN("Invalid fill color specified: %g\n", g); - return -1; - } - } - - return 0; -} - -static int -spc_handler_tpic_wh (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 0.0; - - return 0; -} - -static int -spc_handler_tpic_bk (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - tp->fill_shape = 1; - tp->fill_color = 1.0; - - return 0; -} - -static int -spc_handler_tpic_tx (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - - ASSERT(spe && ap && tp); - - spc_warn(spe, "TPIC command \"tx\" not supported."); - - return -1; -} - - -static int -spc_handler_tpic__init (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - -#if 0 - tp->mode.fill = TPIC_MODE__FILL_SOLID; -#endif - tp->pen_size = 1.0; - tp->fill_shape = 0; - tp->fill_color = 0.0; - - tp->points = NULL; - tp->num_points = 0; - tp->max_points = 0; - - if (tp->mode.fill != TPIC_MODE__FILL_SOLID && pdf_get_version() < 4) { - spc_warn(spe, "Tpic shading support requires PDF version 1.4."); - tp->mode.fill = TPIC_MODE__FILL_SOLID; - } - - return 0; -} - -static int -spc_handler_tpic__bophook (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - tpic__clear(tp); - - return 0; -} - -static int -spc_handler_tpic__eophook (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - if (tp->num_points > 0) - spc_warn(spe, "Unflushed tpic path at end of the page."); - tpic__clear(tp); - - return 0; -} - -static int -spc_handler_tpic__clean (struct spc_env *spe, - struct spc_arg *ap, void *dp) -{ - struct spc_tpic_ *tp = dp; - - ASSERT(tp); - - if (tp->num_points > 0) - spc_warn(spe, "Unflushed tpic path at end of the document."); - - tpic__clear(tp); -#if 0 - RELEASE(tp); -#endif - - return 0; -} - -void -tpic_set_fill_mode (int mode) -{ - struct spc_tpic_ *tp = &_tpic_state; - tp->mode.fill = mode; -} - - -int -spc_tpic_at_begin_page (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__bophook(NULL, NULL, tp); -} - -int -spc_tpic_at_end_page (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__eophook(NULL, NULL, tp); -} - - -int -spc_tpic_at_begin_document (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__init(NULL, NULL, tp); -} - -int -spc_tpic_at_end_document (void) -{ - struct spc_tpic_ *tp = &_tpic_state; - return spc_handler_tpic__clean(NULL, NULL, tp); -} - - -#if DEBUG -#include "pdfparse.h" /* parse_val_ident :( */ - -static pdf_obj * -spc_parse_kvpairs (struct spc_env *spe, struct spc_arg *ap) -{ - pdf_obj *dict; - char *kp, *vp; - int error = 0; - - dict = pdf_new_dict(); - - skip_blank(&ap->curptr, ap->endptr); - while (!error && ap->curptr < ap->endptr) { - kp = parse_val_ident(&ap->curptr, ap->endptr); - if (!kp) - break; - skip_blank(&ap->curptr, ap->endptr); - if (ap->curptr < ap->endptr && - ap->curptr[0] == '=') { - ap->curptr++; - skip_blank(&ap->curptr, ap->endptr); - if (ap->curptr == ap->endptr) { - RELEASE(kp); - error = -1; - break; - } - vp = parse_c_string(&ap->curptr, ap->endptr); - if (!vp) - error = -1; - else { - pdf_add_dict(dict, - pdf_new_name(kp), - pdf_new_string(vp, strlen(vp) + 1)); /* NULL terminate */ - RELEASE(vp); - } - } else { - /* Treated as 'flag' */ - pdf_add_dict(dict, - pdf_new_name(kp), - pdf_new_boolean(1)); - } - RELEASE(kp); - if (!error) - skip_blank(&ap->curptr, ap->endptr); - } - - if (error) { - pdf_release_obj(dict); - dict = NULL; - } - - return dict; -} - -static int -tpic_filter_getopts (pdf_obj *kp, pdf_obj *vp, void *dp) -{ - struct spc_tpic_ *tp = dp; - char *k, *v; - int error = 0; - - ASSERT( kp && vp && tp ); - - k = pdf_name_value(kp); - if (!strcmp(k, "fill-mode")) { - if (pdf_obj_typeof(vp) != PDF_STRING) { - WARN("Invalid value for TPIC option fill-mode..."); - error = -1; - } else { - v = pdf_string_value(vp); - if (!strcmp(v, "shape")) - tp->mode.fill = TPIC_MODE__FILL_SHAPE; - else if (!strcmp(v, "opacity")) - tp->mode.fill = TPIC_MODE__FILL_OPACITY; - else if (!strcmp(v, "solid")) - tp->mode.fill = TPIC_MODE__FILL_SOLID; - else { - WARN("Invalid value for TPIC option fill-mode: %s", v); - error = -1; - } - } - } else { - WARN("Unrecognized option for TPIC special handler: %s", k); - error = -1; - } - - return error; -} - -static int -spc_handler_tpic__setopts (struct spc_env *spe, - struct spc_arg *ap ) /* , void *dp) */ -{ - struct spc_tpic_ *tp = &_tpic_state; - pdf_obj *dict; - int error = 0; - - dict = spc_parse_kvpairs(spe, ap); - if (!dict) - return -1; - error = pdf_foreach_dict(dict, tpic_filter_getopts, tp); - if (!error) { - if (tp->mode.fill != TPIC_MODE__FILL_SOLID && - pdf_get_version() < 4) { - spc_warn(spe, "Transparent fill mode requires PDF version 1.4."); - tp->mode.fill = TPIC_MODE__FILL_SOLID; - } - } - - return error; -} -#endif /* DEBUG */ - - -static struct spc_handler tpic_handlers[] = { - {"pn", spc_handler_tpic_pn}, - {"pa", spc_handler_tpic_pa}, - {"fp", spc_handler_tpic_fp}, - {"ip", spc_handler_tpic_ip}, - {"da", spc_handler_tpic_da}, - {"dt", spc_handler_tpic_dt}, - {"sp", spc_handler_tpic_sp}, - {"ar", spc_handler_tpic_ar}, - {"ia", spc_handler_tpic_ia}, - {"sh", spc_handler_tpic_sh}, - {"wh", spc_handler_tpic_wh}, - {"bk", spc_handler_tpic_bk}, - {"tx", spc_handler_tpic_tx} -}; - -int -spc_tpic_check_special (const char *buf, long len) -{ - int istpic = 0; - char *q; - const char *p, *endptr; - int i, hasnsp = 0; - - p = buf; - endptr = p + len; - - skip_blank(&p, endptr); -#if ENABLE_SPC_NAMESPACE - if (p + strlen("tpic:") < endptr && - !memcmp(p, "tpic:", strlen("tpic:"))) - { - p += strlen("tpic:"); - hasnsp = 1; - } -#endif - q = parse_c_ident(&p, endptr); - - if (!q) - istpic = 0; - else if (q && hasnsp && !strcmp(q, "__setopt__")) { -#if DEBUG - istpic = 1; -#endif - RELEASE(q); - } else { - for (i = 0; - i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { - if (!strcmp(q, tpic_handlers[i].key)) { - istpic = 1; - break; - } - } - RELEASE(q); - } - - return istpic; -} - - -int -spc_tpic_setup_handler (struct spc_handler *sph, - struct spc_env *spe, struct spc_arg *ap) -{ - char *q; - int i, hasnsp = 0, error = -1; - - ASSERT(sph && spe && ap); - - skip_blank(&ap->curptr, ap->endptr); -#if ENABLE_SPC_NAMESPACE - if (ap->curptr + strlen("tpic:") < ap->endptr && - !memcmp(ap->curptr, "tpic:", strlen("tpic:"))) - { - ap->curptr += strlen("tpic:"); - hasnsp = 1; - } -#endif - q = parse_c_ident(&ap->curptr, ap->endptr); - - if (!q) - error = -1; - else if (q && hasnsp && !strcmp(q, "__setopt__")) { -#if DEBUG - ap->command = "__setopt__"; - sph->key = "tpic:"; - sph->exec = spc_handler_tpic__setopts; - skip_blank(&ap->curptr, ap->endptr); - error = 0; -#endif - RELEASE(q); - } else { - for (i = 0; - i < sizeof(tpic_handlers)/sizeof(struct spc_handler); i++) { - if (!strcmp(q, tpic_handlers[i].key)) { - ap->command = tpic_handlers[i].key; - sph->key = "tpic:"; - sph->exec = tpic_handlers[i].exec; - skip_blank(&ap->curptr, ap->endptr); - error = 0; - break; - } - } - RELEASE(q); - } - - return error; -} - - -#if 0 -int -spc_load_tpic_special (struct spc_env *spe, pdf_obj *lopts) -{ - struct spc_def *spd; - struct spc_tpic_ *sd; - - sd = NEW(1, struct spc_tpic_); - - spd = NEW(1, struct spc_def); - spc_init_def(spd); - - spc_def_init (spd, &spc_handler_tpic__init); - spc_def_setopts(spd, &spc_handler_tpic__setopts); - spc_def_bophook(spd, &spc_handler_tpic__bophook); - spc_def_eophook(spd, &spc_handler_tpic__eophook); - spc_def_clean (spd, &spc_handler_tpic__clean); - - spc_def_func(spd, "pn", &spc_handler_tpic_pn); - spc_def_func(spd, "pa", &spc_handler_tpic_pa); - spc_def_func(spd, "fp", &spc_handler_tpic_fp); - spc_def_func(spd, "ip", &spc_handler_tpic_ip); - spc_def_func(spd, "da", &spc_handler_tpic_da); - spc_def_func(spd, "dt", &spc_handler_tpic_dt); - spc_def_func(spd, "sp", &spc_handler_tpic_sp); - spc_def_func(spd, "ar", &spc_handler_tpic_ar); - spc_def_func(spd, "ia", &spc_handler_tpic_ia); - spc_def_func(spd, "sh", &spc_handler_tpic_sh); - spc_def_func(spd, "wh", &spc_handler_tpic_wh); - spc_def_func(spd, "bk", &spc_handler_tpic_bk); - spc_def_func(spd, "tx", &spc_handler_tpic_tx); - - spc_add_special(spe, "tpic", spd, sd); - - return 0; -} -#endif /* 0 */ - diff --git a/Build/source/texk/dvipdfm-x/xsrc/tt_cmap.c b/Build/source/texk/dvipdfm-x/xsrc/tt_cmap.c deleted file mode 100644 index 9bf9f4506da..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/tt_cmap.c +++ /dev/null @@ -1,1944 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2007-2012 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - 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. -*/ - -/* - * A large part of codes are brought from ttfdump-0.5.5. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "sfnt.h" - - -/* Sorry for placing this here. - * We need to rewrite TrueType font support code... - */ -#include "cmap.h" -#include "cmap_write.h" - -#include "tt_aux.h" -#include "tt_gsub.h" - -#include "unicode.h" -#include "agl.h" -#include "pdfparse.h" -#include "pdfresource.h" -#include "otl_conf.h" - -#include "dpxfile.h" - -/* Hash */ -#include "dpxutil.h" - -#include "tt_cmap.h" - -#define VERBOSE_LEVEL_MIN 0 -static int verbose = 0; -void -otf_cmap_set_verbose (void) -{ - otl_gsub_set_verbose(); - verbose++; -} - -/* format 0: byte encoding table */ -struct cmap0 -{ - BYTE glyphIndexArray[256]; -}; - -static struct cmap0 * -read_cmap0 (sfnt *sfont, ULONG len) -{ - struct cmap0 *map; - int i; - - if (len < 256) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap0); - - for (i = 0; i < 256; i++) - map->glyphIndexArray[i] = sfnt_get_byte(sfont); - - return map; -} - -static void -release_cmap0(struct cmap0 *map) -{ - if (map) - RELEASE(map); -} - -static USHORT -lookup_cmap0 (struct cmap0 *map, USHORT cc) -{ - return ((cc > 255) ? 0 : map->glyphIndexArray[cc]); -} - -/* format 2: high-byte mapping through table */ -struct SubHeader -{ - USHORT firstCode; - USHORT entryCount; - SHORT idDelta; - USHORT idRangeOffset; -}; - -struct cmap2 -{ - USHORT subHeaderKeys[256]; - struct SubHeader *subHeaders; - USHORT *glyphIndexArray; -}; - -static struct cmap2 * -read_cmap2 (sfnt *sfont, ULONG len) -{ - struct cmap2 *map; - USHORT i, n; - - if (len < 512) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap2); - - for (i = 0; i < 256; i++) - map->subHeaderKeys[i] = sfnt_get_ushort(sfont); - - for (n = 0, i = 0; i < 256; i++) { - map->subHeaderKeys[i] /= 8; - if (n < map->subHeaderKeys[i]) - n = map->subHeaderKeys[i]; - } - n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ - - map->subHeaders = NEW(n, struct SubHeader); - for (i = 0; i < n; i++) { - map->subHeaders[i].firstCode = sfnt_get_ushort(sfont); - map->subHeaders[i].entryCount = sfnt_get_ushort(sfont); - map->subHeaders[i].idDelta = sfnt_get_short(sfont); - map->subHeaders[i].idRangeOffset = sfnt_get_ushort(sfont); - - /* It makes things easier to let the offset starts from - * the beginning of glyphIndexArray. - */ - if (map->subHeaders[i].idRangeOffset != 0) - map->subHeaders[i].idRangeOffset -= (2 + (n - i - 1) * 8); - } - - /* Caculate the length of glyphIndexArray, this is ugly, - * there should be a better way to get this information. - */ - n = (USHORT) (len - 518 - n * 8) / 2; - - map->glyphIndexArray = NEW(n, USHORT); - for (i = 0; i < n; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - - return map; -} - -static void -release_cmap2 (struct cmap2 *map) -{ - if (map) { - if (map->subHeaders) - RELEASE(map->subHeaders); - if (map->glyphIndexArray) - RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap2 (struct cmap2 *map, USHORT cc) -{ - USHORT idx = 0; - SHORT idDelta; - USHORT firstCode, entryCount, idRangeOffset; - int hi, lo; - USHORT i; - - hi = (cc >> 8) & 0xff; - lo = cc & 0xff; - - /* select which subHeader to use */ - i = map->subHeaderKeys[hi]; - - firstCode = map->subHeaders[i].firstCode; - entryCount = map->subHeaders[i].entryCount; - idDelta = map->subHeaders[i].idDelta; - idRangeOffset = map->subHeaders[i].idRangeOffset / 2; - - if (lo >= firstCode && - lo < firstCode + entryCount) { - idRangeOffset += lo - firstCode; - idx = map->glyphIndexArray[idRangeOffset]; - if (idx != 0) - idx = (idx + idDelta) & 0xffff; - } - - return idx; -} - -/* - * format 4: segment mapping to delta values - * - Microsoft standard character to glyph index mapping table - */ -struct cmap4 -{ - USHORT segCountX2; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; - USHORT *endCount; - USHORT reservedPad; - USHORT *startCount; - USHORT *idDelta; - USHORT *idRangeOffset; - USHORT *glyphIndexArray; -}; - -static struct cmap4 * -read_cmap4(sfnt *sfont, ULONG len) -{ - struct cmap4 *map; - USHORT i, n, segCount; - - if (len < 8) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap4); - - map->segCountX2 = segCount = sfnt_get_ushort(sfont); - map->searchRange = sfnt_get_ushort(sfont); - map->entrySelector = sfnt_get_ushort(sfont); - map->rangeShift = sfnt_get_ushort(sfont); - - segCount /= 2; - - map->endCount = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->endCount[i] = sfnt_get_ushort(sfont); - - map->reservedPad = sfnt_get_ushort(sfont); - - map->startCount = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->startCount[i] = sfnt_get_ushort(sfont); - - map->idDelta = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->idDelta[i] = sfnt_get_ushort(sfont); - - map->idRangeOffset = NEW(segCount, USHORT); - for (i = 0; i < segCount; i++) - map->idRangeOffset[i] = sfnt_get_ushort(sfont); - - n = (len - 16 - 8 * segCount) / 2; - if (n == 0) - map->glyphIndexArray = NULL; - else { - map->glyphIndexArray = NEW(n, USHORT); - for (i = 0; i < n; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - } - - return map; -} - -static void -release_cmap4 (struct cmap4 *map) -{ - if (map) { - if (map->endCount) RELEASE(map->endCount); - if (map->startCount) RELEASE(map->startCount); - if (map->idDelta) RELEASE(map->idDelta); - if (map->idRangeOffset) RELEASE(map->idRangeOffset); - if (map->glyphIndexArray) RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap4 (struct cmap4 *map, USHORT cc) -{ - USHORT gid = 0; - USHORT i, j, segCount; - - /* - * Segments are sorted in order of increasing endCode values. - * Last segment maps 0xffff to gid 0 (?) - */ - i = segCount = map->segCountX2 / 2; - while (i-- > 0 && cc <= map->endCount[i]) { - if (cc >= map->startCount[i]) { - if (map->idRangeOffset[i] == 0) { - gid = (cc + map->idDelta[i]) & 0xffff; - } else if (cc == 0xffff && map->idRangeOffset[i] == 0xffff) { - /* this is for protection against some old broken fonts... */ - gid = 0; - } else { - j = map->idRangeOffset[i] - (segCount - i) * 2; - j = (cc - map->startCount[i]) + (j / 2); - gid = map->glyphIndexArray[j]; - if (gid != 0) - gid = (gid + map->idDelta[i]) & 0xffff; - } - break; - } - } - - return gid; -} - -/* format 6: trimmed table mapping */ -struct cmap6 -{ - USHORT firstCode; - USHORT entryCount; - USHORT *glyphIndexArray; -}; - -static struct cmap6 * -read_cmap6 (sfnt *sfont, ULONG len) -{ - struct cmap6 *map; - USHORT i; - - if (len < 4) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap6); - map->firstCode = sfnt_get_ushort(sfont); - map->entryCount = sfnt_get_ushort(sfont); - map->glyphIndexArray = NEW(map->entryCount, USHORT); - - for (i = 0; i < map->entryCount; i++) - map->glyphIndexArray[i] = sfnt_get_ushort(sfont); - - return map; -} - -static void -release_cmap6 (struct cmap6 *map) -{ - if (map) { - if (map->glyphIndexArray) - RELEASE(map->glyphIndexArray); - RELEASE(map); - } -} - -static USHORT -lookup_cmap6 (struct cmap6 *map, USHORT cc) -{ - USHORT idx; - - idx = cc - map->firstCode; - if (idx < map->entryCount) - return map->glyphIndexArray[idx]; - else - return 0; - - return 0; -} - -/* Format 8 and 10 not supported... - * - * format 8: mixed 16-bit and 32-bit coverage - * format 10: trimmed array - */ - -/* - * format 12: segmented coverage - * - * startGlyphID is 32-bit long, however, GlyphID is still 16-bit long ! - */ - -struct charGroup -{ - ULONG startCharCode; - ULONG endCharCode; - ULONG startGlyphID; -}; - -struct cmap12 -{ - ULONG nGroups; - struct charGroup *groups; -}; - -/* ULONG length */ -static struct cmap12 * -read_cmap12 (sfnt *sfont, ULONG len) -{ - struct cmap12 *map; - ULONG i; - - if (len < 4) - ERROR("invalid cmap subtable"); - - map = NEW(1, struct cmap12); - map->nGroups = sfnt_get_ulong(sfont); - map->groups = NEW(map->nGroups, struct charGroup); - - for (i = 0; i < map->nGroups; i++) { - map->groups[i].startCharCode = sfnt_get_ulong(sfont); - map->groups[i].endCharCode = sfnt_get_ulong(sfont); - map->groups[i].startGlyphID = sfnt_get_ulong(sfont); - } - - return map; -} - -static void -release_cmap12 (struct cmap12 *map) -{ - if (map) { - if (map->groups) - RELEASE(map->groups); - RELEASE(map); - } -} - -static USHORT -lookup_cmap12 (struct cmap12 *map, ULONG cccc) -{ - USHORT gid = 0; - ULONG i; - - i = map->nGroups; - while (i-- >= 0 && - cccc <= map->groups[i].endCharCode) { - if (cccc >= map->groups[i].startCharCode) { - gid = (USHORT) ((cccc - - map->groups[i].startCharCode + - map->groups[i].startGlyphID) & 0xffff); - break; - } - } - - return gid; -} - -/* read cmap */ -tt_cmap * -tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding) -{ - tt_cmap *cmap = NULL; - ULONG offset, length = 0; - USHORT p_id, e_id; - USHORT i, n_subtabs; - - ASSERT(sfont); - - offset = sfnt_locate_table(sfont, "cmap"); - (void) sfnt_get_ushort(sfont); - n_subtabs = sfnt_get_ushort(sfont); - - for (i = 0; i < n_subtabs; i++) { - p_id = sfnt_get_ushort(sfont); - e_id = sfnt_get_ushort(sfont); - if (p_id != platform || e_id != encoding) - sfnt_get_ulong(sfont); - else { - offset += sfnt_get_ulong(sfont); - break; - } - } - - if (i == n_subtabs) - return NULL; - - cmap = NEW(1, tt_cmap); - cmap->map = NULL; - cmap->platform = platform; - cmap->encoding = encoding; - - sfnt_seek_set(sfont, offset); - cmap->format = sfnt_get_ushort(sfont); - /* Length and version (language) is ULONG for - * format 8, 10, 12 ! - */ - if (cmap->format <= 6) { - length = sfnt_get_ushort(sfont); - cmap->language = sfnt_get_ushort(sfont); /* language (Mac) */ - } else { - if (sfnt_get_ushort(sfont) != 0) { /* reverved - 0 */ - WARN("Unrecognized cmap subtable format."); - tt_cmap_release(cmap); - return NULL; - } else { - length = sfnt_get_ulong(sfont); - cmap->language = sfnt_get_ulong(sfont); - } - } - - switch(cmap->format) { - case 0: - cmap->map = read_cmap0(sfont, length); - break; - case 2: - cmap->map = read_cmap2(sfont, length); - break; - case 4: - cmap->map = read_cmap4(sfont, length); - break; - case 6: - cmap->map = read_cmap6(sfont, length); - break; - case 12: - /*WARN("UCS-4 TrueType cmap table...");*/ - cmap->map = read_cmap12(sfont, length); - break; - default: - WARN("Unrecognized OpenType/TrueType cmap format."); - tt_cmap_release(cmap); - return NULL; - } - - if (!cmap->map) { - tt_cmap_release(cmap); - cmap = NULL; - } - - return cmap; -} - -void -tt_cmap_release (tt_cmap *cmap) -{ - - if (cmap) { - if (cmap->map) { - switch(cmap->format) { - case 0: - release_cmap0(cmap->map); - break; - case 2: - release_cmap2(cmap->map); - break; - case 4: - release_cmap4(cmap->map); - break; - case 6: - release_cmap6(cmap->map); - break; - case 12: - release_cmap12(cmap->map); - break; - default: - ERROR("Unrecognized OpenType/TrueType cmap format."); - } - } - RELEASE(cmap); - } - - return; -} - - -USHORT -tt_cmap_lookup (tt_cmap *cmap, long cc) -{ - USHORT gid = 0; - - ASSERT(cmap); - - if (cc > 0xffffL && cmap->format < 12) { - WARN("Four bytes charcode not supported in OpenType/TrueType cmap format 0...6."); - return 0; - } - - switch (cmap->format) { - case 0: - gid = lookup_cmap0(cmap->map, (USHORT) cc); - break; - case 2: - gid = lookup_cmap2(cmap->map, (USHORT) cc); - break; - case 4: - gid = lookup_cmap4(cmap->map, (USHORT) cc); - break; - case 6: - gid = lookup_cmap6(cmap->map, (USHORT) cc); - break; - case 12: - gid = lookup_cmap12(cmap->map, (ULONG) cc); - break; - default: - ERROR("Unrecognized OpenType/TrueType cmap subtable format"); - break; - } - - return gid; -} - -/* Sorry for placing this here. - * We need to rewrite TrueType font support code... - */ - -#define WBUF_SIZE 1024 -static unsigned char wbuf[WBUF_SIZE]; - -static unsigned char srange_min[2] = {0x00, 0x00}; -static unsigned char srange_max[2] = {0xff, 0xff}; -static unsigned char lrange_min[4] = {0x00, 0x00, 0x00, 0x00}; -static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff}; - -static void -load_cmap4 (struct cmap4 *map, - unsigned char *GIDToCIDMap, CMap *cmap) -{ - USHORT c0, c1, gid, cid; - USHORT j, d, segCount; - USHORT ch; - long i; - - segCount = map->segCountX2 / 2; - for (i = segCount - 1; i >= 0 ; i--) { - c0 = map->startCount[i]; - c1 = map->endCount[i]; - d = map->idRangeOffset[i] / 2 - (segCount - i); - for (j = 0; j <= c1 - c0; j++) { - ch = c0 + j; - if (map->idRangeOffset[i] == 0) { - gid = (ch + map->idDelta[i]) & 0xffff; - } else if (c0 == 0xffff && c1 == 0xffff && map->idRangeOffset[i] == 0xffff) { - /* this is for protection against some old broken fonts... */ - gid = 0; - } else { - gid = (map->glyphIndexArray[j+d] + - map->idDelta[i]) & 0xffff; - } - if (gid != 0 && gid != 0xffff) { - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); - if (cid == 0) - WARN("GID %u does not have corresponding CID %u.", - gid, cid); - } else { - cid = gid; - } - wbuf[0] = 0; - wbuf[1] = 0; - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - CMap_add_cidchar(cmap, wbuf, 4, cid); - } - } - } - - return; -} - -static void -load_cmap12 (struct cmap12 *map, - unsigned char *GIDToCIDMap, CMap *cmap) -{ - ULONG i, ch; /* LONG ? */ - USHORT gid, cid; - - for (i = 0; i < map->nGroups; i++) { - for (ch = map->groups[i].startCharCode; - ch <= map->groups[i].endCharCode; - ch++) { - long d = ch - map->groups[i].startCharCode; - gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); - if (cid == 0) - WARN("GID %u does not have corresponding CID %u.", gid, cid); - } else { - cid = gid; - } - wbuf[0] = (ch >> 24) & 0xff; - wbuf[1] = (ch >> 16) & 0xff; - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - CMap_add_cidchar(cmap, wbuf, 4, cid); - } - } - - return; -} - -/* OpenType CIDFont: - * - * We don't use GID for them. OpenType cmap table is for - * charcode to GID mapping rather than to-CID mapping. - */ -#include "cid.h" - -#include "tt_table.h" -#include "cff_types.h" -#include "cff_dict.h" -#include "cff.h" - -static int -handle_CIDFont (sfnt *sfont, - unsigned char **GIDToCIDMap, CIDSysInfo *csi) -{ - cff_font *cffont; - long offset, i; - card16 num_glyphs, gid; - cff_charsets *charset; - unsigned char *map; - struct tt_maxp_table *maxp; - - ASSERT(csi); - - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset == 0) { - csi->registry = NULL; - csi->ordering = NULL; - *GIDToCIDMap = NULL; - return 0; - } - - maxp = tt_read_maxp_table(sfont); - num_glyphs = (card16) maxp->numGlyphs; - RELEASE(maxp); - if (num_glyphs < 1) - ERROR("No glyph contained in this font..."); - - cffont = cff_open(sfont, offset, 0); - if (!cffont) - ERROR("Could not open CFF font..."); - - - if (!(cffont->flag & FONTTYPE_CIDFONT)) { - cff_close(cffont); - csi->registry = NULL; - csi->ordering = NULL; - *GIDToCIDMap = NULL; - return 0; - } - - if (!cff_dict_known(cffont->topdict, "ROS")) { - ERROR("No CIDSystemInfo???"); - } else { - card16 reg, ord; - - reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0); - ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1); - - csi->registry = cff_get_string(cffont, reg); - csi->ordering = cff_get_string(cffont, ord); - csi->supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2); - } - - cff_read_charsets(cffont); - charset = cffont->charsets; - if (!charset) { - ERROR("No CFF charset data???"); - } - - map = NEW(num_glyphs * 2, unsigned char); - memset(map, 0, num_glyphs * 2); - switch (charset->format) { - case 0: - { - s_SID *cids; /* CID... */ - - cids = charset->data.glyphs; - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - map[2*gid ] = (cids[i] >> 8) & 0xff; - map[2*gid+1] = cids[i] & 0xff; - gid++; - } - } - break; - case 1: - { - cff_range1 *ranges; - card16 cid, count; - - ranges = charset->data.range1; - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - cid = ranges[i].first; - count = ranges[i].n_left + 1; /* card8 */ - while (count-- > 0 && - gid <= num_glyphs) { - map[2*gid ] = (cid >> 8) & 0xff; - map[2*gid + 1] = cid & 0xff; - gid++; - } - } - } - break; - case 2: - { - cff_range2 *ranges; - card16 cid, count; - - ranges = charset->data.range2; - if (charset->num_entries == 1 && - ranges[0].first == 1) { - /* "Complete" CIDFont */ - RELEASE(map); map = NULL; - } else { - /* Not trivial mapping */ - for (gid = 1, i = 0; - i < charset->num_entries; i++) { - cid = ranges[i].first; - count = ranges[i].n_left + 1; - while (count-- > 0 && - gid <= num_glyphs) { - map[gid] = (cid >> 8) & 0xff; - map[gid] = cid & 0xff; - gid++; - } - } - - } - } - break; - default: - RELEASE(map); map = NULL; - ERROR("Unknown CFF charset format...: %d", charset->format); - break; - } - cff_close(cffont); - - *GIDToCIDMap = map; - return 1; -} - -/* - * Substituted glyphs: - * - * Mapping information stored in cmap_add. - */ -#ifndef is_used_char2 -#define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8)))) -#endif - -static USHORT -handle_subst_glyphs (CMap *cmap, - CMap *cmap_add, const char *used_glyphs, - sfnt *sfont) -{ - USHORT count; - USHORT i, gid; - - for (count = 0, i = 0; i < 8192; i++) { - int j; - long len, inbytesleft, outbytesleft; - const unsigned char *inbuf; - unsigned char *outbuf; - - if (used_glyphs[i] == 0) - continue; - - for (j = 0; j < 8; j++) { - gid = 8 * i + j; - - if (!is_used_char2(used_glyphs, gid)) - continue; - - if (!cmap_add) { -#if XETEX - if (FT_HAS_GLYPH_NAMES(sfont->ft_face)) { - /* JK: try to look up Unicode values from the glyph name... */ -#define MAX_UNICODES 16 -#define MAX_NAME 256 - static char name[MAX_NAME] = "(none)"; - long unicodes[MAX_UNICODES]; - int unicode_count = -1; - FT_Error err = FT_Get_Glyph_Name(sfont->ft_face, gid, name, MAX_NAME); - if (!err) { - unicode_count = agl_get_unicodes(name, unicodes, MAX_UNICODES); - } -#undef MAX_UNICODES -#undef MAX_NAME - if (unicode_count == -1) { - MESG("No Unicode mapping available: GID=%u, name=%s\n", gid, name); - } else { - /* the Unicode characters go into wbuf[2] and following, in UTF16BE */ - /* we rely on WBUF_SIZE being more than adequate for MAX_UNICODES */ - unsigned char* p = wbuf + 2; - int k; - len = 0; - 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); - } - } -#else - WARN("No Unicode mapping available: GID=%u", gid); -#endif - } else { - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = gid & 0xff; - inbuf = wbuf; - inbytesleft = 2; - outbuf = wbuf + 2; - outbytesleft = WBUF_SIZE - 2; - CMap_decode(cmap_add, - &inbuf , &inbytesleft, - &outbuf, &outbytesleft); - if (inbytesleft != 0) { - WARN("CMap conversion failed..."); - } else { - len = WBUF_SIZE - 2 - outbytesleft; - CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len); - count++; - - if (verbose > VERBOSE_LEVEL_MIN) { - long _i; - - MESG("otf_cmap>> Additional ToUnicode mapping: <%04X> <", gid); - for (_i = 0; _i < len; _i++) { - MESG("%02X", wbuf[2 + _i]); - } - MESG(">\n"); - } - - } - } - - } - } - - return count; -} - -static pdf_obj * -create_ToUnicode_cmap4 (struct cmap4 *map, - const char *cmap_name, CMap *cmap_add, - const char *used_glyphs, - sfnt *sfont) -{ - pdf_obj *stream = NULL; - CMap *cmap; - USHORT c0, c1, gid, count, ch; - USHORT i, j, d, segCount; - char used_glyphs_copy[8192]; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - CMap_add_codespacerange(cmap, srange_min, srange_max, 2); - - memcpy(used_glyphs_copy, used_glyphs, 8192); - - segCount = map->segCountX2 / 2; - for (count = 0, i = 0; i < segCount; i++) { - c0 = map->startCount[i]; - c1 = map->endCount[i]; - d = map->idRangeOffset[i] / 2 - (segCount - i); - for (j = 0; j <= c1 - c0; j++) { - ch = c0 + j; - if (map->idRangeOffset[i] == 0) { - gid = (ch + map->idDelta[i]) & 0xffff; - } else if (c0 == 0xffff && c1 == 0xffff && map->idRangeOffset[i] == 0xffff) { - /* this is for protection against some old broken fonts... */ - gid = 0; - } else { - gid = (map->glyphIndexArray[j+d] + - map->idDelta[i]) & 0xffff; - } - if (is_used_char2(used_glyphs_copy, gid)) { - count++; - - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = (gid & 0xff); - - wbuf[2] = (ch >> 8) & 0xff; - wbuf[3] = ch & 0xff; - - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, 2); - - /* Avoid duplicate entry - * There are problem when two Unicode code is mapped to - * single glyph... - */ - used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); - count++; - } - } - } - - count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont); - - if (count < 1) - stream = NULL; - else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - - -static pdf_obj * -create_ToUnicode_cmap12 (struct cmap12 *map, - const char *cmap_name, CMap *cmap_add, - const char *used_glyphs, - sfnt *sfont) -{ - pdf_obj *stream = NULL; - CMap *cmap; - ULONG i, ch; - USHORT gid, count; - char used_glyphs_copy[8192]; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_wmode(cmap, 0); - CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE); - CMap_set_CIDSysInfo(cmap, &CSI_UNICODE); - CMap_add_codespacerange(cmap, srange_min, srange_max, 2); - - memcpy(used_glyphs_copy, used_glyphs, 8192); - for (count = 0, i = 0; i < map->nGroups; i++) { - for (ch = map->groups[i].startCharCode; - ch <= map->groups[i].endCharCode; ch++) { - unsigned char *p; - int len; - long d; - - p = wbuf + 2; - d = ch - map->groups[i].startCharCode; - gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); - if (is_used_char2(used_glyphs_copy, gid)) { - count++; - wbuf[0] = (gid >> 8) & 0xff; - wbuf[1] = (gid & 0xff); - len = UC_sput_UTF16BE((long)ch, &p, wbuf+WBUF_SIZE); - - used_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8))); - CMap_add_bfchar(cmap, wbuf, 2, wbuf+2, len); - } - } - } - - count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont); - - if (count < 1) - stream = NULL; - else { - stream = CMap_create_stream(cmap, 0); - } - CMap_release(cmap); - - return stream; -} - -#ifdef XETEX -typedef struct { - short platform; - short encoding; -} cmap_plat_enc_rec; - -static cmap_plat_enc_rec cmap_plat_encs[] = { - { 3, 10 }, - { 0, 3 }, - { 0, 0 }, - { 3, 1 }, - { 0, 1 } -}; -#endif - -pdf_obj * -otf_create_ToUnicode_stream (const char *font_name, - int ttc_index, /* 0 for non-TTC */ -#ifdef XETEX - FT_Face face, -#endif - const char *used_glyphs) -{ - pdf_obj *cmap_ref = NULL; - long res_id; - pdf_obj *cmap_obj = NULL; - CMap *cmap_add; - int cmap_add_id; - tt_cmap *ttcmap; - char *normalized_font_name; - char *cmap_name; - FILE *fp = NULL; - sfnt *sfont; - long offset = 0; - int i; - - /* replace slash in map name with dash to make the output cmap name valid, - * happens when XeTeX embeds full font path - * https://sourceforge.net/p/xetex/bugs/52/ - */ - normalized_font_name = NEW(strlen(font_name)+1, char); - strcpy(normalized_font_name, font_name); - for (i = 0; i < strlen(font_name); ++i) { - if (normalized_font_name[i] == '/') - normalized_font_name[i] = '-'; - } - - cmap_name = NEW(strlen(font_name)+strlen("-UTF16")+5, char); - sprintf(cmap_name, "%s,%03d-UTF16", normalized_font_name, ttc_index); - - res_id = pdf_findresource("CMap", cmap_name); - if (res_id >= 0) { - RELEASE(cmap_name); - cmap_ref = pdf_get_resource_reference(res_id); - return cmap_ref; - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - MESG("otf_cmap>> Creating ToUnicode CMap for \"%s\"...\n", font_name); - } - -#ifdef XETEX - sfont = sfnt_open(face, -1); -#else - fp = DPXFOPEN(font_name, DPX_RES_TYPE_TTFONT); - if (!fp) { - fp = DPXFOPEN(font_name, DPX_RES_TYPE_OTFONT); - } - - if (!fp) { - RELEASE(cmap_name); - return NULL; - } - - sfont = sfnt_open(fp); -#endif - - if (!sfont) { - ERROR("Could not open OpenType/TrueType font file \"%s\"", font_name); - } - - switch (sfont->type) { - case SFNT_TYPE_TTC: - offset = ttc_read_offset(sfont, ttc_index); - if (offset == 0) { - ERROR("Invalid TTC index"); - } - break; - default: - offset = 0; - break; - } - - if (sfnt_read_table_directory(sfont, offset) < 0) { - ERROR("Could not read OpenType/TrueType table directory."); - } - - cmap_add_id = CMap_cache_find(cmap_name); - if (cmap_add_id < 0) { - cmap_add = NULL; - } else { - cmap_add = CMap_cache_get(cmap_add_id); - } - - CMap_set_silent(1); /* many warnings without this... */ - for (i = 0; i < sizeof(cmap_plat_encs) / sizeof(cmap_plat_enc_rec); ++i) { - ttcmap = tt_cmap_read(sfont, cmap_plat_encs[i].platform, cmap_plat_encs[i].encoding); - if (!ttcmap) - continue; - if (ttcmap->format == 4) { - cmap_obj = create_ToUnicode_cmap4(ttcmap->map, - cmap_name, cmap_add, used_glyphs, sfont); - break; - } - if (ttcmap->format == 12) { - cmap_obj = create_ToUnicode_cmap12(ttcmap->map, - cmap_name, cmap_add, used_glyphs, sfont); - break; - } - } - if (cmap_obj == NULL) - WARN("Unable to read OpenType/TrueType Unicode cmap table."); - tt_cmap_release(ttcmap); - CMap_set_silent(0); - - if (cmap_obj) { - res_id = pdf_defineresource("CMap", cmap_name, - cmap_obj, PDF_RES_FLUSH_IMMEDIATE); - cmap_ref = pdf_get_resource_reference(res_id); - } else { - cmap_ref = NULL; - } - RELEASE(cmap_name); - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return cmap_ref; -} - -/* Must be smaller than (WBUF_SIZE-2)/8 */ -#define MAX_UNICODES 16 - -struct gent -{ - USHORT gid; - long ucv; /* assigned PUA unicode */ - - int num_unicodes; - long unicodes[MAX_UNICODES]; -}; - -static void -create_cmaps (CMap *cmap, CMap *tounicode, - struct ht_table *unencoded, unsigned char *GIDToCIDMap) -{ - struct ht_iter iter; - - ASSERT(cmap && unencoded); - - if (ht_set_iter(unencoded, &iter) < 0) - return; - - CMap_set_silent(1); /* many warnings without this... */ - - do { - struct gent *glyph; - unsigned char *ucv; - int i, len; - unsigned char *p, *endptr; - CID cid; - - glyph = (struct gent *) ht_iter_getval(&iter); - ucv = (unsigned char *) ht_iter_getkey(&iter, &len); - - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]); - if (cid == 0) - WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid); - } else { - cid = glyph->gid; - } - - CMap_add_cidchar(cmap, ucv, 4, cid); - - if (tounicode) { - wbuf[0] = (cid >> 8) & 0xff; - wbuf[1] = cid & 0xff; - p = wbuf + 2; - endptr = wbuf + WBUF_SIZE; - len = 0; - for (i = 0; i < glyph->num_unicodes; i++) { - len += UC_sput_UTF16BE(glyph->unicodes[i], &p, endptr); - } - CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len); - } - } while (ht_iter_next(&iter) >= 0); - - CMap_set_silent(0); - - ht_clear_iter(&iter); -} - -static void -add_glyph (struct ht_table *unencoded, - USHORT gid, long ucv, int num_unicodes, long *unicodes) -{ - struct gent *glyph; - int i; - - ASSERT(unencoded); - - if (gid == 0 || num_unicodes < 1) { - return; - } - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - glyph = NEW(1, struct gent); - glyph->gid = gid; - glyph->num_unicodes = num_unicodes; - for (i = 0; - i < num_unicodes && i < MAX_UNICODES; i++) { - glyph->unicodes[i] = unicodes[i]; - } - - ht_append_table(unencoded, wbuf, 4, glyph); -} - -/* This seriously affects speed... */ -static struct gent * -find_glyph (struct ht_table *unencoded, long ucv) -{ - ASSERT(unencoded); - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - return (struct gent *) ht_lookup_table(unencoded, wbuf, 4); -} - -static void -handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - pdf_obj *tmp; - long i, j, src_size, dst_size; - long src, dst; - long src_start, src_end, dst_start, dst_end; - - src_size = pdf_array_length(src_obj); - dst_size = pdf_array_length(dst_obj); - - dst_start = dst_end = -1; dst = 0; - src_start = src_end = -1; src = 0; - for (i = 0, j = 0; - i < src_size && j < dst_size; i++) { - USHORT gid; - int rv; - struct gent *glyph; - - tmp = pdf_get_array(src_obj, i); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - src_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); - src_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - src_start = src_end = (long) pdf_number_value(tmp); - } - for (src = src_start; src <= src_end; src++) { - glyph = find_glyph(unencoded, src); - if (glyph) - gid = glyph->gid; - else { - gid = tt_cmap_lookup(ttcmap, src); - } - dst++; - if (dst > dst_end) { - tmp = pdf_get_array(dst_obj, j++); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - dst_start = (long) pdf_number_value(pdf_get_array(tmp, 0)); - dst_end = (long) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - dst_start = dst_end = (long) pdf_number_value(tmp); - } - dst = dst_start; - } - if (gid == 0) { - if (flag == 'r' || flag == 'p') { - if (src < 0x10000) { - WARN("Font does not have glyph for U+%04X.", src); - } else { - WARN("Font does not have glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - rv = otl_gsub_apply(gsub_list, &gid); - if (rv < 0) { - if (flag == 'p' || flag == 'r') { - if (src < 0x10000) { - WARN("No substituted glyph for U+%04X.", src); - } else { - WARN("No substituted glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - - if (glyph) { - glyph->gid = gid; - } else { - add_glyph(unencoded, gid, dst, 1, &src); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - if (dst < 0x10000) { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n", - gid, dst); - } else { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n", - gid, dst); - } - } - - } - } - - if (dst < dst_end || src < src_end || - i < src_size || j < dst_size) { - WARN("Number of glyphs in left-side and right-side not equal..."); - WARN("Please check .otl file..."); - } -} - -static void -handle_assign (pdf_obj *dst, pdf_obj *src, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - long unicodes[MAX_UNICODES], ucv; - int i, n_unicodes, rv; - USHORT gid_in[MAX_UNICODES], lig; - - n_unicodes = pdf_array_length(src); /* FIXME */ - ucv = (long) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */ - if (!UC_is_valid(ucv)) { - if (flag == 'r' || flag == 'p') { - if (ucv < 0x10000) { - WARN("Invalid Unicode in: %04X", ucv); - } else { - WARN("Invalid Unicode in: %06X", ucv); - } - } - if (flag == 'r') { - ERROR("Invalid Unicode code specified.", ucv); - } - return; - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Ligature component:"); - } - - for (i = 0; i < n_unicodes; i++) { - unicodes[i] = - (long) pdf_number_value(pdf_get_array(src, i)); - gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (unicodes[i] < 0x10000) { - MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]); - } else { - MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]); - } - } - - if (gid_in[i] == 0) { - if (flag == 'r' || flag == 'p') { - if (unicodes[i] < 0x10000) { - WARN("Unicode char U+%04X not exist in font...", unicodes[i]); - } else { - WARN("Unicode char U+%06X not exist in font...", unicodes[i]); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - return; - } - - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - } - - rv = otl_gsub_apply_lig(gsub_list, - gid_in, (USHORT)n_unicodes, &lig); - if (rv < 0) { - if (flag == 'p') - WARN("No ligature found..."); - else if (flag == 'r') - ERROR("No ligature found..."); - return; - } - - add_glyph(unencoded, lig, ucv, n_unicodes, unicodes); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (ucv < 0x10000) { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv); - } else { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv); - } - } - - return; -} - -static int -load_base_CMap (const char *cmap_name, int wmode, - CIDSysInfo *csi, unsigned char *GIDToCIDMap, - tt_cmap *ttcmap) -{ - int cmap_id; - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id < 0) { - CMap *cmap; - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); - - if (csi) { /* CID */ - CMap_set_CIDSysInfo(cmap, csi); - } else { - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - } - - if (ttcmap->format == 12) { - load_cmap12(ttcmap->map, GIDToCIDMap, cmap); - } else if (ttcmap->format == 4) { - load_cmap4(ttcmap->map, GIDToCIDMap, cmap); - } - - cmap_id = CMap_cache_add(cmap); - } - - return cmap_id; -} - -static void -load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont) -{ - pdf_obj *rule; - char *script, *language, *feature; - long i, size; - - rule = otl_conf_get_rule(conf); - if (!rule) - return; - - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - int flag; - long j, num_comms; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array(rule, i+1); - num_comms = pdf_array_length(commands); - - /* (assign|substitute) tag dst src */ - for (j = 0 ; j < num_comms; j += 4) { - tmp = pdf_get_array(commands, 1); - if (PDF_OBJ_STRINGTYPE(tmp)) { - feature = pdf_string_value(tmp); - if (otl_gsub_add_feat(gsub_list, - script, language, feature, sfont) < 0) { - if (flag == 'p') - WARN("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - else if (flag == 'r') - ERROR("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - } - } - - } - } - -} - -static void -handle_gsub (pdf_obj *conf, - tt_cmap *ttcmap, otl_gsub *gsub_list, - struct ht_table *unencoded) -{ - pdf_obj *rule; - char *script, *language, *feature; - long i, size; - - if (!conf) - return; - - rule = otl_conf_get_rule(conf); - if (!rule) { - return; - } - - if (!PDF_OBJ_ARRAYTYPE(rule)) { - WARN("Not arraytype?"); - return; - } - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - long j, num_comms; - int flag; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array (rule, i+1); - num_comms = pdf_array_length(commands); - - for (j = 0; j < num_comms; j += 4) { - pdf_obj *operator; - pdf_obj *src, *dst, *feat; - int rv; - - /* (assing|substitute) tag dst src */ - operator = pdf_get_array(commands, j); - - feat = pdf_get_array(commands, j+1); - if (PDF_OBJ_STRINGTYPE(feat)) - feature = pdf_string_value(feat); - else - feature = NULL; - - dst = pdf_get_array(commands, j+2); - src = pdf_get_array(commands, j+3); - - rv = otl_gsub_select(gsub_list, script, language, feature); - if (rv < 0) { - if (flag == 'p') { - WARN("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } else if (flag == 'r') { - ERROR("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } - } else { - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> %s:\n", pdf_name_value(operator)); - } - - if (!strcmp(pdf_name_value(operator), "assign")) { - handle_assign(dst, src, flag, - gsub_list, ttcmap, unencoded); - } else if (!strcmp(pdf_name_value(operator), "substitute")) { - handle_subst(dst, src, flag, - gsub_list, ttcmap, unencoded); - } - } - - } - - } - -} - -static void CDECL -hval_free (void *hval) -{ - RELEASE(hval); -} - -int -otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */ - const char *otl_tags, int wmode) -{ - int cmap_id = -1; - int tounicode_id = -1, is_cidfont = 0; - sfnt *sfont; - unsigned long offset = 0; - char *base_name = NULL, *cmap_name = NULL; - char *tounicode_name = NULL; - FILE *fp = NULL; - otl_gsub *gsub_list = NULL; - tt_cmap *ttcmap; - CMap *cmap, *base, *tounicode = NULL; - CIDSysInfo csi = {NULL, NULL, 0}; - unsigned char *GIDToCIDMap = NULL; - - if (!map_name) - return -1; - - if (ttc_index > 999 || ttc_index < 0) { - return -1; /* Sorry for this... */ - } - -#ifdef XETEX - fprintf(stderr, "otf_load_Unicode_CMap(%s, %d)\n", map_name, ttc_index); - sfont = NULL; /* FIXME */ -#else - fp = DPXFOPEN(map_name, DPX_RES_TYPE_TTFONT); - if (!fp) { - fp = DPXFOPEN(map_name, DPX_RES_TYPE_OTFONT); - } - if (!fp) { - fp = DPXFOPEN(map_name, DPX_RES_TYPE_DFONT); - if (!fp) return -1; - sfont = dfont_open(fp, ttc_index); - } else { - sfont = sfnt_open(fp); - } -#endif - - if (!sfont) { - ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name); - } - switch (sfont->type) { - case SFNT_TYPE_TTC: - offset = ttc_read_offset(sfont, ttc_index); - if (offset == 0) { - ERROR("Invalid TTC index"); - } - break; - case SFNT_TYPE_TRUETYPE: - case SFNT_TYPE_POSTSCRIPT: - offset = 0; - break; - case SFNT_TYPE_DFONT: - offset = sfont->offset; - break; - default: - ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name); - break; - } - - if (sfnt_read_table_directory(sfont, offset) < 0) - ERROR("Could not read OpenType/TrueType table directory."); - - base_name = NEW(strlen(map_name)+strlen("-UCS4-H")+5, char); - if (wmode) - sprintf(base_name, "%s,%03d-UCS4-V", map_name, ttc_index); - else { - sprintf(base_name, "%s,%03d-UCS4-H", map_name, ttc_index); - } - - if (otl_tags) { - cmap_name = NEW(strlen(map_name)+strlen(otl_tags)+strlen("-UCS4-H")+6, char); - if (wmode) - sprintf(cmap_name, "%s,%03d,%s-UCS4-V", map_name, ttc_index, otl_tags); - else - sprintf(cmap_name, "%s,%03d,%s-UCS4-H", map_name, ttc_index, otl_tags); - } else { - cmap_name = NEW(strlen(base_name)+1, char); - strcpy(cmap_name, base_name); - } - - if (sfont->type == SFNT_TYPE_POSTSCRIPT) { - is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi); - } else { - is_cidfont = 0; - } - - if (is_cidfont) { - tounicode_name = NULL; - } else { - tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char); - sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n", - map_name, (otl_tags ? otl_tags : "none")); - } - - cmap_id = CMap_cache_find(cmap_name); - if (cmap_id >= 0) { - RELEASE(cmap_name); - RELEASE(base_name); - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); - - sfnt_close(sfont); - DPXFCLOSE(fp); - - if (verbose > VERBOSE_LEVEL_MIN) - MESG("otf_cmap>> Found at cmap_id=%d.\n", cmap_id); - - return cmap_id; - } - - ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */ - if (!ttcmap) { - 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 OpenType/TrueType cmap table."); - - if (!otl_tags) { - RELEASE(cmap_name); - RELEASE(base_name); - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); - if (is_cidfont) { - if (csi.registry) - RELEASE(csi.registry); - if (csi.ordering) - RELEASE(csi.ordering); - } - tt_cmap_release(ttcmap); - sfnt_close(sfont); - DPXFCLOSE(fp); - - return cmap_id; - } - - base = CMap_cache_get(cmap_id); - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */ - CMap_set_usecmap(cmap, base); - CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */ - - if (is_cidfont) { - CMap_set_CIDSysInfo(cmap, &csi); - if (csi.registry) - RELEASE(csi.registry); - if (csi.ordering) - RELEASE(csi.ordering); - } else { - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - } - - gsub_list = otl_gsub_new(); - - { - struct ht_table unencoded; - char *conf_name, *opt_tag; - pdf_obj *conf, *opt_conf; - - conf_name = NEW(strlen(otl_tags)+1, char); - memset (conf_name, 0, strlen(otl_tags)+1); - opt_tag = strchr(otl_tags, ':'); - if (opt_tag) { - opt_tag++; - strncpy(conf_name, otl_tags, - strlen(otl_tags) - strlen(opt_tag) - 1); - } else { - strcpy(conf_name, otl_tags); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name); - } - - conf = otl_find_conf(conf_name); - if (!conf) - ERROR("Layout file \"%s\" not found...", conf_name); - - load_gsub(conf, gsub_list, sfont); - if (opt_tag) { - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag); - } - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - load_gsub(opt_conf, gsub_list, sfont); - } - - ht_init_table(&unencoded, hval_free); - - handle_gsub(conf, ttcmap, gsub_list, &unencoded); - if (opt_tag) { - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded); - } - if (is_cidfont) { - tounicode_id = -1; - tounicode = NULL; - } else { - tounicode_id = CMap_cache_find(tounicode_name); - if (tounicode_id >= 0) - tounicode = CMap_cache_get(tounicode_id); - else { - tounicode = CMap_new(); - CMap_set_name (tounicode, tounicode_name); - CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE); - CMap_set_wmode(tounicode, 0); - CMap_add_codespacerange(tounicode, srange_min, srange_max, 2); - CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE); - /* FIXME */ - CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2); - } - } - create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap); - - ht_clear_table(&unencoded); - RELEASE(conf_name); - } - - cmap_id = CMap_cache_add(cmap); - if (!is_cidfont && tounicode_id < 0) /* New */ - CMap_cache_add(tounicode); - - tt_cmap_release(ttcmap); - if (gsub_list) - otl_gsub_release(gsub_list); - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n", - base_name, cmap_name); - } - - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (base_name) - RELEASE(base_name); - if (cmap_name) - RELEASE(cmap_name); - if (tounicode_name) - RELEASE(tounicode_name); - - sfnt_close(sfont); - DPXFCLOSE(fp); - - return cmap_id; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/type1c.c b/Build/source/texk/dvipdfm-x/xsrc/type1c.c deleted file mode 100644 index 7a51b8f15c4..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/type1c.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - - This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2008-2012 by Jin-Hwan Cho, Matthias Franz, 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. -*/ - -/* - * CFF/OpenType Font support: - * - * Adobe Technical Note #5176, "The Compact Font Format Specfication" - * - * NOTE: - * - * Many CFF/OpenType does not have meaningful/correct CFF encoding. - * Encoding should be expilicitly supplied in the fontmap. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "system.h" -#include "mem.h" -#include "error.h" - -#include "dpxfile.h" - -#include "pdfobj.h" -#include "pdffont.h" - -#include "pdfencoding.h" -#include "unicode.h" - -/* Font info. from OpenType tables */ -#include "sfnt.h" -#include "tt_aux.h" - -#include "cff_types.h" -#include "cff_limits.h" -#include "cff.h" -#include "cff_dict.h" -#include "cs_type2.h" - -#include "type1c.h" - -#include "tfm.h" - -int -pdf_font_open_type1c (pdf_font *font) -{ - char *fontname; -#ifndef XETEX - char *ident; -#endif - FILE *fp = NULL; - sfnt *sfont; - cff_font *cffont; - pdf_obj *descriptor, *tmp; - unsigned long offset = 0; - int encoding_id, embedding; - - ASSERT(font); - -#ifndef XETEX - ident = -#endif - pdf_font_get_ident (font); - encoding_id = pdf_font_get_encoding(font); - -#ifdef XETEX - sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); - if (!sfont) - return -1; -#else - fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); - if (!fp) - return -1; - - sfont = sfnt_open(fp); -#endif - if (!sfont || - sfont->type != SFNT_TYPE_POSTSCRIPT || - sfnt_read_table_directory(sfont, 0) < 0) { - ERROR("Not a CFF/OpenType font?"); - } - - offset = sfnt_find_table_pos(sfont, "CFF "); - if (offset < 1) { - ERROR("No \"CFF \" table found. Not a CFF/OpenType font?"); - } - - cffont = cff_open(sfont, offset, 0); - if (!cffont) { - ERROR("Could not read CFF font data"); - } - - if (cffont->flag & FONTTYPE_CIDFONT) { - cff_close (cffont); - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - return -1; - } - - fontname = cff_get_name(cffont); - if (!fontname) { - ERROR("No valid FontName found in CFF/OpenType font."); - } - pdf_font_set_fontname(font, fontname); - RELEASE(fontname); - - cff_close(cffont); - - /* - * Font like AdobePiStd does not have meaningful built-in encoding. - * Some software generate CFF/OpenType font with incorrect encoding. - */ - if (encoding_id < 0) { - WARN("Built-in encoding used for CFF/OpenType font."); - WARN("CFF font in OpenType font sometimes have strange built-in encoding."); - WARN("If you find text is not encoded properly in the generated PDF file,"); - WARN("please specify appropriate \".enc\" file in your fontmap."); - } - pdf_font_set_subtype (font, PDF_FONT_FONTTYPE_TYPE1C); - - embedding = pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED) ? 0 : 1; - descriptor = pdf_font_get_descriptor(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, 1, fontname); - if (!tmp) { - ERROR("Could not obtain neccesary font info from OpenType table."); - return -1; - } - pdf_merge_dict (descriptor, tmp); /* copy */ - pdf_release_obj(tmp); - if (!embedding) { /* tt_get_fontdesc may have changed this */ - pdf_font_set_flags(font, PDF_FONT_FLAG_NOEMBED); - } - - sfnt_close(sfont); - if (fp) - DPXFCLOSE(fp); - - return 0; -} - -static void -add_SimpleMetrics (pdf_font *font, cff_font *cffont, - double *widths, card16 num_glyphs) -{ - pdf_obj *fontdict; - int code, firstchar, lastchar, tfm_id; - char *usedchars; - pdf_obj *tmp_array; - double scaling; - - fontdict = pdf_font_get_resource(font); - usedchars = pdf_font_get_usedchars(font); - - /* The widhts array in the font dictionary must be given relative - * to the default scaling of 1000:1, not relative to the scaling - * given by the font matrix. - */ - if (cff_dict_known(cffont->topdict, "FontMatrix")) - scaling = 1000*cff_dict_get(cffont->topdict, "FontMatrix", 0); - else - scaling = 1; - - tmp_array = pdf_new_array(); - if (num_glyphs <= 1) { - /* This should be error. */ - firstchar = lastchar = 0; - pdf_add_array(tmp_array, pdf_new_number(0.0)); - } else { - firstchar = 255; lastchar = 0; - for (code = 0; code < 256; code++) { - if (usedchars[code]) { - if (code < firstchar) firstchar = code; - if (code > lastchar) lastchar = code; - } - } - if (firstchar > lastchar) { - ERROR("No glyphs used at all!"); - pdf_release_obj(tmp_array); - return; - } - tfm_id = tfm_open(pdf_font_get_mapname(font), 0); - for (code = firstchar; code <= lastchar; code++) { - if (usedchars[code]) { - double width; - if (tfm_id < 0) /* tfm is not found */ - width = scaling * widths[code]; - else - width = 1000. * tfm_get_width(tfm_id, code); - pdf_add_array(tmp_array, - pdf_new_number(ROUND(width, 0.1))); - } else { - pdf_add_array(tmp_array, pdf_new_number(0.0)); - } - } - } - - if (pdf_array_length(tmp_array) > 0) { - pdf_add_dict(fontdict, - pdf_new_name("Widths"), pdf_ref_obj(tmp_array)); - } - pdf_release_obj(tmp_array); - - pdf_add_dict(fontdict, - pdf_new_name("FirstChar"), pdf_new_number(firstchar)); - pdf_add_dict(fontdict, - pdf_new_name("LastChar"), pdf_new_number(lastchar)); - - return; -} - -int -pdf_font_load_type1c (pdf_font *font) -{ - pdf_obj *fontdict, *descriptor; - char *usedchars; - char *fontname, *uniqueTag, *ident, *fullname; - FILE *fp = NULL; - int encoding_id; - pdf_obj *fontfile, *stream_dict; - char **enc_vec; - sfnt *sfont; - cff_font *cffont; - cff_index *charstrings, *topdict, *cs_idx; - cff_charsets *charset = NULL; - cff_encoding *encoding = NULL; - long topdict_offset, private_size; - long charstring_len, max_len; - long size, offset = 0; - long stream_data_len = 0; - card8 *stream_data_ptr, *data; - card16 num_glyphs, cs_count, code; - cs_ginfo ginfo; - double nominal_width, default_width, notdef_width; - double widths[256]; - int verbose; - - ASSERT(font); - - verbose = pdf_font_get_verbose(); - - if (!pdf_font_is_in_use(font)) { - return 0; - } - - if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { - ERROR("Only embedded font supported for CFF/OpenType font."); - } - - usedchars = pdf_font_get_usedchars (font); - fontname = pdf_font_get_fontname (font); - ident = pdf_font_get_ident (font); - uniqueTag = pdf_font_get_uniqueTag (font); - if (!usedchars || - !fontname || !ident) { - ERROR("Unexpected error...."); - } - - fontdict = pdf_font_get_resource (font); - descriptor = pdf_font_get_descriptor(font); - encoding_id = pdf_font_get_encoding (font); - -#ifdef XETEX - sfont = sfnt_open(pdf_font_get_ft_face(font), SFNT_TYPE_POSTSCRIPT); -#else - fp = DPXFOPEN(ident, DPX_RES_TYPE_OTFONT); - if (!fp) { - ERROR("Could not open OpenType font: %s", ident); - } - - sfont = sfnt_open(fp); -#endif - if (!sfont) { - ERROR("Could not open OpenType font: %s", ident); - } - if (sfnt_read_table_directory(sfont, 0) < 0) { - ERROR("Could not read OpenType table directory: %s", ident); - } - if (sfont->type != SFNT_TYPE_POSTSCRIPT || - (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) { - ERROR("Not a CFF/OpenType font ?"); - } - - cffont = cff_open(sfont, offset, 0); - if (!cffont) { - ERROR("Could not open CFF font."); - } - if (cffont->flag & FONTTYPE_CIDFONT) { - ERROR("This is CIDFont..."); - } - - fullname = NEW(strlen(fontname) + 8, char); - sprintf(fullname, "%6s+%s", uniqueTag, fontname); - - /* Offsets from DICTs */ - cff_read_charsets(cffont); - if (encoding_id < 0) - cff_read_encoding(cffont); - cff_read_private(cffont); - cff_read_subrs (cffont); - - /* FIXME */ - cffont->_string = cff_new_index(0); - - /* New Charsets data */ - charset = NEW(1, cff_charsets); - charset->format = 0; - charset->num_entries = 0; - charset->data.glyphs = NEW(256, s_SID); - - /* - * Encoding related things. - */ - enc_vec = NULL; - if (encoding_id >= 0) { - enc_vec = pdf_encoding_get_encoding(encoding_id); - } else { - pdf_obj *tounicode; - - /* - * Create enc_vec and ToUnicode CMap for built-in encoding. - */ - enc_vec = NEW(256, char *); - for (code = 0; code < 256; code++) { - if (usedchars[code]) { - card16 gid; - - gid = cff_encoding_lookup(cffont, code); - enc_vec[code] = cff_get_string(cffont, - cff_charsets_lookup_inverse(cffont, gid)); - } else { - enc_vec[code] = NULL; - } - } - if (!pdf_lookup_dict(fontdict, "ToUnicode")) { - tounicode = pdf_create_ToUnicode_CMap(fullname, - enc_vec, usedchars); - if (tounicode) { - pdf_add_dict(fontdict, - pdf_new_name("ToUnicode"), - pdf_ref_obj (tounicode)); - pdf_release_obj(tounicode); - } - } - } - - /* - * New Encoding data: - * - * We should not use format 0 here. - * The number of encoded glyphs (num_entries) is limited to 255 in format 0, - * and hence it causes problem for encodings that uses full 256 code-points. - * As we always sort glyphs by encoding, we can avoid this problem simply - * by using format 1; Using full range result in a single range, 0 255. - * - * Creating actual encoding date is delayed to eliminate character codes to - * be mapped to .notdef and to handle multiply-encoded glyphs. - */ - encoding = NEW(1, cff_encoding); - encoding->format = 1; - encoding->num_entries = 0; - encoding->data.range1 = NEW(255, cff_range1); - encoding->num_supps = 0; - encoding->supp = NEW(255, cff_map); - - /* - * Charastrings. - */ - offset = (long) cff_dict_get(cffont->topdict, "CharStrings", 0); - cff_seek_set(cffont, offset); - cs_idx = cff_get_index_header(cffont); - - /* Offset is now absolute offset ... fixme */ - offset = cffont->sfont->loc; - cs_count = cs_idx->count; - if (cs_count < 2) { - ERROR("No valid charstring data found."); - } - - /* New CharStrings INDEX */ - charstrings = cff_new_index(257); /* 256 + 1 for ".notdef" glyph */ - max_len = 2 * CS_STR_LEN_MAX; - charstrings->data = NEW(max_len, card8); - charstring_len = 0; - - /* - * Information from OpenType table is rough estimate. Replace with accurate value. - */ - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "StdVW")) { - double stemv; - - stemv = cff_dict_get(cffont->private[0], "StdVW", 0); - pdf_add_dict(descriptor, - pdf_new_name("StemV"), pdf_new_number(stemv)); - } - - /* - * Widths - */ - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "defaultWidthX")) { - default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0); - } else { - default_width = CFF_DEFAULTWIDTHX_DEFAULT; - } - if (cffont->private[0] && - cff_dict_known(cffont->private[0], "nominalWidthX")) { - nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0); - } else { - nominal_width = CFF_NOMINALWIDTHX_DEFAULT; - } - - data = NEW(CS_STR_LEN_MAX, card8); - - /* First we add .notdef glyph. - * All Type 1 font requires .notdef glyph to be present. - */ - if (verbose > 2) { - MESG("[glyphs:/.notdef"); - } - size = cs_idx->offset[1] - cs_idx->offset[0]; - if (size > CS_STR_LEN_MAX) { - ERROR("Charstring too long: gid=%u, %ld bytes", 0, size); - } - charstrings->offset[0] = charstring_len + 1; - sfnt_seek_set(cffont->sfont, offset + cs_idx->offset[0] - 1); - sfnt_read(data, size, cffont->sfont); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, cffont->subrs[0], - default_width, nominal_width, &ginfo); - notdef_width = ginfo.wx; - - /* - * Subset font - */ - num_glyphs = 1; - for (code = 0; code < 256; code++) { - card16 gid, j; - s_SID sid_orig, sid; - - widths[code] = notdef_width; - - if (!usedchars[code] || !enc_vec[code] || - !strcmp(enc_vec[code], ".notdef")) - continue; - - /* - * FIXME: - * cff_get_sid() obtain SID from original String INDEX. - * It should be cff_string_get_sid(string, ...). - * cff_add_string(cff, ...) -> cff_string_add(string, ...). - */ - sid_orig = cff_get_sid (cffont, enc_vec[code]); - sid = sid_orig < CFF_STDSTR_MAX ? - sid_orig : cff_add_string(cffont, enc_vec[code], 0); - /* - * We use "unique = 0" because duplicate strings are impossible - * at this stage unless the original font already had duplicates. - */ - - /* - * Check if multiply-encoded glyph. - */ - for (j = 0; j < charset->num_entries; j++) { - if (sid == charset->data.glyphs[j]) { - /* Already have this glyph. */ - encoding->supp[encoding->num_supps].code = code; - encoding->supp[encoding->num_supps].glyph = sid; - usedchars[code] = 0; /* Used but multiply-encoded. */ - encoding->num_supps += 1; - break; - } - } - if (j < charset->num_entries) { - continue; /* Prevent duplication. */ - } - - /* This is new encoding entry. */ - gid = cff_charsets_lookup(cffont, sid_orig); /* FIXME */ - if (gid == 0) { - WARN("Glyph \"%s\" missing in font \"%s\".", enc_vec[code], fontname); - WARN("Maybe incorrect encoding specified."); - usedchars[code] = 0; /* Set unused for writing correct encoding */ - continue; - } - if (verbose > 2) { - MESG("/%s", enc_vec[code]); - } - - size = cs_idx->offset[gid+1] - cs_idx->offset[gid]; - if (size > CS_STR_LEN_MAX) { - ERROR("Charstring too long: gid=%u, %ld bytes", gid, size); - } - - if (charstring_len + CS_STR_LEN_MAX >= max_len) { - max_len = charstring_len + 2 * CS_STR_LEN_MAX; - charstrings->data = RENEW(charstrings->data, max_len, card8); - } - charstrings->offset[num_glyphs] = charstring_len + 1; - sfnt_seek_set(cffont->sfont, offset + cs_idx->offset[gid] - 1); - sfnt_read(data, size, cffont->sfont); - charstring_len += cs_copy_charstring(charstrings->data + charstring_len, - max_len - charstring_len, - data, size, - cffont->gsubr, cffont->subrs[0], - default_width, nominal_width, &ginfo); - widths[code] = ginfo.wx; - charset->data.glyphs[charset->num_entries] = sid; - charset->num_entries += 1; - num_glyphs++; - } - if (verbose > 2) { - MESG("]"); - } - RELEASE(data); - - /* - * Now we create encoding data. - */ - if (encoding->num_supps > 0) - encoding->format |= 0x80; /* Have supplemantary data. */ - else { - RELEASE(encoding->supp); /* FIXME */ - } - for (code = 0; code < 256; code++) { - if (!usedchars[code] || - !enc_vec[code] || !strcmp(enc_vec[code], ".notdef")) - continue; - encoding->data.range1[encoding->num_entries].first = code; - encoding->data.range1[encoding->num_entries].n_left = 0; - code++; - while (code < 256 && usedchars[code] && - enc_vec[code] && strcmp(enc_vec[code], ".notdef")) { - encoding->data.range1[encoding->num_entries].n_left += 1; - code++; - } - encoding->num_entries += 1; - /* The above while() loop stopped at unused char or code == 256. */ - } - - /* cleanup */ - if (encoding_id < 0 && enc_vec) { - for (code = 0; code < 256; code++) { - if (enc_vec[code]) { - RELEASE(enc_vec[code]); - } - } - RELEASE(enc_vec); - } - - cff_release_index(cs_idx); - - charstrings->offset[num_glyphs] = charstring_len + 1; - charstrings->count = num_glyphs; - charstring_len = cff_index_size(charstrings); - cffont->num_glyphs = num_glyphs; - - /* - * Discard old one, set new data. - */ - if (cffont->charsets) - cff_release_charsets(cffont->charsets); - cffont->charsets = charset; - if (cffont->encoding) - cff_release_encoding(cffont->encoding); - cffont->encoding = encoding; - /* - * We don't use subroutines at all. - */ - if (cffont->gsubr) - cff_release_index(cffont->gsubr); - cffont->gsubr = cff_new_index(0); - if (cffont->subrs[0]) - cff_release_index(cffont->subrs[0]); - cffont->subrs[0] = NULL; - - /* - * Flag must be reset since cff_pack_encoding(charset) does not write - * encoding(charset) if HAVE_STANDARD_ENCODING(CHARSET) is set. We are - * re-encoding font. - */ - cffont->flag = FONTTYPE_FONT; - - /* - * FIXME: - * Update String INDEX to delete unused strings. - */ - cff_dict_update(cffont->topdict, cffont); - if (cffont->private[0]) - cff_dict_update(cffont->private[0], cffont); - cff_update_string(cffont); - - /* - * Calculate sizes of Top DICT and Private DICT. - * All offset values in DICT are set to long (32-bit) integer - * in cff_dict_pack(), those values are updated later. - */ - topdict = cff_new_index(1); - - cff_dict_remove(cffont->topdict, "UniqueID"); - cff_dict_remove(cffont->topdict, "XUID"); - - /* - * Force existence of Encoding. - */ - if (!cff_dict_known(cffont->topdict, "Encoding")) - cff_dict_add(cffont->topdict, "Encoding", 1); - topdict->offset[1] = cff_dict_pack(cffont->topdict, - (card8 *) work_buffer, - WORK_BUFFER_SIZE) + 1; - private_size = 0; - if (cffont->private[0]) { - cff_dict_remove(cffont->private[0], "Subrs"); /* no Subrs */ - private_size = cff_dict_pack(cffont->private[0], - (card8 *) work_buffer, WORK_BUFFER_SIZE); - } - - /* - * Estimate total size of fontfile. - */ - stream_data_len = 4; /* header size */ - - stream_data_len += cff_set_name(cffont, fullname); - RELEASE(fullname); - - stream_data_len += cff_index_size(topdict); - stream_data_len += cff_index_size(cffont->string); - stream_data_len += cff_index_size(cffont->gsubr); - - /* We are using format 1 for Encoding and format 0 for charset. - * TODO: Should implement cff_xxx_size(). - */ - stream_data_len += 2 + (encoding->num_entries)*2 + 1 + (encoding->num_supps)*3; - stream_data_len += 1 + (charset->num_entries)*2; - stream_data_len += charstring_len; - stream_data_len += private_size; - - /* - * Now we create FontFile data. - */ - stream_data_ptr = NEW(stream_data_len, card8); - - /* - * Data Layout order as described in CFF spec., sec 2 "Data Layout". - */ - offset = 0; - /* Header */ - offset += cff_put_header(cffont, stream_data_ptr + offset, stream_data_len - offset); - /* Name */ - offset += cff_pack_index(cffont->name, stream_data_ptr + offset, stream_data_len - offset); - /* Top DICT */ - topdict_offset = offset; - offset += cff_index_size(topdict); - /* Strings */ - offset += cff_pack_index(cffont->string, - stream_data_ptr + offset, stream_data_len - offset); - /* Global Subrs */ - offset += cff_pack_index(cffont->gsubr, - stream_data_ptr + offset, stream_data_len - offset); - /* Encoding */ - cff_dict_set(cffont->topdict, "Encoding", 0, offset); - offset += cff_pack_encoding(cffont, - stream_data_ptr + offset, stream_data_len - offset); - /* charset */ - cff_dict_set(cffont->topdict, "charset", 0, offset); - offset += cff_pack_charsets(cffont, - stream_data_ptr + offset, stream_data_len - offset); - /* CharStrings */ - cff_dict_set(cffont->topdict, "CharStrings", 0, offset); - offset += cff_pack_index(charstrings, - stream_data_ptr + offset, charstring_len); - cff_release_index(charstrings); - /* Private */ - cff_dict_set(cffont->topdict, "Private", 1, offset); - if (cffont->private[0] && private_size > 0) - private_size = cff_dict_pack(cffont->private[0], - stream_data_ptr + offset, private_size); - cff_dict_set(cffont->topdict, "Private", 0, private_size); - offset += private_size; - - /* Finally Top DICT */ - topdict->data = NEW(topdict->offset[1] - 1, card8); - cff_dict_pack (cffont->topdict, topdict->data, topdict->offset[1] - 1); - cff_pack_index(topdict, - stream_data_ptr + topdict_offset, cff_index_size(topdict)); - cff_release_index(topdict); - - /* Copyright and Trademark Notice ommited. */ - - /* Handle Widths in fontdict. */ - add_SimpleMetrics(font, cffont, widths, num_glyphs); - - /* Close font */ - cff_close (cffont); - sfnt_close(sfont); - - if (fp) - DPXFCLOSE(fp); - - if (verbose > 1) { - MESG("[%u/%u glyphs][%ld bytes]", num_glyphs, cs_count, offset); - } - - /* - * CharSet might be recommended for subsetted font, but it is meaningful - * only for Type 1 font... - */ - - /* - * Write PDF FontFile data. - */ - fontfile = pdf_new_stream(STREAM_COMPRESS); - stream_dict = pdf_stream_dict(fontfile); - pdf_add_dict(descriptor, - pdf_new_name("FontFile3"), pdf_ref_obj (fontfile)); - pdf_add_dict(stream_dict, - pdf_new_name("Subtype"), pdf_new_name("Type1C")); - pdf_add_stream (fontfile, (void *) stream_data_ptr, offset); - pdf_release_obj(fontfile); - - RELEASE(stream_data_ptr); - - return 0; -} diff --git a/Build/source/texk/dvipdfm-x/xsrc/xbb.c b/Build/source/texk/dvipdfm-x/xsrc/xbb.c deleted file mode 100644 index da771659c78..00000000000 --- a/Build/source/texk/dvipdfm-x/xsrc/xbb.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - - This is extractbb, a bounding box extraction program. - - Copyright (C) 2008-2012 by Jin-Hwan Cho - - 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 -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "numbers.h" -#include "system.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "pdfobj.h" -#include "pdfdoc.h" -#include "pdfparse.h" - -#include "config.h" - -#include "jpegimage.h" -#include "pngimage.h" - -#include "dvipdfmx.h" - -#define XBB_PROGRAM "extractbb" -#define XBB_VERSION VERSION - -static void show_version(void) -{ - fprintf (stdout, "%s, version %s, Copyright (C) 2008 by Jin-Hwan Cho\n", - XBB_PROGRAM, XBB_VERSION); - fprintf (stdout, "A bounding box extraction utility from PDF, PNG, and JPEG.\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"); - fprintf (stdout, "(at your option) any later version.\n"); -} - -static void show_usage(void) -{ - fprintf (stdout, "\nUsage: %s [-v] [-b] [-m|-x] [files]\n", XBB_PROGRAM); - fprintf (stdout, "\t-v\tBe verbose\n"); - fprintf (stdout, "\t-b\tWrite output file in binary mode\n"); - if(compat_mode) { - fprintf (stdout, "\t-m\tOutput .bb file used in DVIPDFM (default)\n"); - fprintf (stdout, "\t-x\tOutput .xbb file used in DVIPDFMx\n"); - } else { - fprintf (stdout, "\t-m\tOutput .bb file used in DVIPDFM\n"); - fprintf (stdout, "\t-x\tOutput .xbb file used in DVIPDFMx (default)\n"); - } -} - -static void usage(void) -{ - show_version(); - show_usage(); - exit(1); -} - -static char verbose = 0; - -static void do_time(FILE *file) -{ - time_t current_time; - struct tm *bd_time; - - time(¤t_time); - bd_time = localtime(¤t_time); - fprintf(file, "%%%%CreationDate: %s\n", asctime(bd_time)); -} - -const char *extensions[] = { - ".jpeg", ".JPEG", ".jpg", ".JPG", ".pdf", ".PDF", ".png", ".PNG" -}; - -static int xbb_to_file = 1; - -static char *make_xbb_filename(const char *name) -{ - int i; - char *result; - - for (i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) { - if (strlen(extensions[i]) < strlen(name) && - strncmp(name+strlen(name)-strlen(extensions[i]), extensions[i], strlen(extensions[i])) == 0) - break; - } - if (i == sizeof(extensions) / sizeof(extensions[0])) { - WARN("%s: Filename does not end in a recognizable extension.\n", name); - result = NEW(strlen(name)+5, char); /* 5 = ".xbb" + trailing 0 */ - strcpy(result, name); - } else { /* Remove extension */ - result = NEW(strlen(name)-strlen(extensions[i])+5, char); /* 5 = ".xbb" + trailing 0 */ - strncpy(result, name, strlen(name)-strlen(extensions[i])); - result[strlen(name)-strlen(extensions[i])] = 0; - } - strcat(result, (compat_mode ? ".bb" : ".xbb")); - return result; -} - -static void write_xbb(char *fname, - double bbllx_f, double bblly_f, - double bburx_f, double bbury_f, - int pdf_version, long pagecount) -{ - char *outname = NULL; - FILE *fp; - - long bbllx = ROUND(bbllx_f, 1.0), bblly = ROUND(bblly_f, 1.0); - long bburx = ROUND(bburx_f, 1.0), bbury = ROUND(bbury_f, 1.0); - - if (xbb_to_file) { - outname = make_xbb_filename(fname); - if ((fp = MFOPEN(outname, FOPEN_W_MODE)) == NULL) { - ERROR("Unable to open output file: %s\n", outname); - } - } else { - fp = stdout; -#ifdef WIN32 - setmode(fileno(fp), _O_BINARY); -#endif - } - - if (verbose) { - MESG("Writing to %s: ", xbb_to_file ? outname : "stdout"); - MESG("Bounding box: %d %d %d %d\n", bbllx, bblly, bburx, bbury); - } - - fprintf(fp, "%%%%Title: %s\n", fname); - fprintf(fp, "%%%%Creator: %s %s\n", XBB_PROGRAM, XBB_VERSION); - fprintf(fp, "%%%%BoundingBox: %ld %ld %ld %ld\n", bbllx, bblly, bburx, bbury); - - if (!compat_mode) { - /* Note: - * According to Adobe Technical Note #5644, the arguments to - * "%%HiResBoundingBox:" must be of type real. And according - * to the PostScript Language Reference, a real number must - * be written with a decimal point (or an exponent). Hence - * it seems illegal to replace "0.0" by "0". - */ - fprintf(fp, "%%%%HiResBoundingBox: %f %f %f %f\n", - bbllx_f, bblly_f, bburx_f, bbury_f); - if (pdf_version >= 0) { - fprintf(fp, "%%%%PDFVersion: 1.%d\n", pdf_version); - fprintf(fp, "%%%%Pages: %ld\n", pagecount); - } - } - - do_time(fp); - - if (xbb_to_file) { - RELEASE(outname); - MFCLOSE(fp); - } -} - -static void do_jpeg (FILE *fp, char *filename) -{ - long width, height; - double xdensity, ydensity; - - if (jpeg_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { - WARN("%s does not look like a JPEG file...\n", filename); - return; - } - - write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); - return; -} - -#ifdef HAVE_LIBPNG -static void do_png (FILE *fp, char *filename) -{ - long width, height; - double xdensity, ydensity; - - if (png_get_bbox(fp, &width, &height, &xdensity, &ydensity) < 0) { - WARN("%s does not look like a PNG file...\n", filename); - return; - } - - write_xbb(filename, 0, 0, xdensity*width, ydensity*height, -1, -1); - return; -} -#endif /* HAVE_LIBPNG */ - -#ifdef XETEX -static int rect_equal (pdf_obj *rect1, pdf_obj *rect2) -{ - int i; - if (!rect1 || !rect2) return 0; - for (i = 0; i < 4; i++) { - if (pdf_number_value(pdf_get_array(rect1, i)) != pdf_number_value(pdf_get_array(rect2, i))) return 0; - } - return 1; -} - -static int pdf_get_info (FILE *image_file, char *filename, int *version, - double *llx, double *lly, double *urx, double *ury) -{ - pdf_obj *page_tree; - pdf_obj *bbox; - pdf_file *pf; - - page_tree = NULL; - { - pdf_obj *trailer, *catalog; - - pf = pdf_open(filename, image_file); - if (!pf) - return -1; - - trailer = pdf_file_get_trailer(pf); - - if (pdf_lookup_dict(trailer, "Encrypt")) { - WARN("This PDF document is encrypted."); - pdf_release_obj(trailer); - pdf_close(pf); - return -1; - } - catalog = pdf_deref_obj(pdf_lookup_dict(trailer, "Root")); - if (!catalog) { - WARN("Catalog isn't where I expect it."); - pdf_close(pf); - return -1; - } - pdf_release_obj(trailer); - page_tree = pdf_deref_obj(pdf_lookup_dict(catalog, "Pages")); - pdf_release_obj(catalog); - } - if (!page_tree) { - WARN("Page tree not found."); - pdf_close(pf); - return -1; - } - { - pdf_obj *kids_ref, *kids; - pdf_obj *crop_box; - 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; - - while ((kids_ref = pdf_lookup_dict(page_tree, "Kids")) != NULL) { - kids = pdf_deref_obj(kids_ref); - pdf_release_obj(page_tree); - page_tree = pdf_deref_obj(pdf_get_array(kids, 0)); - pdf_release_obj(kids); - - 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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(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; - } else - pdf_release_obj(tmp); - } - if ((tmp = pdf_deref_obj(pdf_lookup_dict(page_tree, "CropBox")))) { - if (crop_box) - pdf_release_obj(crop_box); - crop_box = tmp; - } - } - if (crop_box) { - pdf_release_obj(bbox); - bbox = crop_box; - } - } - pdf_release_obj(page_tree); - - if (!bbox) { - WARN("No BoundingBox information available."); - pdf_close(pf); - return -1; - } - - *version = pdf_file_get_version(pf); - - *llx = pdf_number_value(pdf_get_array(bbox, 0)); - *lly = pdf_number_value(pdf_get_array(bbox, 1)); - *urx = pdf_number_value(pdf_get_array(bbox, 2)); - *ury = pdf_number_value(pdf_get_array(bbox, 3)); - - pdf_release_obj(bbox); - - pdf_close(pf); - return 0; -} - -static void do_pdf (FILE *fp, char *filename) -{ - double llx, lly, urx, ury; - int version; - - if (pdf_get_info(fp, filename, &version, &llx, &lly, &urx, &ury) < 0) { - fprintf (stderr, "%s does not look like a PDF file...\n", filename); - return; - } - write_xbb(filename, llx, lly, urx, ury, version, 1); - return; -} -#else -static void do_pdf (FILE *fp, char *filename) -{ - pdf_obj *page; - pdf_file *pf; - long page_no = 1; - long count; - pdf_rect bbox; - - pf = pdf_open(filename, fp); - if (!pf) { - WARN("%s does not look like a PDF file...\n", filename); - return; - } - - page = pdf_doc_get_page(pf, page_no, &count, &bbox, NULL); - - pdf_close(pf); - - if (!page) - return; - - pdf_release_obj(page); - write_xbb(filename, bbox.llx, bbox.lly, bbox.urx, bbox.ury, - pdf_file_get_version(pf), count); -} -#endif - -int extractbb (int argc, char *argv[]) -{ - pdf_files_init(); - - pdf_set_version(5); - - argc -= 1; argv += 1; - if (argc == 0) - usage(); - - while (argc > 0 && *argv[0] == '-') { - switch (*(argv[0]+1)) { - case 'b': - argc -= 1; argv += 1; - break; - case 'm': - compat_mode = 1; - argc -= 1; argv += 1; - break; - case 'x': - compat_mode = 0; - argc -= 1; argv += 1; - break; - case 'v': - verbose = 1; - argc -= 1; argv += 1; - break; - case 'h': - show_version(); - show_usage(); - exit (0); - default: - usage(); - } - } - - for (; argc > 0; argc--, argv++) { - FILE *infile = NULL; - char *kpse_file_name; - if (!(kpse_file_name = kpse_find_pict(argv[0])) || - (infile = MFOPEN(kpse_file_name, FOPEN_RBIN_MODE)) == NULL) { - WARN("Can't find file (%s)...skipping\n", argv[0]); - goto cont; - } - if (check_for_jpeg(infile)) { - do_jpeg(infile, kpse_file_name); - goto cont; - } - if (check_for_pdf(infile)) { - do_pdf(infile, kpse_file_name); - goto cont; - } -#ifdef HAVE_LIBPNG - if (check_for_png(infile)) { - do_png(infile, kpse_file_name); - goto cont; - } -#endif /* HAVE_LIBPNG */ - WARN("Can't handle file type for file named %s\n", argv[0]); - cont: - if (kpse_file_name) - RELEASE(kpse_file_name); - if (infile) - MFCLOSE(infile); - } - - pdf_files_close(); - - return 0; -} -- cgit v1.2.3