summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2021-03-30 10:59:39 +0200
committerThomas Deutschmann <whissi@gentoo.org>2021-04-01 00:04:14 +0200
commit5ff1d6955496b3cf9a35042c9ac35db43bc336b1 (patch)
tree6d470f7eb448f59f53e8df1010aec9dad8ce1f72 /devices
parentImport Ghostscript 9.53.1 (diff)
downloadghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.gz
ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.bz2
ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.zip
Import Ghostscript 9.54ghostscript-9.54
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'devices')
-rw-r--r--devices/dcontrib.mak2
-rw-r--r--devices/devs.mak75
-rw-r--r--devices/extract.mak48
-rw-r--r--devices/gdev3852.c2
-rw-r--r--devices/gdev4081.c2
-rw-r--r--devices/gdev8510.c2
-rw-r--r--devices/gdev8bcm.c2
-rw-r--r--devices/gdev8bcm.h2
-rw-r--r--devices/gdevatx.c2
-rw-r--r--devices/gdevbit.c7
-rw-r--r--devices/gdevbj10.c2
-rw-r--r--devices/gdevbjc.h2
-rw-r--r--devices/gdevbjcl.c2
-rw-r--r--devices/gdevbjcl.h2
-rw-r--r--devices/gdevbmp.c2
-rw-r--r--devices/gdevbmp.h2
-rw-r--r--devices/gdevbmpc.c2
-rw-r--r--devices/gdevccr.c2
-rw-r--r--devices/gdevcdj.c2
-rw-r--r--devices/gdevcfax.c2
-rw-r--r--devices/gdevchameleon.c2
-rw-r--r--devices/gdevcif.c2
-rw-r--r--devices/gdevclj.c2
-rw-r--r--devices/gdevcljc.c2
-rw-r--r--devices/gdevcmykog.c8
-rw-r--r--devices/gdevcslw.c2
-rw-r--r--devices/gdevdfax.c2
-rw-r--r--devices/gdevdjet.c2
-rw-r--r--devices/gdevdjtc.c2
-rw-r--r--devices/gdevdljm.c2
-rw-r--r--devices/gdevdljm.h2
-rw-r--r--devices/gdevdm24.c2
-rw-r--r--devices/gdevdsp.c87
-rw-r--r--devices/gdevdsp.h2
-rw-r--r--devices/gdevdsp2.h2
-rw-r--r--devices/gdevepsc.c6
-rw-r--r--devices/gdevepsn.c8
-rw-r--r--devices/gdevescp.c2
-rw-r--r--devices/gdevfax.c4
-rw-r--r--devices/gdevfax.h2
-rw-r--r--devices/gdevfpng.c2
-rw-r--r--devices/gdevhl7x.c2
-rw-r--r--devices/gdevicov.c8
-rw-r--r--devices/gdevijs.c2
-rw-r--r--devices/gdevimgn.c2
-rw-r--r--devices/gdevjbig2.c128
-rw-r--r--devices/gdevjpeg.c2
-rw-r--r--devices/gdevjpx.c229
-rw-r--r--devices/gdevl31s.c2
-rw-r--r--devices/gdevlbp8.c2
-rw-r--r--devices/gdevlj56.c2
-rw-r--r--devices/gdevlp8k.c2
-rw-r--r--devices/gdevlxm.c4
-rw-r--r--devices/gdevmeds.c2
-rw-r--r--devices/gdevmeds.h2
-rw-r--r--devices/gdevmgr.c2
-rw-r--r--devices/gdevmgr.h2
-rw-r--r--devices/gdevmiff.c2
-rw-r--r--devices/gdevn533.c2
-rw-r--r--devices/gdevo182.c2
-rw-r--r--devices/gdevocr.c58
-rw-r--r--devices/gdevokii.c2
-rw-r--r--devices/gdevpbm.c2
-rw-r--r--devices/gdevpcl.c2
-rw-r--r--devices/gdevpcl.h2
-rw-r--r--devices/gdevpcx.c2
-rw-r--r--devices/gdevpdfimg.c42
-rw-r--r--devices/gdevpdfimg.h13
-rw-r--r--devices/gdevpdfocr.c64
-rw-r--r--devices/gdevpe.c2
-rw-r--r--devices/gdevperm.c2
-rw-r--r--devices/gdevphex.c2
-rw-r--r--devices/gdevpjet.c2
-rw-r--r--devices/gdevplan.c2
-rw-r--r--devices/gdevplib.c2
-rw-r--r--devices/gdevplib.h2
-rw-r--r--devices/gdevpm.h2
-rw-r--r--devices/gdevpng.c2
-rw-r--r--devices/gdevpsd.c75
-rw-r--r--devices/gdevpsd.h2
-rw-r--r--devices/gdevpsim.c2
-rw-r--r--devices/gdevpxut.c4
-rw-r--r--devices/gdevpxut.h2
-rw-r--r--devices/gdevrinkj.c2
-rw-r--r--devices/gdevsj48.c2
-rw-r--r--devices/gdevsnfb.c2
-rw-r--r--devices/gdevsppr.c2
-rw-r--r--devices/gdevstc.c2
-rw-r--r--devices/gdevstc.h2
-rw-r--r--devices/gdevstc1.c2
-rw-r--r--devices/gdevstc2.c2
-rw-r--r--devices/gdevstc3.c2
-rw-r--r--devices/gdevstc4.c2
-rw-r--r--devices/gdevtfax.c2
-rw-r--r--devices/gdevtfax.h2
-rw-r--r--devices/gdevtfnx.c2
-rw-r--r--devices/gdevtifs.c2
-rw-r--r--devices/gdevtifs.h2
-rw-r--r--devices/gdevtknk.c2
-rw-r--r--devices/gdevtrac.c2
-rw-r--r--devices/gdevtsep.c10
-rw-r--r--devices/gdevupd.c2
-rw-r--r--devices/gdevwpr2.c10
-rw-r--r--devices/gdevx.c21
-rw-r--r--devices/gdevx.h6
-rw-r--r--devices/gdevxalt.c2
-rw-r--r--devices/gdevxcf.c4
-rw-r--r--devices/gdevxcmp.c2
-rw-r--r--devices/gdevxcmp.h2
-rw-r--r--devices/gdevxini.c32
-rw-r--r--devices/gdevxres.c2
-rw-r--r--devices/gxfcopy.c100
-rw-r--r--devices/gxfcopy.h2
-rw-r--r--devices/minftrsz.c2
-rw-r--r--devices/minftrsz.h2
-rw-r--r--devices/rinkj/evenbetter-rll.c2
-rw-r--r--devices/rinkj/evenbetter-rll.h2
-rw-r--r--devices/rinkj/rinkj-byte-stream.c2
-rw-r--r--devices/rinkj/rinkj-byte-stream.h2
-rw-r--r--devices/rinkj/rinkj-config.c2
-rw-r--r--devices/rinkj/rinkj-config.h2
-rw-r--r--devices/rinkj/rinkj-device.c2
-rw-r--r--devices/rinkj/rinkj-device.h2
-rw-r--r--devices/rinkj/rinkj-dither.c2
-rw-r--r--devices/rinkj/rinkj-dither.h2
-rw-r--r--devices/rinkj/rinkj-epson870.c2
-rw-r--r--devices/rinkj/rinkj-epson870.h2
-rw-r--r--devices/rinkj/rinkj-screen-eb.c2
-rw-r--r--devices/rinkj/rinkj-screen-eb.h2
-rw-r--r--devices/vector/doc_common.c532
-rw-r--r--devices/vector/doc_common.h58
-rw-r--r--devices/vector/gdevagl.c2
-rw-r--r--devices/vector/gdevagl.h2
-rw-r--r--devices/vector/gdevdocxw.c1376
-rw-r--r--devices/vector/gdevpdf.c171
-rw-r--r--devices/vector/gdevpdfb.c48
-rw-r--r--devices/vector/gdevpdfb.h19
-rw-r--r--devices/vector/gdevpdfc.c43
-rw-r--r--devices/vector/gdevpdfc.h2
-rw-r--r--devices/vector/gdevpdfd.c2
-rw-r--r--devices/vector/gdevpdfe.c32
-rw-r--r--devices/vector/gdevpdfg.c4
-rw-r--r--devices/vector/gdevpdfg.h4
-rw-r--r--devices/vector/gdevpdfi.c512
-rw-r--r--devices/vector/gdevpdfj.c17
-rw-r--r--devices/vector/gdevpdfk.c4
-rw-r--r--devices/vector/gdevpdfm.c101
-rw-r--r--devices/vector/gdevpdfo.c17
-rw-r--r--devices/vector/gdevpdfo.h4
-rw-r--r--devices/vector/gdevpdfp.c182
-rw-r--r--devices/vector/gdevpdfr.c33
-rw-r--r--devices/vector/gdevpdft.c4
-rw-r--r--devices/vector/gdevpdfu.c25
-rw-r--r--devices/vector/gdevpdfv.c2
-rw-r--r--devices/vector/gdevpdfx.h41
-rw-r--r--devices/vector/gdevpdt.c2
-rw-r--r--devices/vector/gdevpdt.h2
-rw-r--r--devices/vector/gdevpdtb.c22
-rw-r--r--devices/vector/gdevpdtb.h2
-rw-r--r--devices/vector/gdevpdtc.c2
-rw-r--r--devices/vector/gdevpdtd.c23
-rw-r--r--devices/vector/gdevpdtd.h4
-rw-r--r--devices/vector/gdevpdte.c272
-rw-r--r--devices/vector/gdevpdtf.c18
-rw-r--r--devices/vector/gdevpdtf.h2
-rw-r--r--devices/vector/gdevpdti.c9
-rw-r--r--devices/vector/gdevpdti.h2
-rw-r--r--devices/vector/gdevpdts.c2
-rw-r--r--devices/vector/gdevpdts.h2
-rw-r--r--devices/vector/gdevpdtt.c119
-rw-r--r--devices/vector/gdevpdtt.h2
-rw-r--r--devices/vector/gdevpdtv.c2
-rw-r--r--devices/vector/gdevpdtv.h2
-rw-r--r--devices/vector/gdevpdtw.c2
-rw-r--r--devices/vector/gdevpdtw.h2
-rw-r--r--devices/vector/gdevpdtx.h2
-rw-r--r--devices/vector/gdevpsdf.h2
-rw-r--r--devices/vector/gdevpsdi.c92
-rw-r--r--devices/vector/gdevpsdp.c25
-rw-r--r--devices/vector/gdevpsds.c2
-rw-r--r--devices/vector/gdevpsds.h2
-rw-r--r--devices/vector/gdevpsdu.c12
-rw-r--r--devices/vector/gdevpsf.h4
-rw-r--r--devices/vector/gdevpsf1.c20
-rw-r--r--devices/vector/gdevpsf2.c11
-rw-r--r--devices/vector/gdevpsfm.c2
-rw-r--r--devices/vector/gdevpsft.c2
-rw-r--r--devices/vector/gdevpsfu.c2
-rw-r--r--devices/vector/gdevpsfx.c2
-rw-r--r--devices/vector/gdevpsu.c2
-rw-r--r--devices/vector/gdevpsu.h2
-rw-r--r--devices/vector/gdevpx.c6
-rw-r--r--devices/vector/gdevtxtw.c778
-rw-r--r--devices/vector/gdevxps.c247
-rw-r--r--devices/vector/opdfread.ps6
-rw-r--r--devices/vector/whitelst.c2
-rw-r--r--devices/vector/whitelst.h2
197 files changed, 4164 insertions, 2050 deletions
diff --git a/devices/dcontrib.mak b/devices/dcontrib.mak
index 975c68bd..423d3ba2 100644
--- a/devices/dcontrib.mak
+++ b/devices/dcontrib.mak
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2020 Artifex Software, Inc.
+# Copyright (C) 2001-2021 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
diff --git a/devices/devs.mak b/devices/devs.mak
index 5526a907..dced3bf4 100644
--- a/devices/devs.mak
+++ b/devices/devs.mak
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2020 Artifex Software, Inc.
+# Copyright (C) 2001-2021 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
@@ -24,7 +24,7 @@ DEVVECSRC=$(DEVVEC)$(D)
DEVI_=$(DEVGENDIR) $(II)$(GLSRCDIR) $(II)$(GLGENDIR) $(II)$(DEVSRCDIR)
DEVF_=
-DEVCCFLAGS=$(I_)$(DEVI_)$(_I) $(I_)$(DEVVEC)$(_I) $(DEVF_)
+DEVCCFLAGS=$(I_)$(DEVI_)$(_I) $(I_)$(DEVVEC)$(_I) $(D_)OCR_VERSION=$(OCR_VERSION)$(_D) $(DEVF_)
DEVCC=$(CC_) $(DEVCCFLAGS)
XPSDEVCC=$(CC_) $(XPSPRINTCFLAGS) $(DEVCCFLAGS)
@@ -117,6 +117,7 @@ DEVGEN=$(DEVGENDIR)$(D)
# High-level file formats:
# pdfwrite PDF output (like Adobe Acrobat Distiller)
# txtwrite ASCII or Unicode text output
+# docxwrite Docx output
# pxlmono Black-and-white PCL XL
# pxlcolor Color PCL XL
# Other raster file formats and devices:
@@ -633,14 +634,14 @@ $(DEVOBJ)gdevpsdi.$(OBJ) : $(DEVVECSRC)gdevpsdi.c $(GXERR)\
$(scfx_h) $(slzwx_h) $(spngpx_h)\
$(strimpl_h) $(szlibx_h) $(sisparam_h)\
$(gdevpsdf_h) $(gdevpsds_h) $(gxdevmem_h) $(gxcspace_h) $(gxparamx_h)\
- $(sjbig2_luratech_h) $(sjpx_luratech_h) $(gsicc_manage_h) $(DEVS_MAK) $(MAKEDIRS)
+ $(gsicc_manage_h) $(DEVS_MAK) $(MAKEDIRS)
$(GDEVLWFJB2JPXCC) $(DEVO_)gdevpsdi.$(OBJ) $(C_) $(DEVVECSRC)gdevpsdi.c
$(DEVOBJ)gdevpsdp.$(OBJ) : $(DEVVECSRC)gdevpsdp.c $(GDEVH)\
$(string__h) $(jpeglib__h)\
$(scfx_h) $(sdct_h) $(slzwx_h) $(srlx_h) $(strimpl_h) $(szlibx_h)\
$(gsparamx_h) $(gsutil_h) $(gdevpsdf_h)\
- $(sjbig2_luratech_h) $(sjpx_luratech_h) $(DEVS_MAK) $(MAKEDIRS)
+ $(DEVS_MAK) $(MAKEDIRS)
$(GDEVLWFJB2JPXCC) $(DEVO_)gdevpsdp.$(OBJ) $(C_) $(DEVVECSRC)gdevpsdp.c
$(DEVOBJ)gdevpsds.$(OBJ) : $(DEVVECSRC)gdevpsds.c $(GX) $(memory__h)\
@@ -659,7 +660,7 @@ $(DEVOBJ)gdevpsdu.$(OBJ) : $(DEVVECSRC)gdevpsdu.c $(GXERR)\
gdevagl_h=$(DEVVECSRC)gdevagl.h
-txtwrite_=$(DEVOBJ)gdevtxtw.$(OBJ) $(DEVOBJ)gdevagl.$(OBJ)
+txtwrite_=$(DEVOBJ)gdevtxtw.$(OBJ) $(DEVOBJ)gdevagl.$(OBJ) $(DEVOBJ)doc_common.$(OBJ)
$(DD)txtwrite.dev : $(ECHOGS_XE) $(txtwrite_) $(GDEV)\
$(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS)
@@ -668,7 +669,7 @@ $(DD)txtwrite.dev : $(ECHOGS_XE) $(txtwrite_) $(GDEV)\
$(DEVOBJ)gdevtxtw.$(OBJ) : $(DEVVECSRC)gdevtxtw.c $(GDEV) $(gdevkrnlsclass_h) \
$(memory__h) $(string__h) $(gp_h) $(gsparam_h) $(gsutil_h) \
$(gsdevice_h) $(gxfont_h) $(gxfont0_h) $(gstext_h) $(gxfcid_h)\
- $(gxgstate_h) $(gxpath_h) $(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS)
+ $(gxgstate_h) $(gxpath_h) $(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS) $(DEVVECSRC)doc_common.h
$(DEVCC) $(DEVO_)gdevtxtw.$(OBJ) $(C_) $(DEVVECSRC)gdevtxtw.c
$(DEVOBJ)gdevagl.$(OBJ) : $(DEVVECSRC)gdevagl.c $(GDEV)\
@@ -676,6 +677,32 @@ $(DEVOBJ)gdevagl.$(OBJ) : $(DEVVECSRC)gdevagl.c $(GDEV)\
$(DEVCC) $(DEVO_)gdevagl.$(OBJ) $(C_) $(DEVVECSRC)gdevagl.c
+# Docx writer
+
+gdevagl_h=$(DEVVECSRC)gdevagl.h
+
+docxwrite_=$(DEVOBJ)gdevdocxw.$(OBJ) $(DEVOBJ)gdevagl.$(OBJ) $(DEVOBJ)doc_common.$(OBJ)
+
+$(DD)docxwrite.dev : $(ECHOGS_XE) $(docxwrite_) $(GDEV)\
+ $(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS) $(EXTRACT_OBJS)
+ $(SETDEV2) $(DD)docxwrite $(docxwrite_) $(EXTRACT_OBJS)
+
+$(DEVOBJ)gdevdocxw.$(OBJ) : $(DEVVECSRC)gdevdocxw.c $(GDEV) $(gdevkrnlsclass_h) \
+ $(memory__h) $(string__h) $(gp_h) $(gsparam_h) $(gsutil_h) \
+ $(gsdevice_h) $(gxfont_h) $(gxfont0_h) $(gstext_h) $(gxfcid_h)\
+ $(gxgstate_h) $(gxpath_h) $(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS) \
+ $(DEVVECSRC)doc_common.h
+ $(DEVCC) $(DEVO_)gdevdocxw.$(OBJ) $(C_) $(DEVVECSRC)gdevdocxw.c
+
+# Shared code used by txtwrite and docxwrite.
+
+$(DEVOBJ)doc_common.$(OBJ) : $(DEVVECSRC)doc_common.c $(GDEV) $(gdevkrnlsclass_h) \
+ $(memory__h) $(string__h) $(gp_h) $(gsparam_h) $(gsutil_h) \
+ $(gsdevice_h) $(gxfont_h) $(gxfont0_h) $(gstext_h) $(gxfcid_h)\
+ $(gxgstate_h) $(gxpath_h) $(gdevagl_h) $(DEVS_MAK) $(MAKEDIRS) $(DEVVECSRC)doc_common.h
+ $(DEVCC) $(DEVO_)doc_common.$(OBJ) $(C_) $(DEVVECSRC)doc_common.c
+
+
################ BEGIN PDF WRITER ################
# We reserve slots here for gdevpdfa...z, just in case we need them.
@@ -847,7 +874,7 @@ $(DEVOBJ)gdevpdfu.$(OBJ) : $(DEVVECSRC)gdevpdfu.c $(GXERR)\
$(gsdsrc_h) $(gsfunc_h) $(gsfunc3_h)\
$(sa85x_h) $(scfx_h) $(sdct_h) $(slzwx_h) $(spngpx_h)\
$(srlx_h) $(sarc4_h) $(smd5_h) $(sstring_h) $(strimpl_h) $(szlibx_h)\
- $(strmio_h) $(sjbig2_luratech_h) $(sjpx_luratech_h)\
+ $(strmio_h) \
$(opdfread_h) $(gdevagl_h) $(gs_mro_e_h) $(gs_mgl_e_h) \
$(DEVS_MAK) $(MAKEDIRS)
$(GDEVLWFJB2JPXCC) $(DEVO_)gdevpdfu.$(OBJ) $(C_) $(DEVVECSRC)gdevpdfu.c
@@ -1248,38 +1275,6 @@ $(DEVOBJ)gdevperm.$(OBJ) : $(DEVSRC)gdevperm.c $(PDEVH) $(math__h)\
$(gdevdcrd_h) $(gscrd_h) $(gscrdp_h) $(gsparam_h) $(gxlum_h) $(DEVS_MAK) $(MAKEDIRS)
$(DEVCC) $(DEVO_)gdevperm.$(OBJ) $(C_) $(DEVSRC)gdevperm.c
-### ------------------------ JBIG2 testing device ---------------------- ###
-
-gdevjbig2_=$(DEVOBJ)gdevjbig2.$(OBJ)
-
-$(DD)gdevjbig2.dev : $(gdevjbig2_) $(GLD)page.dev $(GDEV) \
- $(DEVS_MAK) $(MAKEDIRS)
- $(SETPDEV2) $(DD)gdevjbig2 $(gdevjbig2_)
-
-$(DEVOBJ)gdevjbig2.$(OBJ) : $(DEVSRC)gdevjbig2.c $(PDEVH)\
- $(stream_h) $(strimpl_h) $(sjbig2_luratech_h) $(DEVS_MAK) $(MAKEDIRS)
- $(GDEVLDFJB2CC) $(DEVO_)gdevjbig2.$(OBJ) $(C_) $(DEVSRC)gdevjbig2.c
-
-### ------------------------ JPX testing device ----------------------
-###
-
-gdevjpx_=$(DEVOBJ)gdevjpx.$(OBJ)
-
-$(DD)jpxrgb.dev : $(gdevjpx_) $(GLD)page.dev $(GDEV) \
- $(DEVS_MAK) $(MAKEDIRS)
- $(SETPDEV2) $(DD)jpxrgb $(gdevjpx_)
-
-$(DD)jpxgray.dev : $(gdevjpx_) $(GLD)page.dev $(GDEV) \
- $(DEVS_MAK) $(MAKEDIRS)
- $(SETPDEV2) $(DD)jpxgray $(gdevjpx_)
-
-$(DD)jpxcmyk.dev : $(gdevjpx_) $(GLD)page.dev $(GDEV) \
- $(DEVS_MAK) $(MAKEDIRS)
- $(SETPDEV2) $(DD)jpxcmyk $(gdevjpx_)
-
-$(DEVOBJ)gdevjpx.$(OBJ) : $(DEVSRC)gdevjpx.c $(PDEVH)\
- $(stream_h) $(strimpl_h) $(sjpx_luratech_h) $(DEVS_MAK) $(MAKEDIRS)
- $(GDEVLWFJPXCC) $(DEVO_)gdevjpx.$(OBJ) $(C_) $(DEVSRC)gdevjpx.c
### ------------------------- JPEG file format ------------------------- ###
@@ -1709,7 +1704,7 @@ $(DEVOBJ)gdevtsep_1.$(OBJ) : $(DEVSRC)gdevtsep.c $(PDEVH) $(stdint__h)\
$(DEVOBJ)gdevtsep.$(OBJ) : $(DEVOBJ)gdevtsep_$(WITH_CAL).$(OBJ)
$(CP_) $(DEVOBJ)gdevtsep_$(WITH_CAL).$(OBJ) $(DEVOBJ)gdevtsep.$(OBJ)
-
+
# TIFF Scaled (downscaled gray -> mono), configurable compression
diff --git a/devices/extract.mak b/devices/extract.mak
new file mode 100644
index 00000000..5e186e08
--- /dev/null
+++ b/devices/extract.mak
@@ -0,0 +1,48 @@
+extract_cc = $(CC) $(CCFLAGS) $(I_)$(EXTRACT_DIR)/include$(_I) $(I_)$(ZSRCDIR)$(_I) $(O_)
+extract_out_prefix = $(GLOBJDIR)$(D)extract_
+
+$(extract_out_prefix)alloc.$(OBJ): $(EXTRACT_DIR)/src/alloc.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/alloc.c
+
+$(extract_out_prefix)astring.$(OBJ): $(EXTRACT_DIR)/src/astring.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/astring.c
+
+$(extract_out_prefix)buffer.$(OBJ): $(EXTRACT_DIR)/src/buffer.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/buffer.c
+
+$(extract_out_prefix)docx.$(OBJ): $(EXTRACT_DIR)/src/docx.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/docx.c
+
+$(extract_out_prefix)docx_template.$(OBJ): $(EXTRACT_DIR)/src/docx_template.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/docx_template.c
+
+$(extract_out_prefix)extract.$(OBJ): $(EXTRACT_DIR)/src/extract.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/extract.c
+
+$(extract_out_prefix)join.$(OBJ): $(EXTRACT_DIR)/src/join.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/join.c
+
+$(extract_out_prefix)mem.$(OBJ): $(EXTRACT_DIR)/src/mem.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/mem.c
+
+$(extract_out_prefix)outf.$(OBJ): $(EXTRACT_DIR)/src/outf.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/outf.c
+
+$(extract_out_prefix)xml.$(OBJ): $(EXTRACT_DIR)/src/xml.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/xml.c
+
+$(extract_out_prefix)zip.$(OBJ): $(EXTRACT_DIR)/src/zip.c
+ $(extract_cc)$@ $(C_) $(EXTRACT_DIR)/src/zip.c
+
+EXTRACT_OBJS = \
+ $(extract_out_prefix)alloc.$(OBJ) \
+ $(extract_out_prefix)astring.$(OBJ) \
+ $(extract_out_prefix)buffer.$(OBJ) \
+ $(extract_out_prefix)docx.$(OBJ) \
+ $(extract_out_prefix)docx_template.$(OBJ) \
+ $(extract_out_prefix)extract.$(OBJ) \
+ $(extract_out_prefix)join.$(OBJ) \
+ $(extract_out_prefix)mem.$(OBJ) \
+ $(extract_out_prefix)outf.$(OBJ) \
+ $(extract_out_prefix)xml.$(OBJ) \
+ $(extract_out_prefix)zip.$(OBJ) \
diff --git a/devices/gdev3852.c b/devices/gdev3852.c
index 32649bd1..1b3377b2 100644
--- a/devices/gdev3852.c
+++ b/devices/gdev3852.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdev4081.c b/devices/gdev4081.c
index 6a715b8b..70bfbb51 100644
--- a/devices/gdev4081.c
+++ b/devices/gdev4081.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdev8510.c b/devices/gdev8510.c
index ad5c6978..af9fcf8f 100644
--- a/devices/gdev8510.c
+++ b/devices/gdev8510.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdev8bcm.c b/devices/gdev8bcm.c
index 0adb7963..a76541be 100644
--- a/devices/gdev8bcm.c
+++ b/devices/gdev8bcm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdev8bcm.h b/devices/gdev8bcm.h
index 4b30675a..6b12a24d 100644
--- a/devices/gdev8bcm.h
+++ b/devices/gdev8bcm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevatx.c b/devices/gdevatx.c
index aaf22a5e..1836edf6 100644
--- a/devices/gdevatx.c
+++ b/devices/gdevatx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbit.c b/devices/gdevbit.c
index 86786fb9..600bfdd2 100644
--- a/devices/gdevbit.c
+++ b/devices/gdevbit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -319,6 +319,8 @@ const gx_device_bit gs_bitrgbtags_device =
0, /*DisablePageHandler*/
0, /*ObjectFilter*/
0, /*ObjectHandlerPushed*/
+ 0, /*NupControl*/
+ 0, /*NupHandlerPushed*/
0, /*PageCount*/
0, /*ShowPageCount*/
1, /*NumCopies*/
@@ -332,6 +334,7 @@ const gx_device_bit gs_bitrgbtags_device =
{false}, /*sgr*/
0, /*MaxPatternBitmap*/
0, /*page_uses_transparency*/
+ 0, /*page_uses_overprint*/
{
MAX_BITMAP, BUFFER_SPACE,
{ BAND_PARAMS_INITIAL_VALUES },
@@ -365,7 +368,7 @@ const gx_device_bit gs_bitrgbtags_device =
false, /* file_is_new */
NULL, /* file */
false, /* bg_print_requested */
- {0}, /* bg_print */
+ 0, /* bg_print * */
0, /* num_render_threads_requested */
NULL, /* saved_pages_list */
{0} /* save_procs_while_delaying_erasepage */
diff --git a/devices/gdevbj10.c b/devices/gdevbj10.c
index cbb9c469..9468552a 100644
--- a/devices/gdevbj10.c
+++ b/devices/gdevbj10.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbjc.h b/devices/gdevbjc.h
index 9d58211e..120f528f 100644
--- a/devices/gdevbjc.h
+++ b/devices/gdevbjc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbjcl.c b/devices/gdevbjcl.c
index 4692266b..75377d74 100644
--- a/devices/gdevbjcl.c
+++ b/devices/gdevbjcl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbjcl.h b/devices/gdevbjcl.h
index a3bc9987..e249d790 100644
--- a/devices/gdevbjcl.h
+++ b/devices/gdevbjcl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbmp.c b/devices/gdevbmp.c
index 14033dca..52a13374 100644
--- a/devices/gdevbmp.c
+++ b/devices/gdevbmp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbmp.h b/devices/gdevbmp.h
index aec8f12c..4d58fc36 100644
--- a/devices/gdevbmp.h
+++ b/devices/gdevbmp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevbmpc.c b/devices/gdevbmpc.c
index 81b2abd6..efc2333b 100644
--- a/devices/gdevbmpc.c
+++ b/devices/gdevbmpc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevccr.c b/devices/gdevccr.c
index 5c9b7098..451cb82c 100644
--- a/devices/gdevccr.c
+++ b/devices/gdevccr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevcdj.c b/devices/gdevcdj.c
index ce74cc29..49b30df6 100644
--- a/devices/gdevcdj.c
+++ b/devices/gdevcdj.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevcfax.c b/devices/gdevcfax.c
index a6d0db44..cd3dc15c 100644
--- a/devices/gdevcfax.c
+++ b/devices/gdevcfax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevchameleon.c b/devices/gdevchameleon.c
index 74421244..20abe218 100644
--- a/devices/gdevchameleon.c
+++ b/devices/gdevchameleon.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevcif.c b/devices/gdevcif.c
index d2e09b79..66a44013 100644
--- a/devices/gdevcif.c
+++ b/devices/gdevcif.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevclj.c b/devices/gdevclj.c
index 4c5ffb7b..5edac41e 100644
--- a/devices/gdevclj.c
+++ b/devices/gdevclj.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevcljc.c b/devices/gdevcljc.c
index 15405cbd..bf8a4b82 100644
--- a/devices/gdevcljc.c
+++ b/devices/gdevcljc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevcmykog.c b/devices/gdevcmykog.c
index 4330258e..dcd1a4a4 100644
--- a/devices/gdevcmykog.c
+++ b/devices/gdevcmykog.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -171,9 +171,9 @@ cmykog_open(gx_device * pdev)
dev->icc_struct->supports_devn = true;
/* This device is a DeviceN color based device but unlike psdcmyk and
- tiffsep it can't change its color characteristics. It remains as
- a 6 color cmykog device. Postsript files can change the maxseparations
- (example Bug 696600 29-07E.PS) The gdevdevn code will, if it
+ tiffsep it can't change its color characteristics. It remains as
+ a 6 color cmykog device. Postsript files can change the maxseparations
+ (example Bug 696600 29-07E.PS) The gdevdevn code will, if it
detects a change occured, close the device and reopen (see
devn_printer_put_params) possibly resetting the color info. tiffsep
and psdcmyk, when reopened, will reset their color characteristics based upon
diff --git a/devices/gdevcslw.c b/devices/gdevcslw.c
index 4ded7ccd..8744f668 100644
--- a/devices/gdevcslw.c
+++ b/devices/gdevcslw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdfax.c b/devices/gdevdfax.c
index 3d2a579f..d113fd07 100644
--- a/devices/gdevdfax.c
+++ b/devices/gdevdfax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdjet.c b/devices/gdevdjet.c
index ea81dead..402e8aaa 100644
--- a/devices/gdevdjet.c
+++ b/devices/gdevdjet.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdjtc.c b/devices/gdevdjtc.c
index a0ffe625..34bb030d 100644
--- a/devices/gdevdjtc.c
+++ b/devices/gdevdjtc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdljm.c b/devices/gdevdljm.c
index fa859164..321160a0 100644
--- a/devices/gdevdljm.c
+++ b/devices/gdevdljm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdljm.h b/devices/gdevdljm.h
index 679bd561..18335805 100644
--- a/devices/gdevdljm.h
+++ b/devices/gdevdljm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdm24.c b/devices/gdevdm24.c
index 42706eee..08cad67f 100644
--- a/devices/gdevdm24.c
+++ b/devices/gdevdm24.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdsp.c b/devices/gdevdsp.c
index 0a66a027..10cfd85e 100644
--- a/devices/gdevdsp.c
+++ b/devices/gdevdsp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -1430,9 +1430,6 @@ static int display_check_structure(gx_device_display *ddev)
}
else if (ddev->callback->size == sizeof(struct display_callback_v2_s)) {
/* V2 structure with added display_separation callback */
- if (ddev->callback->size != sizeof(display_callback))
- return_error(gs_error_rangecheck);
-
if (ddev->callback->version_major != DISPLAY_VERSION_MAJOR_V2)
return_error(gs_error_rangecheck);
@@ -1649,7 +1646,7 @@ display_size_buf_device(gx_device_buf_space_t *space, gx_device *target,
int height, bool for_band)
{
gx_device_display *ddev = (gx_device_display *)target;
- gx_device_memory mdev;
+ gx_device_memory mdev = { 0 };
int code;
int planar = ddev->nFormat & (DISPLAY_PLANAR | DISPLAY_PLANAR_INTERLEAVED);
int interleaved = (ddev->nFormat & DISPLAY_PLANAR_INTERLEAVED);
@@ -1680,75 +1677,6 @@ static gx_device_buf_procs_t display_buf_procs = {
gx_default_destroy_buf_device
};
-static int /* returns 0 ok, else -ve error cde */
-setup_as_clist(gx_device_display *ddev, gs_memory_t *buffer_memory)
-{
- gdev_space_params space_params = ddev->space_params;
- gx_device *target = (gx_device *)ddev;
- uint space;
- int code;
- gx_device_clist *const pclist_dev = (gx_device_clist *)ddev;
- gx_device_clist_common * const pcldev = &pclist_dev->common;
- byte *base;
- bool save_is_open = ddev->is_open; /* Save around temporary failure in open_c loop */
-
- while (target->parent != NULL) {
- target = target->parent;
- gx_update_from_subclass(target);
- }
-
- /* Try to allocate based simply on param-requested buffer size */
- for ( space = space_params.BufferSpace; ; ) {
- base = gs_alloc_bytes(buffer_memory, space,
- "cmd list buffer");
- if (base != NULL)
- break;
- if ((space >>= 1) < MIN_BUFFER_SPACE)
- break;
- }
- if (base == NULL)
- return_error(gs_error_VMerror);
-
- /* Try opening the command list, to see if we allocated */
- /* enough buffer space. */
-open_c:
- ddev->buf = base;
- ddev->buffer_space = space;
- pclist_dev->common.orig_spec_op = ddev->orig_procs.dev_spec_op;
- clist_init_io_procs(pclist_dev, ddev->BLS_force_memory);
- clist_init_params(pclist_dev, base, space, target,
- display_buf_procs,
- space_params.band,
- false, /* do_not_open_or_close_bandfiles */
- (ddev->bandlist_memory == NULL ?
- ddev->memory->non_gc_memory:
- ddev->bandlist_memory),
- ddev->clist_disable_mask,
- ddev->page_uses_transparency);
- code = (*gs_clist_device_procs.open_device)( (gx_device *)pcldev );
- if (code < 0) {
- /* If there wasn't enough room, and we haven't */
- /* already shrunk the buffer, try enlarging it. */
- if (code == gs_error_rangecheck &&
- space >= space_params.BufferSpace) {
- space += space / 8;
- gs_free_object(buffer_memory, base,
- "cmd list buf(retry open)");
- base = gs_alloc_bytes(buffer_memory, space,
- "cmd list buf(retry open)");
- ddev->buf = base;
- if (base != NULL) {
- ddev->is_open = save_is_open; /* allow for success when we loop */
- goto open_c;
- }
- }
- /* Failure. */
- gs_free_object(buffer_memory, base, "cmd list buf");
- ddev->buffer_space = 0;
- }
- return code;
-}
-
/* Allocate the backing bitmap. */
static int
display_alloc_bitmap(gx_device_display * ddev, gx_device * param_dev)
@@ -1814,7 +1742,14 @@ display_alloc_bitmap(gx_device_display * ddev, gx_device * param_dev)
return_error(gs_error_VMerror);
}
/* Let's set up as a clist. */
- ccode = setup_as_clist(ddev, ddev->memory->non_gc_memory);
+ ccode = clist_mutate_to_clist((gx_device_clist_mutatable *)ddev,
+ ddev->memory->non_gc_memory,
+ NULL,
+ &ddev->space_params,
+ 0,
+ &display_buf_procs,
+ ddev->orig_procs.dev_spec_op,
+ MIN_BUFFER_SPACE);
if (ccode >= 0)
ddev->procs = gs_clist_device_procs;
} else {
@@ -2285,7 +2220,7 @@ display_set_color_format(gx_device_display *ddev, int nFormat)
if ((nFormat & DISPLAY_DEPTH_MASK) == DISPLAY_DEPTH_8) {
ddev->devn_params.bitspercomponent = bpc;
if (ddev->icc_struct == NULL) {
- ddev->icc_struct = gsicc_new_device_profile_array(ddev->memory);
+ ddev->icc_struct = gsicc_new_device_profile_array((gx_device *)ddev);
if (ddev->icc_struct == NULL)
return_error(gs_error_VMerror);
}
diff --git a/devices/gdevdsp.h b/devices/gdevdsp.h
index a062374b..37a839f2 100644
--- a/devices/gdevdsp.h
+++ b/devices/gdevdsp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevdsp2.h b/devices/gdevdsp2.h
index 3a098873..a592a9ce 100644
--- a/devices/gdevdsp2.h
+++ b/devices/gdevdsp2.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevepsc.c b/devices/gdevepsc.c
index 830d7668..5818eac8 100644
--- a/devices/gdevepsc.c
+++ b/devices/gdevepsc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -182,7 +182,7 @@ epsc_print_page(gx_device_printer * pdev, gp_file * prn_stream)
char start_graphics;
int first_pass;
int last_pass;
- int dots_per_space;
+ int dots_per_space;
int bytes_per_space;
int skip = 0, lnum = 0, code = 0, pass;
@@ -201,7 +201,7 @@ epsc_print_page(gx_device_printer * pdev, gp_file * prn_stream)
if (x_dpi > max_dpi) {
return_error(gs_error_rangecheck);
}
-
+
start_graphics = (char)
((y_24pin ? graphics_modes_24 : graphics_modes_9)[x_dpi / 60]);
first_pass = (start_graphics & DD ? 1 : 0);
diff --git a/devices/gdevepsn.c b/devices/gdevepsn.c
index 7b77b998..bea4b2c0 100644
--- a/devices/gdevepsn.c
+++ b/devices/gdevepsn.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -171,7 +171,7 @@ eps_print_page(gx_device_printer *pdev, gp_file *prn_stream, int y_9pin_high,
int tab_min_pixels = x_dpi * MIN_TAB_10THS / 10;
int skip = 0, lnum = 0, pass, ypass;
int code = 0;
-
+
char start_graphics;
int first_pass;
int last_pass;
@@ -195,12 +195,12 @@ eps_print_page(gx_device_printer *pdev, gp_file *prn_stream, int y_9pin_high,
/* This avoids divide by zero later on, bug 701843. */
return_error(gs_error_rangecheck);
}
-
+
buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf1)");
buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf2)");
in = buf1;
out = buf2;
-
+
/* Check allocations */
if ( buf1 == 0 || buf2 == 0 ) {
diff --git a/devices/gdevescp.c b/devices/gdevescp.c
index 14e420b5..f111785a 100644
--- a/devices/gdevescp.c
+++ b/devices/gdevescp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevfax.c b/devices/gdevfax.c
index 27b3c888..f85d8392 100644
--- a/devices/gdevfax.c
+++ b/devices/gdevfax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -69,7 +69,7 @@ gdev_fax_get_params(gx_device * dev, gs_param_list * plist)
ecode = code;
if ((code = param_write_bool(plist, "BlackIs1", &fdev->BlackIs1)) < 0)
ecode = code;
-
+
return ecode;
}
int
diff --git a/devices/gdevfax.h b/devices/gdevfax.h
index b0419d31..73a668e6 100644
--- a/devices/gdevfax.h
+++ b/devices/gdevfax.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevfpng.c b/devices/gdevfpng.c
index 74cfac70..324cbd28 100644
--- a/devices/gdevfpng.c
+++ b/devices/gdevfpng.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevhl7x.c b/devices/gdevhl7x.c
index 66d1db29..c2f1eaa1 100644
--- a/devices/gdevhl7x.c
+++ b/devices/gdevhl7x.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevicov.c b/devices/gdevicov.c
index 355be240..91e98d6e 100644
--- a/devices/gdevicov.c
+++ b/devices/gdevicov.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -77,7 +77,7 @@ cov_write_page(gx_device_printer *pdev, gp_file *file)
k = (double)k_pix / total_pix;
}
-
+
if (IS_LIBCTX_STDOUT(pdev->memory, gp_get_file(file))) {
outprintf(pdev->memory, "%8.5f %8.5f %8.5f %8.5f CMYK %s\n",
c, m, y, k, code ? "ERROR" : "OK");
@@ -122,13 +122,13 @@ static int cov_write_page_ink(gx_device_printer *pdev, gp_file *file)
end = row + raster;
for (; row < end; row += 4) {
-
+
dc_pix += row[0];
dm_pix += row[1];
dy_pix += row[2];
-
+
dk_pix += row[3];
++total_pix;
diff --git a/devices/gdevijs.c b/devices/gdevijs.c
index 42e1e916..884ea54a 100644
--- a/devices/gdevijs.c
+++ b/devices/gdevijs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevimgn.c b/devices/gdevimgn.c
index c6e291a4..1abde294 100644
--- a/devices/gdevimgn.c
+++ b/devices/gdevimgn.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevjbig2.c b/devices/gdevjbig2.c
deleted file mode 100644
index d6b4ef96..00000000
--- a/devices/gdevjbig2.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
- All Rights Reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied,
- modified or distributed except as expressly authorized under the terms
- of the license contained in the file LICENSE in this distribution.
-
- Refer to licensing information at http://www.artifex.com or contact
- Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
- CA 94945, U.S.A., +1(415)492-9861, for further information.
-*/
-
-
-/* $Id: gdevjbig2.c 6300 2005-12-28 19:56:24Z giles $ */
-/* JBIG2 encode filter test device */
-
-#include "gdevprn.h"
-#include "stream.h"
-#include "strimpl.h"
-#include "sjbig2_luratech.h"
-
-/* Structure for the JBIG2-writing device. */
-typedef struct gx_device_jbig2_s {
- gx_device_common;
- gx_prn_device_common;
-} gx_device_jbig2;
-
-/* ------ The device descriptors ------ */
-
-/* Default X and Y resolution. */
-#ifndef X_DPI
-# define X_DPI 72
-#endif
-#ifndef Y_DPI
-# define Y_DPI 72
-#endif
-
-static dev_proc_print_page(jbig2_print_page);
-
-/* Monochrome only */
-
-const gx_device_printer gs_gdevjbig2_device =
-prn_device(prn_bg_procs, "jbig2", /* The print_page proc is compatible with allowing bg printing */
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
- X_DPI, Y_DPI, /* resolution */
- 0, 0, 0, 0, /* margins */
- 1, jbig2_print_page);
-
-/* Send the page to the file. */
-static int
-jbig2_print_page(gx_device_printer * pdev, gp_file * prn_stream)
-{
- gx_device_jbig2 *jdev = (gx_device_jbig2 *) pdev;
- gs_memory_t *mem = jdev->memory;
- int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
- byte *in = gs_alloc_bytes(mem, line_size, "jbig2_print_page(in)");
- byte *fbuf = 0;
- uint fbuf_size;
- byte *jbuf = 0;
- uint jbuf_size;
- int lnum;
- int code = 0;
- stream_jbig2encode_state state;
- stream fstrm, cstrm;
-
- if (in == 0) {
- code = gs_note_error(gs_error_VMerror);
- goto fail;
- }
- /* Create the jbig2encode state. */
- s_init_state((stream_state *)&state, &s_jbig2encode_template, 0);
- if (state.templat->set_defaults)
- (*state.templat->set_defaults) ((stream_state *) & state);
- state.width = jdev->width;
- state.height = jdev->height;
- /* Set up the streams. */
- fbuf_size = max(512 /* arbitrary */ , state.templat->min_out_size);
- jbuf_size = state.templat->min_in_size;
- if ((fbuf = gs_alloc_bytes(mem, fbuf_size, "jbig2_print_page(fbuf)")) == 0 ||
- (jbuf = gs_alloc_bytes(mem, jbuf_size, "jbig2_print_page(jbuf)")) == 0
- ) {
- code = gs_note_error(gs_error_VMerror);
- goto done;
- }
- s_init(&fstrm, mem);
- swrite_file(&fstrm, prn_stream, fbuf, fbuf_size);
- s_init(&cstrm, mem);
- s_std_init(&cstrm, jbuf, jbuf_size, &s_filter_write_procs,
- s_mode_write);
- cstrm.state = (stream_state *) & state;
- cstrm.procs.process = state.templat->process;
- cstrm.strm = &fstrm;
- if (state.templat->init)
- (*state.templat->init) (cstrm.state);
-
- state.jb2_encode = true;
-
- /* Copy the data to the output. */
- for (lnum = 0; lnum < jdev->height; ++lnum) {
- byte *data;
- uint ignore_used;
- int i;
-
- if (cstrm.end_status) {
- code = gs_note_error(gs_error_ioerror);
- goto done;
- }
- code = gdev_prn_get_bits(pdev, lnum, in, &data);
- if (code < 0)
- goto done;
- sputs(&cstrm, data, state.stride, &ignore_used);
- }
-
- /* Wrap up. */
- sclose(&cstrm);
- sflush(&fstrm);
- done:
- gs_free_object(mem, jbuf, "jbig2_print_page(jbuf)");
- gs_free_object(mem, fbuf, "jbig2_print_page(fbuf)");
- gs_free_object(mem, in, "jbig2_print_page(in)");
- return code;
- fail:
- gs_free_object(mem, in, "jbig2_print_page(in)");
- return code;
-}
diff --git a/devices/gdevjpeg.c b/devices/gdevjpeg.c
index 7162acdb..eee3abd0 100644
--- a/devices/gdevjpeg.c
+++ b/devices/gdevjpeg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevjpx.c b/devices/gdevjpx.c
deleted file mode 100644
index b3c3690b..00000000
--- a/devices/gdevjpx.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
- All Rights Reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied,
- modified or distributed except as expressly authorized under the terms
- of the license contained in the file LICENSE in this distribution.
-
- Refer to licensing information at http://www.artifex.com or contact
- Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
- CA 94945, U.S.A., +1(415)492-9861, for further information.
-*/
-
-
-/* $Id: gdevjpx.c 6300 2005-12-28 19:56:24Z giles $ */
-/* JPX encode filter test device */
-
-#include "gdevprn.h"
-#include "stream.h"
-#include "strimpl.h"
-#include "sjpx_luratech.h"
-
-/* Structure for the JPX-writing device. */
-typedef struct gx_device_jpx_s {
- gx_device_common;
- gx_prn_device_common;
-} gx_device_jpx;
-
-/* The device descriptor */
-static dev_proc_print_page(jpx_print_page);
-
-/* ------ The device descriptors ------ */
-
-/* Default X and Y resolution. */
-#ifndef X_DPI
-# define X_DPI 72
-#endif
-#ifndef Y_DPI
-# define Y_DPI 72
-#endif
-
-static dev_proc_print_page(jpx_print_page);
-
-/* 24 bit RGB default */
-/* Since the print_page doesn't alter the device, this device can print in the background */
-static const gx_device_procs jpxrgb_procs =
-prn_color_procs(gdev_prn_open, gdev_prn_bg_output_page, gdev_prn_close,
- gx_default_rgb_map_rgb_color,
- gx_default_rgb_map_color_rgb);
-const gx_device_printer gs_jpxrgb_device = {
- prn_device_std_body(gx_device_jpx, jpxrgb_procs, "jpx",
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
- X_DPI, Y_DPI, /* resolution */
- 0, 0, 0, 0, /* margins */
- 24, /* bits per pixel */
- jpx_print_page)
-};
-
-/* 8 bit Grayscale */
-/* Since the print_page doesn't alter the device, this device can print in the background */
-static const gx_device_procs jpxgray_procs =
-prn_color_procs(gdev_prn_open, gdev_prn_bg_output_page, gdev_prn_close,
- gx_default_gray_map_rgb_color,
- gx_default_gray_map_color_rgb);
-const gx_device_printer gs_jpxgray_device = {
- prn_device_body(gx_device_jpx, jpxgray_procs, "jpxgray",
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
- X_DPI, Y_DPI, /* resolution */
- 0, 0, 0, 0, /* margins */
- 1, 8, 255, 0, 256, 0, /* components, depth and min/max values */
- jpx_print_page)
-};
-
-/* 32 bit CMKY */
-static dev_proc_map_color_rgb(jpx_cmyk_map_color_rgb);
-static dev_proc_map_cmyk_color(jpx_cmyk_map_cmyk_color);
-static const gx_device_procs jpxcmyk_procs =
-{ gdev_prn_open,
- gx_default_get_initial_matrix,
-/* Since the print_page doesn't alter the device, this device can print in the background */
- NULL, /* sync_output */
- gdev_prn_bg_output_page,
- gdev_prn_close,
- NULL,
- jpx_cmyk_map_color_rgb,
- NULL, /* fill_rectangle */
- NULL, /* tile_rectangle */
- NULL, /* copy_mono */
- NULL, /* copy_color */
- NULL, /* draw_line */
- NULL, /* get_bits */
- gdev_prn_get_params,
- gdev_prn_put_params,
- jpx_cmyk_map_cmyk_color,
- NULL, /* get_xfont_procs */
- NULL, /* get_xfont_device */
- NULL, /* map_rgb_alpha_color */
- gx_page_device_get_page_device /* get_page_device */
-};
-const gx_device_printer gs_jpxcmyk_device = {
- prn_device_std_body(gx_device_jpx, jpxcmyk_procs, "jpxcmyk",
- DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
- X_DPI, Y_DPI, /* resolution */
- 0, 0, 0, 0, /* margins */
- 32, /* bits per pixel */
- jpx_print_page)
-};
-
-/* private color conversion routines;
- we don't seem to have defaults for cmyk. */
-static int
-jpx_cmyk_map_color_rgb(gx_device * dev, gx_color_index color,
- gx_color_value prgb[3])
-{
- int not_k = color & 0xff,
- r = not_k - ~(color >> 24),
- g = not_k - ~((color >> 16) & 0xff),
- b = not_k - ~((color >> 8) & 0xff);
-
- prgb[0] = (r < 0 ? 0 : gx_color_value_from_byte(r));
- prgb[1] = (g < 0 ? 0 : gx_color_value_from_byte(g));
- prgb[2] = (b < 0 ? 0 : gx_color_value_from_byte(b));
- return 0;
-}
-
-static gx_color_index
-jpx_cmyk_map_cmyk_color(gx_device * dev, const gx_color_value cv[])
-{
- gx_color_index color = ~(
- gx_color_value_to_byte(cv[3]) +
- ((uint)gx_color_value_to_byte(cv[2]) << 8) +
- ((uint)gx_color_value_to_byte(cv[1]) << 16) +
- ((uint)gx_color_value_to_byte(cv[0]) << 24));
-
- return (color == gx_no_color_index ? color ^ 1 : color);
-}
-
-/* Send the page to the file. */
-static int
-jpx_print_page(gx_device_printer * pdev, gp_file * prn_stream)
-{
- gx_device_jpx *jdev = (gx_device_jpx *) pdev;
- gs_memory_t *mem = jdev->memory;
- int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
- byte *in = gs_alloc_bytes(mem, line_size, "jpx_print_page(in)");
- byte *fbuf = 0;
- uint fbuf_size;
- byte *jbuf = 0;
- uint jbuf_size;
- int lnum;
- int code = 0;
- stream_jpxe_state state;
- stream fstrm, cstrm;
-
- if (in == 0) {
- code = gs_note_error(gs_error_VMerror);
- goto fail;
- }
- /* Create the jpx encoder state. */
- s_init_state((stream_state *)&state, &s_jpxe_template, 0);
- if (state.templat->set_defaults)
- (*state.templat->set_defaults) ((stream_state *) & state);
- state.width = jdev->width;
- state.height = jdev->height;
- switch (jdev->color_info.depth) {
- case 32: state.colorspace = gs_jpx_cs_cmyk; break;
- case 24: state.colorspace = gs_jpx_cs_rgb; break;
- case 8: state.colorspace = gs_jpx_cs_gray; break;
- default:
- state.colorspace = gs_jpx_cs_gray; /* safest option */
- dmlprintf1(mem, "unexpected color_info depth %d\n",
- jdev->color_info.depth);
- }
- state.bpc = 8; /* currently only 8 bits per component is supported */
-
- /* ask for lossless encoding */
- /* state.lossless = 1; */
- /* or, set the quality level different from the default */
- /* state.quality = 35; */
-
- /* Set up the streams. */
- fbuf_size = max(512 /* arbitrary */ , state.templat->min_out_size);
- jbuf_size = state.templat->min_in_size;
- if ((fbuf = gs_alloc_bytes(mem, fbuf_size, "jpx_print_page(fbuf)")) == 0 ||
- (jbuf = gs_alloc_bytes(mem, jbuf_size, "jpx_print_page(jbuf)")) == 0
- ) {
- code = gs_note_error(gs_error_VMerror);
- goto done;
- }
- s_init(&fstrm, mem);
- swrite_file(&fstrm, prn_stream, fbuf, fbuf_size);
- s_init(&cstrm, mem);
- s_std_init(&cstrm, jbuf, jbuf_size, &s_filter_write_procs,
- s_mode_write);
- cstrm.state = (stream_state *) & state;
- cstrm.procs.process = state.templat->process;
- cstrm.strm = &fstrm;
- if (state.templat->init)
- (*state.templat->init) (cstrm.state);
-
- /* Copy the data to the output. */
- for (lnum = 0; lnum < jdev->height; ++lnum) {
- byte *data;
- uint ignore_used;
-
- if (cstrm.end_status) {
- code = gs_note_error(gs_error_ioerror);
- goto done;
- }
- code = gdev_prn_get_bits(pdev, lnum, in, &data);
- if (code < 0)
- goto done;
- sputs(&cstrm, data, state.stride, &ignore_used);
- }
-
- /* Wrap up. */
- sclose(&cstrm);
- sflush(&fstrm);
- done:
- gs_free_object(mem, jbuf, "jpx_print_page(jbuf)");
- gs_free_object(mem, fbuf, "jpx_print_page(fbuf)");
- gs_free_object(mem, in, "jpx_print_page(in)");
- return code;
- fail:
- gs_free_object(mem, in, "jpx_print_page(in)");
- return code;
-}
diff --git a/devices/gdevl31s.c b/devices/gdevl31s.c
index a3225ea9..9a32d434 100644
--- a/devices/gdevl31s.c
+++ b/devices/gdevl31s.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevlbp8.c b/devices/gdevlbp8.c
index ca96b69c..a53b2461 100644
--- a/devices/gdevlbp8.c
+++ b/devices/gdevlbp8.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevlj56.c b/devices/gdevlj56.c
index a3314e03..ed022c0c 100644
--- a/devices/gdevlj56.c
+++ b/devices/gdevlj56.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevlp8k.c b/devices/gdevlp8k.c
index 60d3c6e3..8083db8a 100644
--- a/devices/gdevlp8k.c
+++ b/devices/gdevlp8k.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevlxm.c b/devices/gdevlxm.c
index 6e557ede..4f9bfca1 100644
--- a/devices/gdevlxm.c
+++ b/devices/gdevlxm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -298,7 +298,7 @@ lxm5700m_print_page(gx_device_printer *pdev, gp_file *prn_stream)
sxMask = 0x80>>(sx%8);
/* loop through all the swipeHeight bits of this column.
-
+
Note that <sx> looks like it can get out of range, so we
check for this here. This fixes bug 701842.
diff --git a/devices/gdevmeds.c b/devices/gdevmeds.c
index 9435fed3..08ca0aa4 100644
--- a/devices/gdevmeds.c
+++ b/devices/gdevmeds.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevmeds.h b/devices/gdevmeds.h
index 2c247299..85344222 100644
--- a/devices/gdevmeds.h
+++ b/devices/gdevmeds.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevmgr.c b/devices/gdevmgr.c
index d0b81b11..a2d9b4d1 100644
--- a/devices/gdevmgr.c
+++ b/devices/gdevmgr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevmgr.h b/devices/gdevmgr.h
index 483237ec..dbea5895 100644
--- a/devices/gdevmgr.h
+++ b/devices/gdevmgr.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevmiff.c b/devices/gdevmiff.c
index c1d56496..7919f7a5 100644
--- a/devices/gdevmiff.c
+++ b/devices/gdevmiff.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevn533.c b/devices/gdevn533.c
index c697d441..aa4ebef3 100644
--- a/devices/gdevn533.c
+++ b/devices/gdevn533.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevo182.c b/devices/gdevo182.c
index ec26205c..ce57db05 100644
--- a/devices/gdevo182.c
+++ b/devices/gdevo182.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevocr.c b/devices/gdevocr.c
index ddfaa809..cd1efeb1 100644
--- a/devices/gdevocr.c
+++ b/devices/gdevocr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -34,7 +34,8 @@ static dev_proc_print_page(ocr_print_page);
static dev_proc_print_page(hocr_print_page);
static dev_proc_get_params(ocr_get_params);
static dev_proc_put_params(ocr_put_params);
-static dev_proc_open_device(hocr_open);
+static dev_proc_open_device(ocr_open);
+static dev_proc_close_device(ocr_close);
static dev_proc_close_device(hocr_close);
typedef struct gx_device_ocr_s gx_device_ocr;
@@ -43,13 +44,15 @@ struct gx_device_ocr_s {
gx_prn_device_common;
gx_downscaler_params downscale;
char language[1024];
+ int engine;
int page_count;
+ void *api;
};
/* 8-bit gray bitmap -> UTF8 OCRd text */
static const gx_device_procs ocr_procs =
-prn_color_params_procs(gdev_prn_open, gdev_prn_bg_output_page, gdev_prn_close,
+prn_color_params_procs(ocr_open, gdev_prn_bg_output_page, ocr_close,
gx_default_gray_map_rgb_color,
gx_default_gray_map_color_rgb,
ocr_get_params, ocr_put_params);
@@ -66,7 +69,7 @@ const gx_device_ocr gs_ocr_device =
/* 8-bit gray bitmap -> HTML OCRd text */
static const gx_device_procs hocr_procs =
-prn_color_params_procs(hocr_open, gdev_prn_bg_output_page, hocr_close,
+prn_color_params_procs(ocr_open, gdev_prn_bg_output_page, hocr_close,
gx_default_gray_map_rgb_color,
gx_default_gray_map_color_rgb,
ocr_get_params, ocr_put_params);
@@ -86,16 +89,33 @@ const gx_device_ocr gs_hocr_device =
#define HOCR_TRAILER " </body>\n</html>\n"
static int
-hocr_open(gx_device *pdev)
+ocr_open(gx_device *pdev)
{
gx_device_ocr *dev = (gx_device_ocr *)pdev;
+ int code;
dev->page_count = 0;
+ code = ocr_init_api(dev->memory->non_gc_memory,
+ dev->language, dev->engine, &dev->api);
+ if (code < 0)
+ return code;
+
return gdev_prn_open(pdev);
}
static int
+ocr_close(gx_device *pdev)
+{
+ gx_device_ocr *dev = (gx_device_ocr *)pdev;
+ gx_device_printer * const ppdev = (gx_device_printer *)pdev;
+
+ ocr_fin_api(dev->memory->non_gc_memory, dev->api);
+
+ return gdev_prn_close(pdev);
+}
+
+static int
hocr_close(gx_device *pdev)
{
gx_device_ocr *dev = (gx_device_ocr *)pdev;
@@ -105,7 +125,7 @@ hocr_close(gx_device *pdev)
gp_fwrite(HOCR_TRAILER, 1, sizeof(HOCR_TRAILER)-1, dev->file);
}
- return gdev_prn_close(pdev);
+ return ocr_close(pdev);
}
static int
@@ -127,6 +147,9 @@ ocr_get_params(gx_device * dev, gs_param_list * plist)
if ((code = param_write_string(plist, "OCRLanguage", &langstr)) < 0)
ecode = code;
+ if ((code = param_write_int(plist, "OCREngine", &pdev->engine)) < 0)
+ ecode = code;
+
if ((code = gx_downscaler_write_params(plist, &pdev->downscale,
GX_DOWNSCALER_PARAMS_MFS)) < 0)
ecode = code;
@@ -146,6 +169,7 @@ ocr_put_params(gx_device *dev, gs_param_list *plist)
gs_param_string langstr;
const char *param_name;
size_t len;
+ int engine;
switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
case 0:
@@ -162,6 +186,17 @@ ocr_put_params(gx_device *dev, gs_param_list *plist)
param_signal_error(plist, param_name, ecode);
}
+ switch (code = param_read_int(plist, (param_name = "OCREngine"), &engine)) {
+ case 0:
+ pdev->engine = engine;
+ break;
+ case 1:
+ break;
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
+
code = gx_downscaler_read_params(plist, &pdev->downscale,
GX_DOWNSCALER_PARAMS_MFS);
if (code < 0)
@@ -219,20 +254,20 @@ do_ocr_print_page(gx_device_ocr * pdev, gp_file * file, int hocr)
goto done;
if (hocr)
- code = ocr_image_to_hocr(pdev->memory,
+ code = ocr_image_to_hocr(pdev->api,
width, height,
8, raster,
(int)pdev->HWResolution[0],
(int)pdev->HWResolution[1],
data, 0, pdev->page_count,
- "eng", &out);
+ &out);
else
- code = ocr_image_to_utf8(pdev->memory,
+ code = ocr_image_to_utf8(pdev->api,
width, height,
8, raster,
(int)pdev->HWResolution[0],
(int)pdev->HWResolution[1],
- data, 0, "eng", &out);
+ data, 0, &out);
if (code < 0)
goto done;
if (out)
@@ -241,7 +276,8 @@ do_ocr_print_page(gx_device_ocr * pdev, gp_file * file, int hocr)
gp_fwrite(HOCR_HEADER, 1, sizeof(HOCR_HEADER)-1, file);
}
gp_fwrite(out, 1, strlen(out), file);
- gs_free_object(pdev->memory, out, "ocr_image_to_utf8");
+ gs_free_object(pdev->memory->non_gc_memory,
+ out, "ocr_image_to_utf8");
}
done:
diff --git a/devices/gdevokii.c b/devices/gdevokii.c
index 62fe616c..f9eaf6a8 100644
--- a/devices/gdevokii.c
+++ b/devices/gdevokii.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpbm.c b/devices/gdevpbm.c
index fd9b2619..9bba6889 100644
--- a/devices/gdevpbm.c
+++ b/devices/gdevpbm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpcl.c b/devices/gdevpcl.c
index be196663..ce1e6f93 100644
--- a/devices/gdevpcl.c
+++ b/devices/gdevpcl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpcl.h b/devices/gdevpcl.h
index 3d167ae4..3b98fff1 100644
--- a/devices/gdevpcl.h
+++ b/devices/gdevpcl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpcx.c b/devices/gdevpcx.c
index 137955cb..1515d411 100644
--- a/devices/gdevpcx.c
+++ b/devices/gdevpcx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpdfimg.c b/devices/gdevpdfimg.c
index 313d714f..7d04755b 100644
--- a/devices/gdevpdfimg.c
+++ b/devices/gdevpdfimg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -32,11 +32,13 @@
#include "gdevpdfimg.h"
-#define COMPRESSION_NONE 1 /* dump mode */
-#define COMPRESSION_LZW 2 /* Lempel-Ziv & Welch */
-#define COMPRESSION_FLATE 3
-#define COMPRESSION_JPEG 4
-#define COMPRESSION_RLE 5
+enum {
+ COMPRESSION_NONE = 1, /* dump mode */
+ COMPRESSION_LZW = 2, /* Lempel-Ziv & Welch */
+ COMPRESSION_FLATE = 3,
+ COMPRESSION_JPEG = 4,
+ COMPRESSION_RLE = 5
+};
static struct compression_string {
unsigned char id;
@@ -256,6 +258,7 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev,
stream_puts(pdf_dev->strm, "%PDF-1.3\n");
stream_puts(pdf_dev->strm, "%\307\354\217\242\n");
+ pdfimage_write_args_comment(pdf_dev,pdf_dev->strm);
if (pdf_dev->ocr.file_init) {
code = pdf_dev->ocr.file_init(pdf_dev);
@@ -270,7 +273,6 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev,
}
}
- pdfimage_write_args_comment(pdf_dev, pdf_dev->strm);
pdf_dev->Pages = page;
} else {
pdfimage_page *current = pdf_dev->Pages;
@@ -278,7 +280,7 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev,
current = current->next;
current->next = page;
}
- page->ImageObjectNumber = (pdf_dev->NumPages * 4) + 3 + pdf_dev->ocr.file_objects;
+ page->ImageObjectNumber = (pdf_dev->NumPages * 4) + PDFIMG_STATIC_OBJS + pdf_dev->ocr.file_objects;
page->LengthObjectNumber = page->ImageObjectNumber + 1;
page->PageStreamObjectNumber = page->LengthObjectNumber + 1;
page->PageDictObjectNumber = page->PageStreamObjectNumber + 1;
@@ -596,7 +598,7 @@ pdf_image_downscale_and_print_page(gx_device_printer *dev,
stream_puts(pdf_dev->strm, Buffer);
pprintd1(pdf_dev->strm, "/Resources <<\n/XObject <<\n/Im1 %d 0 R\n>>\n", page->ImageObjectNumber);
if (pdf_dev->ocr.file_init)
- stream_puts(pdf_dev->strm, "/Font <<\n/Ft0 3 0 R\n>>\n");
+ pprintd1(pdf_dev->strm, "/Font <<\n/Ft0 %d 0 R\n>>\n", PDFIMG_STATIC_OBJS);
stream_puts(pdf_dev->strm, ">>\n>>\nendobj\n");
gx_downscaler_fin(&ds);
@@ -622,12 +624,10 @@ static void write_fileID(stream *s, const byte *str, int size)
stream_cursor_write w;
int status;
- r.ptr = str - 1;
- r.limit = r.ptr + size;
- w.limit = buf + sizeof(buf) - 1;
+ stream_cursor_read_init(&r, str, size);
+
do {
- /* One picky compiler complains if we initialize to buf - 1. */
- w.ptr = buf; w.ptr--;
+ stream_cursor_write_init(&w, buf, sizeof(buf));
status = (*templat->process) (st, &r, &w, true);
stream_write(s, buf, (uint) (w.ptr + 1 - buf));
}
@@ -722,7 +722,7 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm)
pdf_store_default_Producer(Producer);
pdf_dev->RootOffset = stell(pdf_dev->strm);
- stream_puts(pdf_dev->strm, "1 0 obj\n<<\n/Pages 2 0 R\n/Type /Catalog\n>>\nendobj\n");
+ stream_puts(pdf_dev->strm, "1 0 obj\n<<\n/Pages 2 0 R\n/Type /Catalog\n/Info 3 0 R\n>>\nendobj\n");
pdf_dev->PagesOffset = stell(pdf_dev->strm);
pprintd1(pdf_dev->strm, "2 0 obj\n<<\n/Count %d\n", pdf_dev->NumPages);
@@ -755,13 +755,21 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm)
tms.tm_hour, tms.tm_min, tms.tm_sec,
timesign, timeoffset / 60, timeoffset % 60);
+ pdf_dev->InfoOffset = stell(pdf_dev->strm);
+ stream_puts(pdf_dev->strm, "3 0 obj\n<<\n/Producer");
+ stream_puts(pdf_dev->strm, Producer);
+ stream_puts(pdf_dev->strm, "\n/CreationDate");
+ stream_puts(pdf_dev->strm, CreationDate);
+ stream_puts(pdf_dev->strm, "\n>>\nendobj\n");
+
pdf_dev->xrefOffset = stell(pdf_dev->strm);
if (PCLm)
pprintd1(pdf_dev->strm, "xref\n0 %d\n0000000000 65536 f \n", pdf_dev->NextObject);
else
- pprintd1(pdf_dev->strm, "xref\n0 %d\n0000000000 65536 f \n", (pdf_dev->NumPages * 4) + 3 + pdf_dev->ocr.file_objects);
+ pprintd1(pdf_dev->strm, "xref\n0 %d\n0000000000 65536 f \n", (pdf_dev->NumPages * 4) + PDFIMG_STATIC_OBJS + pdf_dev->ocr.file_objects);
write_xref_entry(pdf_dev->strm, pdf_dev->RootOffset);
write_xref_entry(pdf_dev->strm, pdf_dev->PagesOffset);
+ write_xref_entry(pdf_dev->strm, pdf_dev->InfoOffset);
if (pdf_dev->ocr.file_objects) {
int i;
@@ -779,7 +787,7 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm)
write_xref_entry(pdf_dev->strm, page->PageDictOffset);
page = page->next;
}
- pprintd1(pdf_dev->strm, "trailer\n<<\n/Size %d\n/Root 1 0 R\n/ID [", (pdf_dev->NumPages * 4) + 3 + pdf_dev->ocr.file_objects);
+ pprintd1(pdf_dev->strm, "trailer\n<<\n/Size %d\n/Root 1 0 R\n/ID [", (pdf_dev->NumPages * 4) + PDFIMG_STATIC_OBJS + pdf_dev->ocr.file_objects);
pdf_compute_fileID(pdf_dev, fileID, CreationDate, Title, Producer);
write_fileID(pdf_dev->strm, (const byte *)&fileID, 16);
write_fileID(pdf_dev->strm, (const byte *)&fileID, 16);
diff --git a/devices/gdevpdfimg.h b/devices/gdevpdfimg.h
index baf8175e..322c1622 100644
--- a/devices/gdevpdfimg.h
+++ b/devices/gdevpdfimg.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -19,6 +19,13 @@
#include "gdevprn.h"
#include "gxdownscale.h"
+/* This is the number of always defined objects; object 0 the head
+ * of the free list, Object 1 the Root dictionary, Object 2
+ * the Pages dictionary and object 3 the Info dictionary
+ */
+#define PDFIMG_STATIC_OBJS 4
+#define OCR_MAX_FILE_OBJECTS 8
+
typedef struct pdfimage_page_s {
int ImageObjectNumber;
gs_offset_t ImageOffset;
@@ -39,8 +46,6 @@ typedef struct PCLm_temp_file_s {
byte *strm_buf;
} PCLm_temp_file_t;
-#define OCR_MAX_FILE_OBJECTS 8
-
typedef struct gx_device_pdf_image_s {
gx_device_common;
gx_prn_device_common;
@@ -55,6 +60,7 @@ typedef struct gx_device_pdf_image_s {
int NumPages;
gs_offset_t RootOffset;
gs_offset_t PagesOffset;
+ gs_offset_t InfoOffset;
gs_offset_t xrefOffset;
pdfimage_page *Pages;
PCLm_temp_file_t xref_stream;
@@ -64,6 +70,7 @@ typedef struct gx_device_pdf_image_s {
/* OCR data */
struct {
char language[1024];
+ int engine;
void *state;
/* Number of "file level" objects - i.e. the number of objects
diff --git a/devices/gdevpdfocr.c b/devices/gdevpdfocr.c
index 95d358b1..afc73ff2 100644
--- a/devices/gdevpdfocr.c
+++ b/devices/gdevpdfocr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -31,24 +31,7 @@
#include "sjpeg.h"
#include "gdevpdfimg.h"
-
-#define COMPRESSION_NONE 1 /* dump mode */
-#define COMPRESSION_LZW 2 /* Lempel-Ziv & Welch */
-#define COMPRESSION_FLATE 3
-#define COMPRESSION_JPEG 4
-#define COMPRESSION_RLE 5
-
-static struct compression_string {
- unsigned char id;
- const char *str;
-} compression_strings [] = {
- { COMPRESSION_NONE, "None" },
- { COMPRESSION_LZW, "LZW" }, /* Not supported in PCLm */
- { COMPRESSION_FLATE, "Flate" },
- { COMPRESSION_JPEG, "JPEG" },
- { COMPRESSION_RLE, "RLE" },
- { 0, NULL }
-};
+#include "tessocr.h"
int pdf_ocr_open(gx_device *pdev);
int pdf_ocr_close(gx_device *pdev);
@@ -63,6 +46,7 @@ pdfocr_put_some_params(gx_device * dev, gs_param_list * plist)
gs_param_string langstr;
const char *param_name;
size_t len;
+ int engine;
switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
case 0:
@@ -79,6 +63,17 @@ pdfocr_put_some_params(gx_device * dev, gs_param_list * plist)
param_signal_error(plist, param_name, ecode);
}
+ switch (code = param_read_int(plist, (param_name = "OCREngine"), &engine)) {
+ case 0:
+ pdf_dev->ocr.engine = engine;
+ break;
+ case 1:
+ break;
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
+
return code;
}
@@ -120,6 +115,9 @@ pdfocr_get_some_params(gx_device * dev, gs_param_list * plist)
if ((code = param_write_string(plist, "OCRLanguage", &langstr)) < 0)
ecode = code;
+ if ((code = param_write_int(plist, "OCREngine", &pdf_dev->ocr.engine)) < 0)
+ ecode = code;
+
return ecode;
}
@@ -228,21 +226,27 @@ const gx_device_pdf_image gs_pdfocr32_device = {
0 /* JPEGQ */
};
+/* These strings have object numbers built into them which are only
+ * correct for a specific value of PDFIMG_STATIC_OBJS (currently 4)
+ * If we add more static objects (eg Metadata) then we need to update
+ * the values in the strings below.
+ */
+
/* Funky font */
static const char funky_font[] =
-"3 0 obj\n<</BaseFont/GlyphLessFont/DescendantFonts[4 0 R]"
-"/Encoding/Identity-H/Subtype/Type0/ToUnicode 6 0 R/Type /Font"
+"4 0 obj\n<</BaseFont/GlyphLessFont/DescendantFonts[5 0 R]"
+"/Encoding/Identity-H/Subtype/Type0/ToUnicode 7 0 R/Type /Font"
">>\nendobj\n";
static const char funky_font2[] =
-"4 0 obj\n<</BaseFont/GlyphLessFont"
-"/CIDToGIDMap 5 0 R\n/CIDSystemInfo<<\n"
+"5 0 obj\n<</BaseFont/GlyphLessFont"
+"/CIDToGIDMap 6 0 R\n/CIDSystemInfo<<\n"
"/Ordering (Identity)/Registry (Adobe)/Supplement 0>>"
-"/FontDescriptor 7 0 R/Subtype /CIDFontType2/Type/Font"
+"/FontDescriptor 8 0 R/Subtype /CIDFontType2/Type/Font"
"/DW 500>>\nendobj\n";
static const char funky_font3[] =
-"5 0 obj\n<</Length 210/Filter/FlateDecode"
+"6 0 obj\n<</Length 210/Filter/FlateDecode"
">>stream\n";
static const char funky_font3a[] = {
@@ -279,7 +283,7 @@ static const char funky_font3b[] =
"endstream\nendobj\n";
static const char funky_font4[] =
-"6 0 obj\n<</Length 353>>\nstream\n"
+"7 0 obj\n<</Length 353>>\nstream\n"
"/CIDInit /ProcSet findresource begin\n"
"12 dict begin\n"
"begincmap\n"
@@ -305,13 +309,13 @@ static const char funky_font4[] =
"endobj\n";
static const char funky_font5[] =
-"7 0 obj\n"
+"8 0 obj\n"
"<</Ascent 1000/CapHeight 1000/Descent -1/Flags 5"
-"/FontBBox[0 0 500 1000]/FontFile2 8 0 R/FontName/GlyphLessFont"
+"/FontBBox[0 0 500 1000]/FontFile2 9 0 R/FontName/GlyphLessFont"
"/ItalicAngle 0/StemV 80/Type/FontDescriptor>>\nendobj\n";
static const char funky_font6[] =
-"8 0 obj\n<</Length 572/Length1 572>>\nstream\n";
+"9 0 obj\n<</Length 572/Length1 572>>\nstream\n";
static const char funky_font6a[] =
{
@@ -416,7 +420,7 @@ ocr_file_init(gx_device_pdf_image *dev)
stream_write(dev->strm, funky_font6a, sizeof(funky_font6a));
stream_write(dev->strm, funky_font6b, sizeof(funky_font6b)-1);
- return ocr_init_api(dev->memory, language, &dev->ocr.state);
+ return ocr_init_api(dev->memory->non_gc_memory, language, dev->ocr.engine, &dev->ocr.state);
}
static void
diff --git a/devices/gdevpe.c b/devices/gdevpe.c
index d2590b92..b4d462f3 100644
--- a/devices/gdevpe.c
+++ b/devices/gdevpe.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevperm.c b/devices/gdevperm.c
index e03c8cae..80afdf48 100644
--- a/devices/gdevperm.c
+++ b/devices/gdevperm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevphex.c b/devices/gdevphex.c
index 3eccb787..7afc6ba3 100644
--- a/devices/gdevphex.c
+++ b/devices/gdevphex.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpjet.c b/devices/gdevpjet.c
index bd428295..8df438f5 100644
--- a/devices/gdevpjet.c
+++ b/devices/gdevpjet.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevplan.c b/devices/gdevplan.c
index 7e5e5f0a..bf9a81e5 100644
--- a/devices/gdevplan.c
+++ b/devices/gdevplan.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevplib.c b/devices/gdevplib.c
index 026b4f8f..f1bf6598 100644
--- a/devices/gdevplib.c
+++ b/devices/gdevplib.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevplib.h b/devices/gdevplib.h
index e4c87345..b724eb42 100644
--- a/devices/gdevplib.h
+++ b/devices/gdevplib.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpm.h b/devices/gdevpm.h
index d79b0f37..af7fec19 100644
--- a/devices/gdevpm.h
+++ b/devices/gdevpm.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpng.c b/devices/gdevpng.c
index a564e6c3..4833efb1 100644
--- a/devices/gdevpng.c
+++ b/devices/gdevpng.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpsd.c b/devices/gdevpsd.c
index 27a6f262..03495ae0 100644
--- a/devices/gdevpsd.c
+++ b/devices/gdevpsd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -752,56 +752,12 @@ psd_get_params_cmyk(gx_device * pdev, gs_param_list * plist)
return psd_get_params_generic(pdev, plist, 1);
}
-
-
-/* Compare a C string and a gs_param_string. */
-static bool
-param_string_eq(const gs_param_string *pcs, const char *str)
-{
- return (strlen(str) == pcs->size &&
- !strncmp(str, (const char *)pcs->data, pcs->size));
-}
-
-static int
-psd_set_color_model(psd_device *xdev, psd_color_model color_model)
-{
- xdev->color_model = color_model;
- if (color_model == psd_DEVICE_GRAY) {
- xdev->devn_params.std_colorant_names = DeviceGrayComponents;
- xdev->devn_params.num_std_colorant_names = 1;
- xdev->color_info.cm_name = "DeviceGray";
- xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
- } else if (color_model == psd_DEVICE_RGB) {
- xdev->devn_params.std_colorant_names = DeviceRGBComponents;
- xdev->devn_params.num_std_colorant_names = 3;
- xdev->color_info.cm_name = "DeviceRGB";
- xdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE;
- } else if (color_model == psd_DEVICE_CMYK) {
- xdev->devn_params.std_colorant_names = DeviceCMYKComponents;
- xdev->devn_params.num_std_colorant_names = 4;
- xdev->color_info.cm_name = "DeviceCMYK";
- xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
- } else if (color_model == psd_DEVICE_N) {
- xdev->devn_params.std_colorant_names = DeviceCMYKComponents;
- xdev->devn_params.num_std_colorant_names = 4;
- xdev->color_info.cm_name = "DeviceN";
- xdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
- } else {
- return -1;
- }
-
- return 0;
-}
-
/* Set parameters. We allow setting the number of bits per component. */
static int
psd_put_params_generic(gx_device * pdev, gs_param_list * plist, int cmyk)
{
psd_device * const pdevn = (psd_device *) pdev;
int code = 0;
- gs_param_string pcm;
- psd_color_model color_model = pdevn->color_model;
- gx_device_color_info save_info = pdevn->color_info;
code = gx_downscaler_read_params(plist, &pdevn->downscale,
cmyk ? GX_DOWNSCALER_PARAMS_TRAP : 0);
@@ -835,37 +791,10 @@ psd_put_params_generic(gx_device * pdev, gs_param_list * plist, int cmyk)
break;
}
- if (code >= 0)
- code = param_read_name(plist, "ProcessColorModel", &pcm);
-
- /* Bug 696318. Don't allow process color model change for RGB device */
- if (code == 0 && color_model != psd_DEVICE_RGB) {
- if (param_string_eq (&pcm, "DeviceGray"))
- color_model = psd_DEVICE_GRAY;
- else if (param_string_eq (&pcm, "DeviceRGB"))
- color_model = psd_DEVICE_RGB;
- else if (param_string_eq (&pcm, "DeviceCMYK"))
- color_model = psd_DEVICE_CMYK;
- else if (param_string_eq (&pcm, "DeviceN"))
- color_model = psd_DEVICE_N;
- else {
- param_signal_error(plist, "ProcessColorModel",
- code = gs_error_rangecheck);
- }
- }
-
- if (code >= 0)
- code = psd_set_color_model(pdevn, color_model);
-
/* handle the standard DeviceN related parameters */
- if (code == 0)
+ if (code >= 0)
code = gx_devn_prn_put_params(pdev, plist);
- if (code < 0) {
- pdev->color_info = save_info;
- return code;
- }
-
return code;
}
diff --git a/devices/gdevpsd.h b/devices/gdevpsd.h
index 98d2e9ae..a10e4ec7 100644
--- a/devices/gdevpsd.h
+++ b/devices/gdevpsd.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpsim.c b/devices/gdevpsim.c
index 4e4080fe..1640da74 100644
--- a/devices/gdevpsim.c
+++ b/devices/gdevpsim.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevpxut.c b/devices/gdevpxut.c
index 08d7741a..c09692b1 100644
--- a/devices/gdevpxut.c
+++ b/devices/gdevpxut.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -45,7 +45,7 @@ px_write_file_header(stream *s, const gx_device *dev, bool staple)
static const char *const resolution_2400 = "2400";
static const char *const file_header =
"\n@PJL ENTER LANGUAGE = PCLXL\n\
-) HP-PCL XL;1;1;Comment Copyright Artifex Sofware, Inc. 2005\000\n";
+) HP-PCL XL;1;1;Comment Copyright Artifex Sofware, Inc. 2005-2021\000\n";
static const byte stream_header[] = {
DA(pxaUnitsPerMeasure),
DUB(0), DA(pxaMeasure),
diff --git a/devices/gdevpxut.h b/devices/gdevpxut.h
index 28f55847..1db5d332 100644
--- a/devices/gdevpxut.h
+++ b/devices/gdevpxut.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevrinkj.c b/devices/gdevrinkj.c
index d10a7a1b..a49ee1c0 100644
--- a/devices/gdevrinkj.c
+++ b/devices/gdevrinkj.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevsj48.c b/devices/gdevsj48.c
index 8b1304b9..9a004446 100644
--- a/devices/gdevsj48.c
+++ b/devices/gdevsj48.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevsnfb.c b/devices/gdevsnfb.c
index 76d5cf47..6ffc7ba4 100644
--- a/devices/gdevsnfb.c
+++ b/devices/gdevsnfb.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevsppr.c b/devices/gdevsppr.c
index 8257aa39..29d34dd9 100644
--- a/devices/gdevsppr.c
+++ b/devices/gdevsppr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc.c b/devices/gdevstc.c
index 22314777..5d8bf425 100644
--- a/devices/gdevstc.c
+++ b/devices/gdevstc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc.h b/devices/gdevstc.h
index 7db27e9a..1b9910d0 100644
--- a/devices/gdevstc.h
+++ b/devices/gdevstc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc1.c b/devices/gdevstc1.c
index dd10268c..cabaac5a 100644
--- a/devices/gdevstc1.c
+++ b/devices/gdevstc1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc2.c b/devices/gdevstc2.c
index 90dca523..e8150565 100644
--- a/devices/gdevstc2.c
+++ b/devices/gdevstc2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc3.c b/devices/gdevstc3.c
index 56fea31d..a4ed4f10 100644
--- a/devices/gdevstc3.c
+++ b/devices/gdevstc3.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevstc4.c b/devices/gdevstc4.c
index 1c7c4589..b747b9e3 100644
--- a/devices/gdevstc4.c
+++ b/devices/gdevstc4.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtfax.c b/devices/gdevtfax.c
index b8aa7e74..d7abc954 100644
--- a/devices/gdevtfax.c
+++ b/devices/gdevtfax.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtfax.h b/devices/gdevtfax.h
index deaa6516..60fd90f8 100644
--- a/devices/gdevtfax.h
+++ b/devices/gdevtfax.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtfnx.c b/devices/gdevtfnx.c
index b3fea72e..e7c7f0fe 100644
--- a/devices/gdevtfnx.c
+++ b/devices/gdevtfnx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtifs.c b/devices/gdevtifs.c
index 4ecafa8b..d72549f5 100644
--- a/devices/gdevtifs.c
+++ b/devices/gdevtifs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtifs.h b/devices/gdevtifs.h
index adc9f4ae..bbd01bb6 100644
--- a/devices/gdevtifs.h
+++ b/devices/gdevtifs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtknk.c b/devices/gdevtknk.c
index 741b5925..7ea92326 100644
--- a/devices/gdevtknk.c
+++ b/devices/gdevtknk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtrac.c b/devices/gdevtrac.c
index 77b7dc93..7fff3862 100644
--- a/devices/gdevtrac.c
+++ b/devices/gdevtrac.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c
index 3dde3523..1a52aede 100644
--- a/devices/gdevtsep.c
+++ b/devices/gdevtsep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -2240,7 +2240,13 @@ tiffsep_print_page(gx_device_printer * pdev, gp_file * file)
for (sep_num = 0; sep_num < num_spot; sep_num++) {
copy_separation_name(tfdev, name,
gp_file_name_sizeof - base_filename_length - SUFFIX_SIZE, sep_num, 0);
- dmlprintf1(pdev->memory, "%%%%SeparationName: %s\n", name);
+ dmlprintf1(pdev->memory, "%%%%SeparationName: %s", name);
+ dmlprintf4(pdev->memory, " CMYK = [ %d %d %d %d ]\n",
+ tfdev->equiv_cmyk_colors.color[sep_num].c,
+ tfdev->equiv_cmyk_colors.color[sep_num].m,
+ tfdev->equiv_cmyk_colors.color[sep_num].y,
+ tfdev->equiv_cmyk_colors.color[sep_num].k
+ );
}
}
diff --git a/devices/gdevupd.c b/devices/gdevupd.c
index 702548d8..badc8041 100644
--- a/devices/gdevupd.c
+++ b/devices/gdevupd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevwpr2.c b/devices/gdevwpr2.c
index 3a4b97b6..c91e82a1 100644
--- a/devices/gdevwpr2.c
+++ b/devices/gdevwpr2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -704,7 +704,7 @@ win_pr2_set_bpp(gx_device * dev, int depth)
if (wdev->icc_struct) {
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
}
- wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
+ wdev->icc_struct = gsicc_new_device_profile_array((gx_device *)wdev);
if (wdev->icc_struct) {
code = gsicc_set_device_profile(dev, dev->memory,
@@ -729,7 +729,7 @@ win_pr2_set_bpp(gx_device * dev, int depth)
if (wdev->icc_struct) {
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
}
- wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
+ wdev->icc_struct = gsicc_new_device_profile_array((gx_device *)wdev);
if (wdev->icc_struct) {
code = gsicc_set_device_profile(dev, dev->memory,
@@ -754,7 +754,7 @@ win_pr2_set_bpp(gx_device * dev, int depth)
if (wdev->icc_struct) {
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
}
- wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
+ wdev->icc_struct = gsicc_new_device_profile_array((gx_device *)wdev);
if (wdev->icc_struct) {
code = gsicc_set_device_profile(dev, dev->memory,
@@ -776,7 +776,7 @@ win_pr2_set_bpp(gx_device * dev, int depth)
if (wdev->icc_struct) {
rc_decrement(wdev->icc_struct, "win_pr2_set_bpp");
}
- wdev->icc_struct = gsicc_new_device_profile_array(wdev->memory);
+ wdev->icc_struct = gsicc_new_device_profile_array((gx_device *)wdev);
if (wdev->icc_struct) {
code = gsicc_set_device_profile(dev, dev->memory,
diff --git a/devices/gdevx.c b/devices/gdevx.c
index cfde7543..438af172 100644
--- a/devices/gdevx.c
+++ b/devices/gdevx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -36,8 +36,6 @@
/****** THIS IS USELESS. XGetImage DOES NOT GENERATE EXPOSURE EVENTS. ******/
#define GET_IMAGE_EXPOSURES 0
-/* GC descriptors */
-private_st_device_X();
/* Forward references */
static int x_copy_image(gx_device_X * xdev, const byte * base, int sourcex,
@@ -240,6 +238,23 @@ const gx_device_X this_device = { \
} \
};
+static void
+x_finalize(const gs_memory_t *cmem, void *vpdev)
+{
+ /* Do an actual close of the window. */
+ gx_device_X *xdev = (gx_device_X *)vpdev;
+
+ if (xdev->dpy) {
+ XCloseDisplay(xdev->dpy);
+ xdev->dpy = NULL;
+ }
+ gx_device_finalize(cmem, vpdev);
+}
+
+gs_public_st_suffix_add1_final(st_device_X, gx_device_X,
+ "gx_device_X", device_x_enum_ptrs, device_x_reloc_ptrs,
+ x_finalize, st_device_bbox, buffer);
+
x_device(gs_x11_device,
std_device_color_stype_body(gx_device_X, 0, "x11", &st_device_X,
FAKE_RES * DEFAULT_WIDTH_10THS / 10,
diff --git a/devices/gdevx.h b/devices/gdevx.h
index 4becd639..b35d4d85 100644
--- a/devices/gdevx.h
+++ b/devices/gdevx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -199,10 +199,6 @@ typedef struct gx_device_X_s {
xdev->text.origin.y, xdev->text.items, xdev->text.item_count)
} gx_device_X;
-#define private_st_device_X() /* in gdevx.c */\
- gs_public_st_suffix_add1_final(st_device_X, gx_device_X,\
- "gx_device_X", device_x_enum_ptrs, device_x_reloc_ptrs,\
- gx_device_finalize, st_device_bbox, buffer)
/* Send an event to the Ghostview process */
void gdev_x_send_event(gx_device_X *xdev, Atom msg);
diff --git a/devices/gdevxalt.c b/devices/gdevxalt.c
index 4d8cc339..0290c8c6 100644
--- a/devices/gdevxalt.c
+++ b/devices/gdevxalt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevxcf.c b/devices/gdevxcf.c
index c4c44bf6..18ff322e 100644
--- a/devices/gdevxcf.c
+++ b/devices/gdevxcf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -1241,7 +1241,7 @@ xcf_icc_to_tile(gx_device_printer *pdev, xcf_write_ctx *xc, byte **tile_data, co
understand what is going on in the loop
with the 255^row[row_idx++] operation */
- gscms_transform_color((gx_device*) pdev, link,
+ gscms_transform_color((gx_device*) pdev, link,
(void *) (&(row[row_idx])),
&(base_ptr[base_idx]), 1);
diff --git a/devices/gdevxcmp.c b/devices/gdevxcmp.c
index 9f7e0401..c43426d7 100644
--- a/devices/gdevxcmp.c
+++ b/devices/gdevxcmp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevxcmp.h b/devices/gdevxcmp.h
index 9d6fca73..8fa1d8e7 100644
--- a/devices/gdevxcmp.h
+++ b/devices/gdevxcmp.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gdevxini.c b/devices/gdevxini.c
index ca8ca2f9..82032cd6 100644
--- a/devices/gdevxini.c
+++ b/devices/gdevxini.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -107,14 +107,16 @@ gdev_x_open(gx_device_X * xdev)
}
# endif
#endif
+
if (!(xdev->dpy = XOpenDisplay((char *)NULL))) {
char *dispname = getenv("DISPLAY");
emprintf1(xdev->memory,
- "Cannot open X display `%s'.\n",
- (dispname == NULL ? "(null)" : dispname));
+ "Cannot open X display `%s'.\n",
+ (dispname == NULL ? "(null)" : dispname));
return_error(gs_error_ioerror);
}
+
xdev->dest = 0;
if ((window_id = getenv("GHOSTVIEW"))) {
if (!(xdev->ghostview = sscanf(window_id, "%ld %ld",
@@ -892,7 +894,7 @@ gdev_x_put_params(gx_device * dev, gs_param_list * plist)
dev->width, dev->height, dev->dname);
return_error(gs_error_rangecheck);
}
-
+
/* points */
dev->MediaSize[0] = (float)dev->width / xdev->x_pixels_per_inch * 72;
dev->MediaSize[1] = (float)dev->height / xdev->y_pixels_per_inch * 72;
@@ -927,7 +929,7 @@ gdev_x_put_params(gx_device * dev, gs_param_list * plist)
}
xdev->MaxTempPixmap = values.MaxTempPixmap;
xdev->MaxTempImage = values.MaxTempImage;
-
+
if (clear_window || xdev->space_params.MaxBitmap != orig_MaxBitmap) {
if (xdev->is_open)
gdev_x_clear_window(xdev);
@@ -949,16 +951,28 @@ gdev_x_close(gx_device_X *xdev)
xdev->vinfo = NULL;
}
gdev_x_free_colors(xdev);
- if (xdev->cmap != DefaultColormapOfScreen(xdev->scr))
+ if (xdev->dpy && xdev->cmap != DefaultColormapOfScreen(xdev->scr)) {
XFreeColormap(xdev->dpy, xdev->cmap);
- if (xdev->gc)
+ xdev->cmap = DefaultColormapOfScreen(xdev->scr);
+ }
+ if (xdev->dpy && xdev->gc) {
XFreeGC(xdev->dpy, xdev->gc);
+ xdev->gc = NULL;
+ }
+ if (xdev->dpy && xdev->bpixmap != (Pixmap)0) {
+ XFreePixmap(xdev->dpy, xdev->bpixmap);
+ xdev->bpixmap = (Pixmap)0;
+ xdev->dest = (Pixmap)0;
+ }
+
+ /* Closure of device will not close the window
+ finalize will do that. */
+ xdev->pwin = xdev->win;
- XCloseDisplay(xdev->dpy);
/* MaxBitmap == 0 ensures x_set_buffer() configures as non-buffering */
xdev->space_params.MaxBitmap = 0;
x_set_buffer(xdev);
xdev->space_params.MaxBitmap = MaxBitmap;
return 0;
-}
+} \ No newline at end of file
diff --git a/devices/gdevxres.c b/devices/gdevxres.c
index 748d3c58..acdef22a 100644
--- a/devices/gdevxres.c
+++ b/devices/gdevxres.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/gxfcopy.c b/devices/gxfcopy.c
index c6d90c9a..4f2ca6fd 100644
--- a/devices/gxfcopy.c
+++ b/devices/gxfcopy.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -389,24 +389,34 @@ copy_subrs(gs_font_type1 *pfont, bool global, gs_subr_info_t *psi,
* pointer to the slot where it would be added, which will have gdata.data
* == 0, and return gs_error_undefined; if the glyph is defined, store the
* pointer and return 0.
+ *
+ * NOTE:
+ * The interim variable (idx) is used here as a workaround for what appears
+ * to be a compiler optimiser bug in VS2019 - using "glyph - GS_MIN_CID_GLYPH"
+ * directly to index into the cfdata->glyphs array results in a pointer value
+ * in *pslot which is complete nonsense. Using the variable to store the
+ * calculated value results in working code.
*/
static int
copied_glyph_slot(gs_copied_font_data_t *cfdata, gs_glyph glyph,
gs_copied_glyph_t **pslot)
{
uint gsize = cfdata->glyphs_size;
+ unsigned int idx;
*pslot = 0;
if (glyph >= GS_MIN_GLYPH_INDEX) {
/* CIDFontType 2 uses glyph indices for slots. */
- if (glyph - GS_MIN_GLYPH_INDEX >= gsize)
+ idx = (unsigned int)(glyph - GS_MIN_GLYPH_INDEX);
+ if (idx >= gsize)
return_error(gs_error_rangecheck);
- *pslot = &cfdata->glyphs[glyph - GS_MIN_GLYPH_INDEX];
+ *pslot = &cfdata->glyphs[idx];
} else if (glyph >= GS_MIN_CID_GLYPH) {
/* CIDFontType 0 uses CIDS for slots. */
- if (glyph - GS_MIN_CID_GLYPH >= gsize)
+ idx = (unsigned int)(glyph - GS_MIN_CID_GLYPH);
+ if (idx >= gsize)
return_error(gs_error_rangecheck);
- *pslot = &cfdata->glyphs[glyph - GS_MIN_CID_GLYPH];
+ *pslot = &cfdata->glyphs[idx];
} else if (cfdata->names == 0)
return_error(gs_error_rangecheck);
else {
@@ -515,16 +525,22 @@ copy_glyph_data(gs_font *font, gs_glyph glyph, gs_font *copied, int options,
code = gs_note_error(gs_error_undefined);
else {
uint str_size = prefix_bytes + size;
- byte *str = gs_alloc_string(copied->memory, str_size,
- "copy_glyph_data(data)");
-
- if (str == 0)
- code = gs_note_error(gs_error_VMerror);
- else {
- if (prefix_bytes)
- memcpy(str, prefix, prefix_bytes);
- memcpy(str + prefix_bytes, pgdata->bits.data, size);
- pcg->gdata.data = str;
+
+ code = 0;
+ if (str_size > 0) {
+ byte *str = gs_alloc_string(copied->memory, str_size,
+ "copy_glyph_data(data)");
+
+ if (str == 0)
+ code = gs_note_error(gs_error_VMerror);
+ else {
+ if (prefix_bytes)
+ memcpy(str, prefix, prefix_bytes);
+ memcpy(str + prefix_bytes, pgdata->bits.data, size);
+ pcg->gdata.data = str;
+ }
+ }
+ if (code >= 0) {
pcg->gdata.size = str_size;
pcg->used = HAS_DATA;
pcg->order_index = -1;
@@ -577,11 +593,14 @@ copy_glyph_name(gs_font *font, gs_glyph glyph, gs_font *copied,
if (extra_name == 0)
return_error(gs_error_VMerror);
+ memset(extra_name, 0x00, sizeof(gs_copied_glyph_extra_name_t));
extra_name->next = cfdata->extra_names;
extra_name->gid = pcg - cfdata->glyphs;
cfdata->extra_names = extra_name;
pcgn = &extra_name->name;
}
+ if (pcgn->str.size != 0 && !gs_is_c_glyph_name(pcgn->str.data, pcgn->str.size))
+ gs_free_string(copied->memory, (byte *)pcgn->str.data, pcgn->str.size, "Free copied glyph name");
pcgn->glyph = glyph;
pcgn->str = str;
return 0;
@@ -968,7 +987,7 @@ copied_type1_seac_data(gs_font_type1 * pfont, int ccode,
code = gs_c_glyph_name(glyph, gstr);
if (code < 0)
return code;
- code = pfont->dir->global_glyph_code(pfont->memory, gstr, &glyph1);
+ code = pfont->dir->global_glyph_code((gs_font *)pfont, gstr, &glyph1);
if (code < 0)
return code;
if (pglyph)
@@ -1850,7 +1869,6 @@ copy_font_cid2(gs_font *font, gs_font *copied)
copied2->memory, return_error(gs_error_VMerror), "copy_font_cid2");
subst->data[0] = subst->data[1] = 0;
copied2->subst_CID_on_WMode = subst;
- rc_increment(subst);
}
return 0;
@@ -1865,12 +1883,13 @@ static int expand_CIDMap(gs_font_cid2 *copied2, uint CIDCount)
return 0;
CIDMap = (ushort *)
gs_alloc_byte_array(copied2->memory, CIDCount, sizeof(ushort),
- "copy_font_cid2(CIDMap");
+ "expand_CIDMap(new CIDMap)");
if (CIDMap == 0)
return_error(gs_error_VMerror);
memcpy(CIDMap, cfdata->CIDMap, copied2->cidata.common.CIDCount * sizeof(*CIDMap));
memset(CIDMap + copied2->cidata.common.CIDCount, 0xFF,
(CIDCount - copied2->cidata.common.CIDCount) * sizeof(*CIDMap));
+ gs_free_object(copied2->memory, cfdata->CIDMap, "expand_CIDMap(old CIDMap)");
cfdata->CIDMap = CIDMap;
copied2->cidata.common.CIDCount = CIDCount;
return 0;
@@ -2194,9 +2213,13 @@ gs_copy_font(gs_font *font, const gs_matrix *orig_matrix, gs_memory_t *mem, gs_f
if (code < 0)
goto fail;
- *pfont_new = copied;
if (cfdata->notdef != GS_NO_GLYPH)
code = gs_copy_glyph(font, cfdata->notdef, copied);
+ if (code < 0)
+ gs_free_copied_font(copied);
+ else
+ *pfont_new = copied;
+
return code;
fail:
@@ -2251,6 +2274,7 @@ int gs_free_copied_font(gs_font *font)
gs_memory_t *mem = font->memory;
int i, code;
gs_copied_glyph_t *pcg = 0;
+ gs_copied_glyph_name_t *pcgn = 0;
/* For CID fonts, we must also free the descendants, which we copied
* at the time we copied the actual CIDFont itself
@@ -2267,13 +2291,39 @@ int gs_free_copied_font(gs_font *font)
copied0->cidata.FDArray = 0;
}
+ if (font->FontType == ft_CID_TrueType) {
+ gs_font_cid2 *copied2 = (gs_font_cid2 *)font;
+
+ if (copied2->subst_CID_on_WMode)
+ rc_decrement(copied2->subst_CID_on_WMode, "gs_free_copied_font(subst_CID_on_WMode");
+ }
+
if (cfdata) {
/* free copied glyph data */
for (i=0;i < cfdata->glyphs_size;i++) {
pcg = &cfdata->glyphs[i];
- if(pcg->gdata.size) {
+ if(pcg->gdata.data != NULL) {
gs_free_string(font->memory, (byte *)pcg->gdata.data, pcg->gdata.size, "Free copied glyph");
}
+ if (cfdata->names) {
+ pcgn = &cfdata->names[i];
+ if (pcgn->str.data != NULL) {
+ if (!gs_is_c_glyph_name(pcgn->str.data, pcgn->str.size))
+ gs_free_string(font->memory, (byte *)pcgn->str.data, pcgn->str.size, "Free copied glyph name");
+ }
+ }
+ }
+ if (cfdata->extra_names) {
+ gs_copied_glyph_extra_name_t *extra_name = cfdata->extra_names, *next;
+
+ while (extra_name != NULL) {
+ next = extra_name->next;
+ if (!gs_is_c_glyph_name(extra_name->name.str.data, extra_name->name.str.size))
+ gs_free_string(font->memory, (byte *)extra_name->name.str.data, extra_name->name.str.size, "Free extra name string");
+ gs_free_object(font->memory, extra_name, "free copied font(extra_names)");
+ extra_name = next;
+ }
+ cfdata->extra_names = NULL;
}
uncopy_string(mem, &cfdata->info.FullName,
@@ -2284,8 +2334,18 @@ int gs_free_copied_font(gs_font *font)
"gs_free_copied_font(Notice)");
uncopy_string(mem, &cfdata->info.Copyright,
"gs_free_copied_font(Copyright)");
+ if (cfdata->subrs.data != NULL)
+ gs_free_object(mem, cfdata->subrs.data, "gs_free_copied_font(subrs.data)");
+ if (cfdata->subrs.starts != NULL)
+ gs_free_object(mem, cfdata->subrs.starts, "gs_free_copied_font(subrs.dtarts)");
+ if (cfdata->global_subrs.data != NULL)
+ gs_free_object(mem, cfdata->global_subrs.data, "gs_free_copied_font(gsubrs.data)");
+ if (cfdata->global_subrs.starts != NULL)
+ gs_free_object(mem, cfdata->global_subrs.starts, "gs_free_copied_font(gsubrs.starts)");
if (cfdata->Encoding)
gs_free_object(mem, cfdata->Encoding, "gs_free_copied_font(Encoding)");
+ if (cfdata->CIDMap)
+ gs_free_object(mem, cfdata->CIDMap, "gs_free_copied_font(CIDMap)");
gs_free_object(mem, cfdata->glyphs, "gs_free_copied_font(glyphs)");
gs_free_object(mem, cfdata->names, "gs_free_copied_font(names)");
gs_free_object(mem, cfdata->data, "gs_free_copied_font(data)");
diff --git a/devices/gxfcopy.h b/devices/gxfcopy.h
index 8a6efbaa..8c6909ed 100644
--- a/devices/gxfcopy.h
+++ b/devices/gxfcopy.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/minftrsz.c b/devices/minftrsz.c
index a8c5d202..5b9aadf2 100644
--- a/devices/minftrsz.c
+++ b/devices/minftrsz.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/minftrsz.h b/devices/minftrsz.h
index d520a62a..5552a9c6 100644
--- a/devices/minftrsz.h
+++ b/devices/minftrsz.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/evenbetter-rll.c b/devices/rinkj/evenbetter-rll.c
index 5928704a..ac03960f 100644
--- a/devices/rinkj/evenbetter-rll.c
+++ b/devices/rinkj/evenbetter-rll.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/evenbetter-rll.h b/devices/rinkj/evenbetter-rll.h
index 3e1d7fa6..1cb1f687 100644
--- a/devices/rinkj/evenbetter-rll.h
+++ b/devices/rinkj/evenbetter-rll.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-byte-stream.c b/devices/rinkj/rinkj-byte-stream.c
index 9f84ce96..c6e551ff 100644
--- a/devices/rinkj/rinkj-byte-stream.c
+++ b/devices/rinkj/rinkj-byte-stream.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-byte-stream.h b/devices/rinkj/rinkj-byte-stream.h
index b2741088..0f68bd0f 100644
--- a/devices/rinkj/rinkj-byte-stream.h
+++ b/devices/rinkj/rinkj-byte-stream.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-config.c b/devices/rinkj/rinkj-config.c
index 4b084458..7e6119fc 100644
--- a/devices/rinkj/rinkj-config.c
+++ b/devices/rinkj/rinkj-config.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-config.h b/devices/rinkj/rinkj-config.h
index 716caa75..2f999575 100644
--- a/devices/rinkj/rinkj-config.h
+++ b/devices/rinkj/rinkj-config.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-device.c b/devices/rinkj/rinkj-device.c
index 43ba6f80..11d076e0 100644
--- a/devices/rinkj/rinkj-device.c
+++ b/devices/rinkj/rinkj-device.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-device.h b/devices/rinkj/rinkj-device.h
index c936711f..8b173c3e 100644
--- a/devices/rinkj/rinkj-device.h
+++ b/devices/rinkj/rinkj-device.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-dither.c b/devices/rinkj/rinkj-dither.c
index f5a12844..fdf8a3b0 100644
--- a/devices/rinkj/rinkj-dither.c
+++ b/devices/rinkj/rinkj-dither.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-dither.h b/devices/rinkj/rinkj-dither.h
index 815368c8..1572ec43 100644
--- a/devices/rinkj/rinkj-dither.h
+++ b/devices/rinkj/rinkj-dither.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-epson870.c b/devices/rinkj/rinkj-epson870.c
index 59d55f57..83bcf12c 100644
--- a/devices/rinkj/rinkj-epson870.c
+++ b/devices/rinkj/rinkj-epson870.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-epson870.h b/devices/rinkj/rinkj-epson870.h
index 08f135f9..308c75c7 100644
--- a/devices/rinkj/rinkj-epson870.h
+++ b/devices/rinkj/rinkj-epson870.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-screen-eb.c b/devices/rinkj/rinkj-screen-eb.c
index e6a9f779..6724b5e2 100644
--- a/devices/rinkj/rinkj-screen-eb.c
+++ b/devices/rinkj/rinkj-screen-eb.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/rinkj/rinkj-screen-eb.h b/devices/rinkj/rinkj-screen-eb.h
index 8b61fe35..6a978fd6 100644
--- a/devices/rinkj/rinkj-screen-eb.h
+++ b/devices/rinkj/rinkj-screen-eb.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/doc_common.c b/devices/vector/doc_common.c
new file mode 100644
index 00000000..50123f8f
--- /dev/null
+++ b/devices/vector/doc_common.c
@@ -0,0 +1,532 @@
+#include "doc_common.h"
+
+#include "gxfont.h"
+#include "gserrors.h"
+#include "gxfcid.h"
+#include "gdevagl.h"
+#include "gxdevcli.h"
+#include "gxgstate.h"
+
+#include <string.h>
+
+
+extern single_glyph_list_t SingleGlyphList[];
+extern double_glyph_list_t DoubleGlyphList[];
+extern treble_glyph_list_t TrebleGlyphList[];
+extern quad_glyph_list_t QuadGlyphList[];
+
+
+static int
+font_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat)
+{
+ int code;
+
+ switch (font->FontType) {
+ case ft_composite: /* subfonts have their own FontMatrix */
+ case ft_TrueType:
+ case ft_CID_TrueType:
+ /* The TrueType FontMatrix is 1 unit per em, which is what we want. */
+ gs_make_identity(pmat);
+ return 0;
+ case ft_encrypted:
+ case ft_encrypted2:
+ case ft_CID_encrypted:
+ case ft_user_defined:
+ case ft_PCL_user_defined:
+ case ft_GL2_stick_user_defined:
+ case ft_GL2_531:
+ /*
+ * Type 1 fonts are supposed to use a standard FontMatrix of
+ * [0.001 0 0 0.001 0 0], with a 1000-unit cell. However,
+ * Windows NT 4.0 creates Type 1 fonts, apparently derived from
+ * TrueType fonts, that use a 2048-unit cell and corresponding
+ * FontMatrix. Also, some PS programs perform font scaling by
+ * replacing FontMatrix like this :
+ *
+ * /f12 /Times-Roman findfont
+ * copyfont % (remove FID)
+ * dup /FontMatrix [0.012 0 0 0.012 0 0] put
+ * definefont
+ * /f12 1 selectfont
+ *
+ * Such fonts are their own "base font", but the orig_matrix
+ * must still be set to 0.001, not 0.012 .
+ *
+ * The old code used a heuristic to detect and correct for this here.
+ * Unfortunately it doesn't work properly when it meets a font
+ * with FontMatrix like this :
+ *
+ * /FontMatrix [1 2288 div 0 0 1 2288 div 0 0 ] def
+ *
+ * (the bug 686970). Also comparefiles\455690.pdf appears to
+ * have similar problem. Therefore we added a support to lib/gs_fonts.ps,
+ * src/zbfont.c, src/gsfont.c that provides an acces to the original
+ * font via a special key OrigFont added to the font dictionary while definefont.
+ * Now we work through this access with PS interpreter,
+ * but keep the old heuristic for other clients.
+ */
+ {
+ const gs_font *base_font = font;
+
+ while (base_font->base != base_font)
+ base_font = base_font->base;
+ if (font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined ||
+ font->FontType == ft_GL2_531)
+ *pmat = base_font->FontMatrix;
+ else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 ||
+ base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0)
+ *pmat = base_font->orig_FontMatrix;
+ else {
+ /* Must not happen with PS interpreter.
+ Provide a hewuristic for other clients.
+ */
+ if (base_font->FontMatrix.xx == 1.0/2048 &&
+ base_font->FontMatrix.xy == 0 &&
+ base_font->FontMatrix.yx == 0 &&
+ any_abs(base_font->FontMatrix.yy) == 1.0/2048
+ )
+ *pmat = base_font->FontMatrix;
+ else
+ gs_make_scaling(0.001, 0.001, pmat);
+ }
+ }
+ if (font->FontType == ft_CID_encrypted && cid != -1) {
+ int fidx;
+
+ if (cid < GS_MIN_CID_GLYPH)
+ cid = GS_MIN_CID_GLYPH;
+ code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
+ cid, NULL, &fidx);
+ if (code < 0) {
+ code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
+ (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx);
+ }
+ if (code >= 0) {
+ gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix),
+ pmat, pmat);
+ }
+ }
+ return 0;
+ default:
+ return_error(gs_error_rangecheck);
+ }
+}
+
+/*
+ * Special version of font_orig_matrix(), that considers FDArray font's FontMatrix too.
+ * Called only by txt_glyph_width().
+ * 'cid' is only consulted if 'font' is a CIDFontType 0 CID font.
+ */
+static int
+glyph_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat)
+{
+ int code = font_orig_matrix(font, cid, pmat);
+ if (code >= 0) {
+ if (font->FontType == ft_CID_encrypted) {
+ int fidx;
+
+ if (cid < GS_MIN_CID_GLYPH)
+ cid = GS_MIN_CID_GLYPH;
+ code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
+ cid, NULL, &fidx);
+ if (code < 0) {
+ code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
+ (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx);
+ }
+ if (code >= 0) {
+ gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix),
+ pmat, pmat);
+ }
+ }
+ }
+ return code;
+}
+
+float txt_calculate_text_size(gs_gstate *pgs, gs_font *ofont,
+ const gs_matrix *pfmat, gs_matrix *smat, gs_matrix *tmat,
+ gs_font *font, gx_device *pdev)
+{
+ gs_matrix orig_matrix;
+ double
+ sx = pdev->HWResolution[0] / 72.0,
+ sy = pdev->HWResolution[1] / 72.0;
+ float size;
+
+ /* Get the original matrix of the base font. */
+
+ font_orig_matrix(ofont, -1, &orig_matrix);
+ /* Compute the scaling matrix and combined matrix. */
+
+ if (gs_matrix_invert(&orig_matrix, smat) < 0) {
+ gs_make_identity(smat);
+ return 1; /* Arbitrary */
+ }
+ gs_matrix_multiply(smat, pfmat, smat);
+ *tmat = ctm_only(pgs);
+ tmat->tx = tmat->ty = 0;
+ gs_matrix_multiply(smat, tmat, tmat);
+
+ /* Try to find a reasonable size value. */
+
+ size = hypot(tmat->yx, tmat->yy) / sy;
+ if (size < 0.01)
+ size = hypot(tmat->xx, tmat->xy) / sx;
+ if (size < 0.01)
+ size = 1;
+
+ return(size);
+}
+
+static int
+store_glyph_width(txt_glyph_width_t *pwidth, int wmode, const gs_matrix *scale,
+ const gs_glyph_info_t *pinfo)
+{
+ double w, v;
+
+ gs_distance_transform(pinfo->width[wmode].x, pinfo->width[wmode].y, scale, &pwidth->xy);
+ if (wmode)
+ w = pwidth->xy.y, v = pwidth->xy.x;
+ else
+ w = pwidth->xy.x, v = pwidth->xy.y;
+ if (v != 0)
+ return 1;
+ pwidth->w = w;
+ gs_distance_transform(pinfo->v.x, pinfo->v.y, scale, &pwidth->v);
+ return 0;
+}
+
+static int
+get_missing_width(gs_font *font, int wmode, const gs_matrix *scale_c,
+ txt_glyph_widths_t *pwidths)
+{
+ gs_font_info_t finfo;
+ int code;
+
+ code = font->procs.font_info((gs_font *)font, NULL,
+ FONT_INFO_MISSING_WIDTH, &finfo);
+ if (code < 0)
+ return code;
+ if (!(finfo.members & FONT_INFO_MISSING_WIDTH))
+ return_error(gs_error_undefined);
+
+ if (wmode) {
+ gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy);
+ pwidths->Width.xy.x = 0;
+ pwidths->Width.xy.y = pwidths->real_width.xy.y;
+ pwidths->Width.w = pwidths->real_width.w =
+ pwidths->Width.xy.y;
+ pwidths->Width.v.x = - pwidths->Width.xy.y / 2;
+ pwidths->Width.v.y = - pwidths->Width.xy.y;
+ } else {
+ gs_distance_transform(finfo.MissingWidth, 0.0, scale_c, &pwidths->real_width.xy);
+ pwidths->Width.xy.x = pwidths->real_width.xy.x;
+ pwidths->Width.xy.y = 0;
+ pwidths->Width.w = pwidths->real_width.w =
+ pwidths->Width.xy.x;
+ pwidths->Width.v.x = pwidths->Width.v.y = 0;
+ }
+ /*
+ * Don't mark the width as known, just in case this is an
+ * incrementally defined font.
+ */
+ return 1;
+}
+
+/*
+ * Get the widths (unmodified from the copied font,
+ * and possibly modified from the original font) of a given glyph.
+ * Return 1 if the width was defaulted to MissingWidth.
+ * Return TEXT_PROCESS_CDEVPROC if a CDevProc callout is needed.
+ * cdevproc_result != NULL if we restart after a CDevProc callout.
+ */
+int
+txt_glyph_widths(gs_font *font, int wmode, gs_glyph glyph,
+ gs_font *orig_font, txt_glyph_widths_t *pwidths,
+ const double cdevproc_result[10])
+{
+ gs_font *ofont = orig_font;
+ gs_glyph_info_t info;
+ gs_matrix scale_c, scale_o;
+ int code, rcode = 0;
+ gs_point v;
+ int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType
+ || orig_font->FontType == ft_CID_encrypted
+ ? GLYPH_INFO_CDEVPROC : 0); /* fixme : allow more font types. */
+
+ if (ofont->FontType == ft_composite)
+ return_error(gs_error_unregistered); /* Must not happen. */
+ code = glyph_orig_matrix((const gs_font *)font, glyph, &scale_c);
+ if (code < 0)
+ return code;
+ code = glyph_orig_matrix(ofont, glyph, &scale_o);
+ if (code < 0)
+ return code;
+ gs_matrix_scale(&scale_c, 1000.0, 1000.0, &scale_c);
+ gs_matrix_scale(&scale_o, 1000.0, 1000.0, &scale_o);
+ pwidths->Width.v.x = pwidths->Width.v.y = pwidths->Width.xy.x = pwidths->Width.xy.y = 0;
+ pwidths->real_width.v.x = pwidths->real_width.v.y = pwidths->real_width.xy.x = pwidths->real_width.xy.y = 0;
+ pwidths->Width.w = pwidths->real_width.w = 0.0;
+ pwidths->replaced_v = false;
+ if (glyph == GS_NO_GLYPH)
+ return get_missing_width(font, wmode, &scale_c, pwidths);
+ code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
+ GLYPH_INFO_WIDTH0 |
+ (GLYPH_INFO_WIDTH0 << wmode) |
+ GLYPH_INFO_OUTLINE_WIDTHS |
+ (GLYPH_INFO_VVECTOR0 << wmode),
+ &info);
+ /* For CID fonts the PDF spec requires the x-component of v-vector
+ to be equal to half glyph width, and AR5 takes it from W, DW.
+ So make a compatibe data here.
+ */
+ if (font->FontType != ft_PCL_user_defined && font->FontType != ft_GL2_stick_user_defined &&
+ font->FontType != ft_GL2_531
+ && (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))) {
+ code = get_missing_width(font, wmode, &scale_c, pwidths);
+ if (code < 0)
+ return code;
+ else
+ v.y = pwidths->Width.v.y;
+ if (wmode && (ofont->FontType == ft_CID_encrypted ||
+ ofont->FontType == ft_CID_TrueType)) {
+ txt_glyph_widths_t widths1;
+
+ if (get_missing_width(font, 0, &scale_c, &widths1) < 0)
+ v.x = 0;
+ else
+ v.x = widths1.Width.w / 2;
+ } else
+ v.x = pwidths->Width.v.x;
+ } else if (code < 0)
+ return code;
+ else {
+ code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info);
+ if (code < 0)
+ return code;
+ rcode |= code;
+ if (info.members & (GLYPH_INFO_VVECTOR0 << wmode))
+ gs_distance_transform(info.v.x, info.v.y, &scale_c, &v);
+ else
+ v.x = v.y = 0;
+ if (wmode && (ofont->FontType == ft_CID_encrypted ||
+ ofont->FontType == ft_CID_TrueType)) {
+ if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) {
+ gs_point xy;
+
+ gs_distance_transform(info.width[0].x, info.width[0].y, &scale_c, &xy);
+ v.x = xy.x / 2;
+ } else {
+ txt_glyph_widths_t widths1;
+
+ if (get_missing_width(font, 0, &scale_c, &widths1) < 0)
+ v.x = 0;
+ else
+ v.x = widths1.Width.w / 2;
+ }
+ }
+ }
+ pwidths->Width.v = v;
+ /* Skip only if not paralel to the axis. */
+ if (code > 0 && ofont->FontType != ft_CID_encrypted &&
+ ofont->FontType != ft_CID_TrueType)
+ pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0;
+ if (cdevproc_result == NULL) {
+ info.members = 0;
+ code = ofont->procs.glyph_info(ofont, glyph, NULL,
+ (GLYPH_INFO_WIDTH0 << wmode) |
+ (GLYPH_INFO_VVECTOR0 << wmode) |
+ allow_cdevproc_callout,
+ &info);
+ /* fixme : Move this call before cfont->procs.glyph_info. */
+ if (info.members & GLYPH_INFO_CDEVPROC) {
+ if (allow_cdevproc_callout)
+ return TEXT_PROCESS_CDEVPROC;
+ else
+ return_error(gs_error_rangecheck);
+ }
+ } else {
+ info.width[0].x = cdevproc_result[0];
+ info.width[0].y = cdevproc_result[1];
+ info.width[1].x = cdevproc_result[6];
+ info.width[1].y = cdevproc_result[7];
+ info.v.x = (wmode ? cdevproc_result[8] : 0);
+ info.v.y = (wmode ? cdevproc_result[9] : 0);
+ info.members = (GLYPH_INFO_WIDTH0 << wmode) |
+ (wmode ? GLYPH_INFO_VVECTOR1 : 0);
+ code = 0;
+ }
+ if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))
+ pwidths->real_width = pwidths->Width;
+ else if (code < 0)
+ return code;
+ else {
+ if ((info.members & (GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1)) != 0)
+ pwidths->replaced_v = true;
+ else
+ info.v.x = info.v.y = 0;
+ code = store_glyph_width(&pwidths->real_width, wmode, &scale_o, &info);
+ if (code < 0)
+ return code;
+ rcode |= code;
+ gs_distance_transform(info.v.x, info.v.y, &scale_o, &pwidths->real_width.v);
+ }
+ return rcode;
+}
+
+void
+txt_char_widths_to_uts(gs_font *font /* may be NULL for non-Type3 */,
+ txt_glyph_widths_t *pwidths)
+{
+ if (font && (font->FontType == ft_user_defined ||
+ font->FontType == ft_PCL_user_defined ||
+ font->FontType == ft_GL2_stick_user_defined ||
+ font->FontType == ft_GL2_531)) {
+ gs_matrix *pmat = &font->orig_FontMatrix;
+
+ pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
+ pwidths->Width.xy.y = 0.0; /* WMode == 0 for PDF Type 3 fonts */
+ gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
+ } else {
+ /*
+ * For other font types:
+ * - PDF design->text space is a simple scaling by 0.001.
+ * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
+ */
+ pwidths->Width.xy.x /= 1000.0;
+ pwidths->Width.xy.y /= 1000.0;
+ pwidths->real_width.xy.x /= 1000.0;
+ pwidths->real_width.xy.y /= 1000.0;
+ }
+}
+
+
+int txt_get_unicode(gx_device *dev, gs_font *font, gs_glyph glyph, gs_char ch, unsigned short *Buffer)
+{
+ int code;
+ gs_const_string gnstr;
+ unsigned short fallback = ch;
+ ushort *unicode = NULL;
+ int length;
+
+ length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
+ if (length == 0) {
+ if (glyph != GS_NO_GLYPH) {
+ code = font->procs.glyph_name(font, glyph, &gnstr);
+ if (code >= 0 && gnstr.size == 7) {
+ if (!memcmp(gnstr.data, "uni", 3)) {
+ static const char *hexdigits = "0123456789ABCDEF";
+ char *d0 = strchr(hexdigits, gnstr.data[3]);
+ char *d1 = strchr(hexdigits, gnstr.data[4]);
+ char *d2 = strchr(hexdigits, gnstr.data[5]);
+ char *d3 = strchr(hexdigits, gnstr.data[6]);
+
+ if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
+ *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits);
+ return 1;
+ }
+ }
+ }
+ if (length == 0) {
+ single_glyph_list_t *sentry = SingleGlyphList;
+ double_glyph_list_t *dentry = DoubleGlyphList;
+ treble_glyph_list_t *tentry = TrebleGlyphList;
+ quad_glyph_list_t *qentry = QuadGlyphList;
+
+ /* Search glyph to single Unicode value table */
+ while (sentry->Glyph != 0) {
+ if (sentry->Glyph[0] < gnstr.data[0]) {
+ sentry++;
+ continue;
+ }
+ if (sentry->Glyph[0] > gnstr.data[0]){
+ break;
+ }
+ if (strlen(sentry->Glyph) == gnstr.size) {
+ if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) {
+ *Buffer = sentry->Unicode;
+ return 1;
+ }
+ }
+ sentry++;
+ }
+
+ /* Search glyph to double Unicode value table */
+ while (dentry->Glyph != 0) {
+ if (dentry->Glyph[0] < gnstr.data[0]) {
+ dentry++;
+ continue;
+ }
+ if (dentry->Glyph[0] > gnstr.data[0]){
+ break;
+ }
+ if (strlen(dentry->Glyph) == gnstr.size) {
+ if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) {
+ memcpy(Buffer, dentry->Unicode, 2);
+ return 2;
+ }
+ }
+ dentry++;
+ }
+
+ /* Search glyph to triple Unicode value table */
+ while (tentry->Glyph != 0) {
+ if (tentry->Glyph[0] < gnstr.data[0]) {
+ tentry++;
+ continue;
+ }
+ if (tentry->Glyph[0] > gnstr.data[0]){
+ break;
+ }
+ if (strlen(tentry->Glyph) == gnstr.size) {
+ if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) {
+ memcpy(Buffer, tentry->Unicode, 3);
+ return 3;
+ }
+ }
+ tentry++;
+ }
+
+ /* Search glyph to quadruple Unicode value table */
+ while (qentry->Glyph != 0) {
+ if (qentry->Glyph[0] < gnstr.data[0]) {
+ qentry++;
+ continue;
+ }
+ if (qentry->Glyph[0] > gnstr.data[0]){
+ break;
+ }
+ if (strlen(qentry->Glyph) == gnstr.size) {
+ if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) {
+ memcpy(Buffer, qentry->Unicode, 4);
+ return 4;
+ }
+ }
+ qentry++;
+ }
+ }
+ }
+ *Buffer = fallback;
+ return 1;
+ } else {
+ char *b, *u;
+ int l = length - 1;
+
+ unicode = (ushort *)gs_alloc_bytes(dev->memory, length, "temporary Unicode array");
+ length = font->procs.decode_glyph((gs_font *)font, glyph, ch, unicode, length);
+#if ARCH_IS_BIG_ENDIAN
+ memcpy(Buffer, unicode, length);
+#else
+ b = (char *)Buffer;
+ u = (char *)unicode;
+
+ for (l=0;l<length;l+=2, u+=2){
+ *b++ = *(u+1);
+ *b++ = *u;
+ }
+#endif
+ gs_free_object(dev->memory, unicode, "free temporary unicode buffer");
+ return length / sizeof(short);
+ }
+}
diff --git a/devices/vector/doc_common.h b/devices/vector/doc_common.h
new file mode 100644
index 00000000..24369054
--- /dev/null
+++ b/devices/vector/doc_common.h
@@ -0,0 +1,58 @@
+#ifndef gdevtxtw_INCLUDED
+#define gdevtxtw_INCLUDED
+
+#include "gsccode.h"
+#include "gsccode.h"
+#include "gsdevice.h"
+#include "gsfont.h"
+#include "gsgstate.h"
+#include "gsmatrix.h"
+#include "gstypes.h"
+
+/*
+ * Some structures and functions that are used by gdevdocxw.c and gdevtxtw.c.
+ */
+
+/*
+ * Define the structure used to return glyph width information. Note that
+ * there are two different sets of width information: real-number (x,y)
+ * values, which give the true advance width, and an integer value, which
+ * gives an X advance width for WMode = 0 or a Y advance width for WMode = 1.
+ * The return value from txt_glyph_width() indicates which of these is/are
+ * valid.
+ */
+typedef struct txt_glyph_width_s {
+ double w;
+ gs_point xy;
+ gs_point v; /* glyph origin shift */
+} txt_glyph_width_t;
+
+typedef struct txt_glyph_widths_s {
+ txt_glyph_width_t Width; /* unmodified, for Widths */
+ txt_glyph_width_t real_width; /* possibly modified, for rendering */
+ bool replaced_v;
+} txt_glyph_widths_t;
+
+int
+txt_glyph_widths(gs_font *font, int wmode, gs_glyph glyph,
+ gs_font *orig_font, txt_glyph_widths_t *pwidths,
+ const double cdevproc_result[10]);
+
+/* Try to convert glyph names/character codes to Unicode. We first try to see
+ * if we have any Unicode information either from a ToUnicode CMap or GlyphNames2Unicode
+ * table. If that fails we look at the glyph name to see if it starts 'uni'
+ * in which case we assume the remainder of the name is the Unicode value. If
+ * its not a glyph of that form then we search a bunch of tables whcih map standard
+ * glyph names to Unicode code points. If that fails we finally just return the character code.
+ */
+int txt_get_unicode(gx_device *dev, gs_font *font, gs_glyph glyph, gs_char ch, unsigned short *Buffer);
+
+void
+txt_char_widths_to_uts(gs_font *font /* may be NULL for non-Type3 */,
+ txt_glyph_widths_t *pwidths);
+
+float txt_calculate_text_size(gs_gstate *pgs, gs_font *ofont,
+ const gs_matrix *pfmat, gs_matrix *smat, gs_matrix *tmat,
+ gs_font *font, gx_device *pdev);
+
+#endif
diff --git a/devices/vector/gdevagl.c b/devices/vector/gdevagl.c
index a551bb38..05b971a1 100644
--- a/devices/vector/gdevagl.c
+++ b/devices/vector/gdevagl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevagl.h b/devices/vector/gdevagl.h
index 066eae76..e05b53be 100644
--- a/devices/vector/gdevagl.h
+++ b/devices/vector/gdevagl.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevdocxw.c b/devices/vector/gdevdocxw.c
new file mode 100644
index 00000000..c9be4757
--- /dev/null
+++ b/devices/vector/gdevdocxw.c
@@ -0,0 +1,1376 @@
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* Device for creating docx files. */
+
+#include "memory_.h"
+#include "string_.h"
+#include "gp.h" /* for gp_file_name_sizeof */
+#include "gx.h"
+#include "gserrors.h"
+#include "gsparam.h"
+#include "gsutil.h"
+#include "gxdevice.h"
+#include "gsdevice.h" /* requires gsmatrix.h */
+#include "gxfont.h"
+#include "gxfont0.h"
+#include "gstext.h"
+#include "gxfcid.h"
+#include "gxgstate.h"
+#include "gxpath.h"
+#include "gdevagl.h"
+#include "gxdevsop.h"
+#include "gzpath.h"
+#include "gdevkrnlsclass.h" /* 'standard' built in subclasses, currently First/Last Page and obejct filter */
+#include "gxchar.h"
+
+#include "doc_common.h"
+
+#include "../../extract/include/extract.h"
+
+#include <errno.h>
+
+#define outf(format, ...)
+#define outfx(format, ...)
+
+#ifdef __unix__
+#if 0
+
+/* Enable logging using outf() macro/function. */
+#include <unistd.h>
+
+static void (outf)(const char* file, int line, const char* function, const char* format, ...)
+{
+ static char buffer[2048];
+ size_t prefix;
+ va_list va;
+ snprintf(buffer, sizeof(buffer), "%s:%i:%s(): ", file, line, function);
+ prefix = strlen(buffer);
+ va_start(va, format);
+ vsnprintf(buffer + prefix, sizeof(buffer) - 1 - prefix, format, va);
+ va_end(va);
+ size_t l = strlen(buffer);
+ buffer[l] = '\n';
+ buffer[l+1] = 0;
+ write(2, buffer, l+1);
+}
+
+#undef outf
+#define outf(format, ...) outf(__FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__)
+
+#endif
+#endif
+
+
+
+extern single_glyph_list_t SingleGlyphList[];
+extern double_glyph_list_t DoubleGlyphList[];
+extern treble_glyph_list_t TrebleGlyphList[];
+extern quad_glyph_list_t QuadGlyphList[];
+
+/* Structure to record the Unicode characters, the total width of the text
+ * recorded, and various useful attributes such as the font, size, colour
+ * rendering mode, writing mode etc. These are stored as a series of x-ordered
+ * entries in a list, using the starting x co-ordinate.
+ */
+typedef struct docx_list_entry_t {
+ struct text_list_entry_s *previous;
+ struct text_list_entry_s *next;
+ gs_matrix matrix; /* Tm et al */
+ char *FontName;
+ int wmode; /* WMode of font */
+ double size;
+} docx_list_entry_t;
+
+/* The custom sub-classed device structure */
+typedef struct {
+ gx_device_common;
+ char fname[gp_file_name_sizeof]; /* OutputFile */
+ gp_file *file;
+ int TextFormat;
+ extract_alloc_t *alloc;
+ extract_t *extract;
+ int file_per_page;
+ float x; /* Used to maintain x pos as we iterate through a span. */
+} gx_device_docxwrite_t;
+
+
+/* Device procedures */
+static dev_proc_open_device(docxwrite_open_device);
+static dev_proc_close_device(docxwrite_close_device);
+static dev_proc_output_page(docxwrite_output_page);
+static dev_proc_fill_rectangle(docxwrite_fill_rectangle);
+static dev_proc_get_params(docxwrite_get_params);
+static dev_proc_put_params(docxwrite_put_params);
+static dev_proc_fill_path(docxwrite_fill_path);
+static dev_proc_stroke_path(docxwrite_stroke_path);
+static dev_proc_text_begin(docxwrite_text_begin);
+static dev_proc_strip_copy_rop(docxwrite_strip_copy_rop);
+static dev_proc_dev_spec_op(docxwrite_dev_spec_op);
+
+
+/* The device prototype */
+#define X_DPI 72
+#define Y_DPI 72
+
+/* Define the text enumerator. */
+typedef struct {
+ gs_text_enum_common;
+ gs_text_enum_t *pte_fallback;
+ double d1_width;
+ bool d1_width_set;
+ bool charproc_accum;
+ bool cdevproc_callout;
+ double cdevproc_result[10];
+ docx_list_entry_t *text_state;
+} docxw_text_enum_t;
+#define private_st_textw_text_enum()\
+ extern_st(st_gs_text_enum);\
+ gs_private_st_suffix_add0(st_textw_text_enum, docxw_text_enum_t,\
+ "docxw_text_enum_t", textw_text_enum_enum_ptrs, textw_text_enum_reloc_ptrs,\
+ st_gs_text_enum)
+
+private_st_textw_text_enum();
+
+const gx_device_docxwrite_t gs_docxwrite_device =
+{
+ /* Define the device as 8-bit gray scale to avoid computing halftones. */
+ std_device_dci_body(gx_device_docxwrite_t, 0, "docxwrite",
+ DEFAULT_WIDTH_10THS * X_DPI / 10,
+ DEFAULT_HEIGHT_10THS * Y_DPI / 10,
+ X_DPI, Y_DPI,
+ 1, 8, 255, 0, 256, 1),
+ {docxwrite_open_device,
+ NULL, /*gx_upright_get_initial_matrix,*/
+ NULL, /*gx_default_sync_output,*/
+ docxwrite_output_page,
+ docxwrite_close_device,
+ NULL, /*gx_default_gray_map_rgb_color,*/
+ NULL, /*gx_default_gray_map_color_rgb,*/
+ docxwrite_fill_rectangle, /* Can't be NULL and there is no gx_default_fill_rectangle! */
+ NULL, /*gx_default_tile_rectangle,*/
+ NULL, /*gx_default_copy_mono,*/
+ NULL, /*gx_default_copy_color,*/
+ NULL, /*gx_default_draw_line,*/
+ NULL, /*gx_default_get_bits,*/
+ docxwrite_get_params,
+ docxwrite_put_params,
+ NULL, /*gx_default_map_cmyk_color,*/
+ NULL, /*gx_default_get_xfont_procs,*/
+ NULL, /*gx_default_get_xfont_device,*/
+ NULL, /*gx_default_map_rgb_alpha_color,*/
+ gx_page_device_get_page_device, /*gx_page_device_get_page_device,*/
+ NULL, /* get_alpha_bits */
+ NULL, /*gx_default_copy_alpha,*/
+ NULL, /* get_band */
+ NULL, /* copy_rop */
+ docxwrite_fill_path,
+ docxwrite_stroke_path,
+ NULL, /*gx_default_fill_mask,*/
+ NULL, /*gx_default_fill_trapezoid,*/
+ NULL, /*gx_default_fill_parallelogram,*/
+ NULL, /*gx_default_fill_triangle,*/
+ NULL, /*gx_default_draw_thin_line,*/
+ NULL, /* begin image */
+ NULL, /* image_data */
+ NULL, /* end_image */
+ NULL, /*gx_default_strip_tile_rectangle,*/
+ docxwrite_strip_copy_rop,
+ NULL, /* get_clipping_box */
+ NULL, /* docxwrite_begin_typed_image */
+ NULL, /* get_bits_rectangle */
+ NULL, /*gx_default_map_color_rgb_alpha,*/
+ gx_null_create_compositor,
+ NULL, /* get_hardware_params */
+ docxwrite_text_begin,
+ NULL, /* finish_copydevice */
+ NULL, /* begin_transparency_group */
+ NULL, /* end_transparency_group */
+ NULL, /* begin_transparency_mask */
+ NULL, /* end_transparency_mask */
+ NULL, /* discard_transparency_layer */
+ NULL, /* get_color_mapping_procs */
+ NULL, /* get_color_comp_index */
+ NULL, /* encode_color */
+ NULL, /* decode_color */
+ NULL, /* pattern manager */
+ NULL, /* fill_rectangle_hl_color */
+ NULL, /* include_color_space */
+ NULL, /* fill_linear_color_scanline */
+ NULL, /* fill_linear_color_trapezoid */
+ NULL, /* fill_linear_color_triangle */
+ NULL, /* update_spot_equivalent_colors */
+ NULL, /* ret_devn_params */
+ NULL, /* fillpage */
+ NULL, /* push_transparency_state */
+ NULL, /* pop_transparency_state */
+ NULL, /* put_image */
+ docxwrite_dev_spec_op, /* dev_spec_op */
+ NULL, /* copy_planes */
+ NULL, /* get_profile */
+ NULL, /* set_graphics_type_tag */
+ NULL, /* strip_copy_rop2 */
+ NULL /* strip_tile_rect_devn */
+ },
+ { 0 }, /* Page Data */
+ 0, /* Output FILE * */
+ 0, /* TextFormat */
+ NULL, /* alloc */
+ NULL, /* extract */
+ 0, /* file_per_page */
+ 0.0 /* x */
+};
+
+
+static const gs_param_item_t docx_param_items[] = {
+#define pi(key, type, memb) { key, type, offset_of(gx_device_docxwrite_t, memb) }
+ pi("TextFormat", gs_param_type_int, TextFormat),
+#undef pi
+ gs_param_item_end
+};
+
+/* ---------------- Open/close/page ---------------- */
+
+
+static void *s_extract_realloc_fn(void *state, void *ptr, size_t newsize)
+{
+ /* We have to go to some effort to behave like realloc() when we only have
+ make gs_malloc() and gs_free() available. We store each allocated block's
+ allocation size in the preceding size_t. */
+ gs_memory_t *mem = state;
+ size_t *oldbase = (ptr) ? (size_t*) ptr - 1 : NULL;
+ size_t oldsize = (oldbase) ? *oldbase : 0;
+ size_t *newbase = NULL;
+ if (newsize) {
+ /* malloc() or realloc() - allocate new buffer. */
+ newbase = gs_malloc(mem, sizeof(size_t) + newsize /*nelts*/, 1 /*esize*/, "extract");
+ if (newbase) {
+ *newbase = newsize;
+ if (oldbase) {
+ /* Realloc, so copy across. */
+ size_t minsize = (newsize < oldsize) ? newsize : oldsize;
+ memcpy(newbase+1, oldbase+1, minsize);
+ }
+ }
+ }
+ if (oldbase && (!newsize || newbase)) {
+ /* free() or successful realloc() - free the old buffer. */
+ gs_free(mem, oldbase, sizeof(size_t) + oldsize /*nelts*/, 1 /*esize*/, "extract");
+ }
+ return (newbase) ? newbase + 1 : NULL;
+}
+
+static int s_errno_to_gs(void)
+{
+ if (errno == EPERM) return gs_error_invalidaccess;
+ if (errno == ENOENT) return gs_error_invalidfileaccess;
+ if (errno == ESRCH) {}
+ if (errno == EINTR) {}
+ if (errno == EIO) return gs_error_ioerror;
+ if (errno == ENXIO) {}
+
+ return gs_error_unknownerror;
+}
+
+static int
+docxwrite_open_device(gx_device * dev)
+{
+ gx_device_docxwrite_t * tdev = (gx_device_docxwrite_t *) dev;
+ const char* fmt = NULL;
+ gs_parsed_file_name_t parsed;
+ int code = 0;
+
+ gx_device_fill_in_procs(dev);
+ if (tdev->fname[0] == 0)
+ return_error(gs_error_undefinedfilename);
+
+ tdev->file = NULL;
+ dev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
+ set_linear_color_bits_mask_shift(dev);
+ dev->interpolate_control = 0;
+
+ tdev->alloc = NULL;
+ tdev->extract = NULL;
+
+ code = gx_parse_output_file_name(&parsed, &fmt, tdev->fname, strlen(tdev->fname), tdev->memory);
+ if (code < 0) goto end;
+ tdev->file_per_page = (fmt) ? 1 : 0;
+
+ if (extract_alloc_create(s_extract_realloc_fn, tdev->memory, &tdev->alloc)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ extract_alloc_exp_min(tdev->alloc, 64);
+
+ if (extract_begin(tdev->alloc, &tdev->extract)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ if (extract_page_begin(tdev->extract)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ code = install_internal_subclass_devices((gx_device **)&dev, NULL);
+
+ end:
+
+ if (code < 0) {
+ extract_alloc_destroy(&tdev->alloc);
+ extract_end(&tdev->extract);
+ }
+ return code;
+}
+
+/* For use with an extract_buffer_t - writes directly to tdev->file. */
+static int docxwrite_extract_buffer_write(void* handle, const void* source, size_t numbytes, size_t* o_actual)
+{
+ int n;
+ gx_device_docxwrite_t *tdev = handle;
+ n = gp_fwrite(source, 1 /*size*/, numbytes /*count*/, tdev->file);
+ if (n < 0) return s_errno_to_gs();
+ *o_actual = n;
+ return 0;
+}
+
+/* Finishes processing for page.
+
+If <write_file> is true, we write to file; e.g. set if we are writing a file
+per page, or if we are being called from docxwrite_close_device(). */
+static int
+s_end_page(gx_device_docxwrite_t *tdev, int write_file)
+{
+ int code = 0;
+ extract_buffer_t *buffer = NULL;
+
+ if (!tdev->extract) {
+ /* Nothing to do. */
+ return 0;
+ }
+ if (extract_page_end(tdev->extract)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ if (extract_process(tdev->extract, 0 /*spacing*/, 1 /*rotation*/, 1 /*images*/)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ if (write_file) {
+ code = gx_device_open_output_file((gx_device*) tdev, tdev->fname, true, false, &tdev->file);
+ if (code) goto end;
+ /* extract_write() can only write to an extract_buffer_t, so we create one that
+ writes to tdev->file. */
+ if (extract_buffer_open(
+ tdev->alloc,
+ tdev,
+ NULL /*fn_read*/,
+ docxwrite_extract_buffer_write,
+ NULL /*cache*/,
+ NULL /*fn_close*/,
+ &buffer
+ )) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ if (extract_write(tdev->extract, buffer)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ }
+
+ end:
+ extract_buffer_close(&buffer);
+ if (tdev->file) {
+ gx_device_close_output_file((gx_device*) tdev, tdev->fname, tdev->file);
+ tdev->file = NULL;
+ }
+ return code;
+}
+
+static int
+docxwrite_close_device(gx_device * dev)
+{
+ int code = 0;
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) dev;
+ if (!tdev->file_per_page)
+ {
+ s_end_page(tdev, true /*write_file*/);
+ }
+ extract_end(&tdev->extract);
+ extract_alloc_destroy(&tdev->alloc);
+ return code;
+}
+
+static int
+docxwrite_output_page(gx_device * dev, int num_copies, int flush)
+{
+ int code;
+ gx_device_docxwrite_t *tdev = (gx_device_docxwrite_t *) dev;
+
+ s_end_page(tdev, tdev->file_per_page /*write_file*/);
+
+ if (tdev->file_per_page) {
+ /* Create a new extract_t for the next page. */
+ extract_end(&tdev->extract);
+ if (extract_begin(tdev->alloc, &tdev->extract)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+ }
+ if (extract_page_begin(tdev->extract)) {
+ code = s_errno_to_gs();
+ goto end;
+ }
+
+ code = gx_default_output_page(dev, num_copies, flush);
+ if (code < 0)
+ goto end;
+
+ end:
+ return code;
+}
+
+/* ---------------- Low-level drawing ---------------- */
+
+static int
+docxwrite_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
+ gx_color_index color)
+{
+ return 0;
+}
+
+/*static int
+docxwrite_copy_alpha(gx_device * dev, const byte * data, int data_x,
+ int raster, gx_bitmap_id id, int x, int y, int w, int h,
+ gx_color_index color, int depth)
+{
+ return 0;
+}
+
+static int
+docxwrite_copy_mono(gx_device * dev, const byte * data, int dx, int raster,
+ gx_bitmap_id id, int x, int y, int w, int h,
+ gx_color_index zero, gx_color_index one)
+{
+ return 0;
+}
+static int
+docxwrite_copy_color(gx_device * dev, const byte * data,
+ int data_x, int raster, gx_bitmap_id id,
+ int x, int y, int width, int height)
+{
+ return 0;
+}
+
+static int
+docxwrite_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tiles,
+ int x, int y, int w, int h, gx_color_index color0, gx_color_index color1,
+ int px, int py)
+{
+ return 0;
+}
+
+static int
+docxwrite_strip_copy_rop(gx_device * dev,
+ const byte * sdata, int sourcex, uint sraster,
+ gx_bitmap_id id,
+ const gx_color_index * scolors,
+ const gx_strip_bitmap * textures,
+ const gx_color_index * tcolors,
+ int x, int y, int w, int h,
+ int phase_x, int phase_y, gs_logical_operation_t lop)
+{
+ return 0;
+}*/
+
+/* ---------------- Parameters ---------------- */
+
+static int docxwrite_get_param(gx_device *dev, char *Param, void *list)
+{
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) dev;
+ gs_param_list * plist = (gs_param_list *)list;
+ bool bool_T = true;
+
+ if (strcmp(Param, "OutputFile") == 0) {
+ gs_param_string ofns;
+
+ ofns.data = (const byte *)tdev->fname,
+ ofns.size = strlen(tdev->fname),
+ ofns.persistent = false;
+ return param_write_string(plist, "OutputFile", &ofns);
+ }
+ if (strcmp(Param, "WantsToUnicode") == 0) {
+ return param_write_bool(plist, "WantsToUnicode", &bool_T);
+ }
+ if (strcmp(Param, "PreserveTrMode") == 0) {
+ return param_write_bool(plist, "PreserveTrMode", &bool_T);
+ }
+ if (strcmp(Param, "HighLevelDevice") == 0) {
+ return param_write_bool(plist, "HighLevelDevice", &bool_T);
+ }
+ return_error(gs_error_undefined);
+}
+
+static int
+docxwrite_get_params(gx_device * dev, gs_param_list * plist)
+{
+ int code;
+ bool bool_T = true;
+ gs_param_string ofns;
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) dev;
+
+ code = gx_default_get_params(dev, plist);
+ if (code < 0)
+ return code;
+
+ ofns.data = (const byte *)tdev->fname,
+ ofns.size = strlen(tdev->fname),
+ ofns.persistent = false;
+ code = param_write_string(plist, "OutputFile", &ofns);
+ if (code < 0)
+ return code;
+
+ code = param_write_bool(plist, "WantsToUnicode", &bool_T);
+ if (code < 0)
+ return code;
+
+ code = param_write_bool(plist, "PreserveTrMode", &bool_T);
+ if (code < 0)
+ return code;
+
+ code = param_write_bool(plist, "HighLevelDevice", &bool_T);
+ if (code < 0)
+ return code;
+
+ code = gs_param_write_items(plist, tdev, NULL, docx_param_items);
+ return code;
+}
+
+/* We implement put_params to ensure that we keep the important */
+/* device parameters up to date, and to prevent an /undefined error */
+static int
+docxwrite_put_params(gx_device * dev, gs_param_list * plist)
+{
+ gx_device_docxwrite_t *tdev = (gx_device_docxwrite_t *) dev;
+ int ecode = 0;
+ int code, old_TextFormat = tdev->TextFormat;
+ const char *param_name;
+ gs_param_string ofs;
+ bool dummy, open = dev->is_open;
+
+ switch (code = param_read_string(plist, (param_name = "OutputFile"), &ofs)) {
+ case 0:
+ if (dev->LockSafetyParams &&
+ bytes_compare(ofs.data, ofs.size,
+ (const byte *)tdev->fname, strlen(tdev->fname))) {
+ ecode = gs_note_error(gs_error_invalidaccess);
+ goto ofe;
+ }
+ if (ofs.size >= gp_file_name_sizeof)
+ ecode = gs_error_limitcheck;
+ else
+ break;
+ goto ofe;
+ default:
+ ecode = code;
+ ofe:param_signal_error(plist, param_name, ecode);
+ /* fall through */
+ case 1:
+ ofs.data = 0;
+ break;
+ }
+
+ if (ecode < 0)
+ return ecode;
+
+ code = param_read_int(plist, "TextFormat", &tdev->TextFormat);
+ if (code < 0)
+ return code;
+
+ code = param_read_bool(plist, "WantsToUnicode", &dummy);
+ if (code < 0)
+ return code;
+
+ code = param_read_bool(plist, "HighLevelDevice", &dummy);
+ if (code < 0)
+ return code;
+
+ code = param_read_bool(plist, "PreserveTrMode", &dummy);
+ if (code < 0)
+ return code;
+
+ if (ofs.data != 0) { /* Close the file if it's open. */
+ if (0 && tdev->file != 0) {
+ gp_fclose(tdev->file);
+ tdev->file = 0;
+ outf("have closed tdef->file. tdev=%p", tdev);
+ }
+ memcpy(tdev->fname, ofs.data, ofs.size);
+ tdev->fname[ofs.size] = 0;
+ }
+
+ /* If we change media size then gs_default_put_params will close
+ * the device if it is open. We don't want it to do that, so set
+ * the device's 'is_open' flag to false, and reset it after we've
+ * processed the params.
+ */
+ if (old_TextFormat == tdev->TextFormat && open)
+ dev->is_open = false;
+
+ code = gx_default_put_params(dev, plist);
+ if (code < 0)
+ return code;
+
+ dev->is_open = open;
+
+ dev->interpolate_control = 0;
+
+ return 0;
+}
+
+/* ---------------- Polygon drawing ---------------- */
+
+/*static int
+docxwrite_fill_trapezoid(gx_device * dev,
+ const gs_fixed_edge * left, const gs_fixed_edge * right,
+ fixed ybot, fixed ytop, bool swap_axes,
+ const gx_device_color * pdevc, gs_logical_operation_t lop)
+{
+ return 0;
+}
+
+static int
+docxwrite_fill_parallelogram(gx_device * dev,
+ fixed px, fixed py, fixed ax, fixed ay,
+ fixed bx, fixed by, const gx_device_color * pdevc,
+ gs_logical_operation_t lop)
+{
+ return 0;
+}
+
+static int
+docxwrite_fill_triangle(gx_device * dev,
+ fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
+ const gx_device_color * pdevc, gs_logical_operation_t lop)
+{
+ return 0;
+}
+
+static int
+docxwrite_draw_thin_line(gx_device * dev,
+ fixed fx0, fixed fy0, fixed fx1, fixed fy1,
+ const gx_device_color * pdevc, gs_logical_operation_t lop,
+ fixed adjustx, fixed adjusty)
+{
+ return 0;
+}*/
+
+/* ---------------- High-level drawing ---------------- */
+
+static int
+docxwrite_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
+ const gx_fill_params * params, const gx_device_color * pdevc,
+ const gx_clip_path * pcpath)
+{
+ return 0;
+}
+
+static int
+docxwrite_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
+ const gx_stroke_params * params,
+ const gx_drawing_color * pdevc, const gx_clip_path * pcpath)
+{
+ return 0;
+}
+
+
+/*
+ * Compute the cached values in the text processing state from the text
+ * parameters, current_font, and pgs->ctm. Return either an error code (<
+ * 0) or a mask of operation attributes that the caller must emulate.
+ * Currently the only such attributes are TEXT_ADD_TO_ALL_WIDTHS and
+ * TEXT_ADD_TO_SPACE_WIDTH. Note that this procedure fills in all the
+ * values in ppts->values, not just the ones that need to be set now.
+ */
+static int
+transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat,
+ gs_point *ppt)
+{
+ int code = gs_distance_transform_inverse(pdelta->x, pdelta->y, pmat, ppt);
+ gs_point delta;
+
+ if (code < 0)
+ return code;
+ if (ppt->y == 0)
+ return 0;
+ /* Check for numerical fuzz. */
+ code = gs_distance_transform(ppt->x, 0.0, pmat, &delta);
+ if (code < 0)
+ return 0; /* punt */
+ if (fabs(delta.x - pdelta->x) < 0.01 && fabs(delta.y - pdelta->y) < 0.01) {
+ /* Close enough to y == 0: device space error < 0.01 pixel. */
+ ppt->y = 0;
+ }
+ return 0;
+}
+
+static int
+docx_update_text_state(docx_list_entry_t *ppts,
+ const docxw_text_enum_t *penum,
+ gs_font *ofont, const gs_matrix *pfmat)
+{
+ gx_device *const pdev = penum->dev;
+ gs_font *font = penum->current_font;
+ gs_fixed_point cpt;
+ gs_matrix smat, tmat;
+ float size;
+ int mask = 0;
+ int code = gx_path_current_point(penum->path, &cpt);
+
+ if (code < 0)
+ return code;
+
+ size = txt_calculate_text_size(penum->pgs, ofont, pfmat, &smat, &tmat, penum->current_font, pdev);
+ /* Check for spacing parameters we can handle, and transform them. */
+
+ if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ if (penum->current_font->WMode == 0) {
+ gs_point pt;
+
+ code = transform_delta_inverse(&penum->text.delta_all, &smat, &pt);
+ if (code < 0 || pt.y != 0)
+ mask |= TEXT_ADD_TO_ALL_WIDTHS;
+ }
+ else
+ mask |= TEXT_ADD_TO_ALL_WIDTHS;
+ }
+
+ if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
+ gs_point pt;
+
+ code = transform_delta_inverse(&penum->text.delta_space, &smat, &pt);
+ if (code < 0 || pt.y != 0 || penum->text.space.s_char != 32)
+ mask |= TEXT_ADD_TO_SPACE_WIDTH;
+ }
+ /* Store the updated values. */
+
+ tmat.xx /= size;
+ tmat.xy /= size;
+ tmat.yx /= size;
+ tmat.yy /= size;
+ tmat.tx += fixed2float(cpt.x);
+ tmat.ty += fixed2float(cpt.y);
+
+ ppts->size = size;
+ ppts->matrix = tmat;
+ ppts->FontName = (char *)gs_malloc(pdev->memory->stable_memory, 1,
+ font->font_name.size + 1, "txtwrite alloc font name");
+ if (!ppts->FontName)
+ return gs_note_error(gs_error_VMerror);
+ memcpy(ppts->FontName, font->font_name.chars, font->font_name.size + 1);
+
+ if (font->PaintType == 2 && penum->pgs->text_rendering_mode == 0)
+ {
+ gs_gstate *pgs = penum->pgs;
+ gs_font *font = penum->current_font;
+ double scaled_width = font->StrokeWidth != 0 ? font->StrokeWidth : 0.001;
+ double saved_width = pgs->line_params.half_width;
+ /*
+ * See stream_to_text in gdevpdfu.c re the computation of
+ * the scaling value.
+ */
+ double scale = 72.0 / pdev->HWResolution[1];
+
+ if (font->FontMatrix.yy != 0)
+ scaled_width *= fabs(font->orig_FontMatrix.yy) * size * tmat.yy * scale;
+ else
+ scaled_width *= fabs(font->orig_FontMatrix.xy) * size * tmat.xy * scale;
+
+ pgs->line_params.half_width = scaled_width / 2;
+ if (code < 0)
+ return code;
+
+ pgs->line_params.half_width = saved_width;
+ }
+ return (code < 0 ? code : mask);
+}
+
+/* Simple routine to update the current point by the accumulated width of the
+ * text.
+ */
+static int
+docx_shift_text_currentpoint(docxw_text_enum_t *penum, gs_point *wpt)
+{
+ return gs_moveto_aux(penum->pgs, gx_current_path(penum->pgs),
+ fixed2float(penum->origin.x) + wpt->x,
+ fixed2float(penum->origin.y) + wpt->y);
+}
+
+static int font_final(gx_device_docxwrite_t *tdev, docxw_text_enum_t *penum)
+{
+ gs_text_enum_t* pte = (void*) penum;
+ gs_font_base *font_base = (gs_font_base *)pte->current_font;
+ int code;
+
+ penum->d1_width = 0;
+ penum->d1_width_set = false;
+ if (font_base->FontBBox.p.x != font_base->FontBBox.q.x ||
+ font_base->FontBBox.p.y != font_base->FontBBox.q.y) {
+ gs_point p0, p1, p2, p3;
+ gs_matrix m;
+
+ m = ctm_only(pte->pgs);
+ m.tx = m.ty = fixed2float(0);
+ gs_matrix_multiply(&font_base->FontMatrix, &m, &m);
+ gs_point_transform(font_base->FontBBox.p.x, font_base->FontBBox.p.y, &m, &p0);
+ gs_point_transform(font_base->FontBBox.p.x, font_base->FontBBox.q.y, &m, &p1);
+ gs_point_transform(font_base->FontBBox.q.x, font_base->FontBBox.p.y, &m, &p2);
+ gs_point_transform(font_base->FontBBox.q.x, font_base->FontBBox.q.y, &m, &p3);
+ }
+ code = docx_shift_text_currentpoint(penum, &penum->returned.total_width);
+ return code;
+}
+
+
+/* Routines to enumerate each glyph/character code in turn and sent to
+ * extract_add_char().
+ */
+
+static int
+docxwrite_process_cmap_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte)
+{
+ docxw_text_enum_t *const penum = (docxw_text_enum_t *)pte;
+ unsigned int rcode = 0;
+ gs_text_enum_t scan = *(gs_text_enum_t *)pte;
+ int i;
+
+ /* Composite font using a CMap */
+
+ for (i=0; ; ++i) {
+ const char* prevFontName;
+
+ gs_glyph glyph;
+ int font_code, code;
+ gs_font *subfont;
+ gs_char chr;
+ txt_glyph_widths_t widths;
+ gs_matrix m3;
+ gs_point wanted; /* user space */
+ gs_point dpt = {0,0};
+
+ font_code = scan.orig_font->procs.next_char_glyph
+ (&scan, &chr, &glyph);
+
+ subfont = scan.fstack.items[scan.fstack.depth].font;
+
+ if (font_code == 2) {
+ /* end of string */
+ return 0;
+ }
+ if (font_code != 0 && font_code != 1) {
+ /* error */
+ return font_code;
+ }
+
+ if (font_code == 1) {
+ /* font change */
+ if (i) abort();
+ }
+
+ code = txt_glyph_widths(subfont, scan.orig_font->WMode, glyph, (gs_font *)subfont, &widths,
+ penum->cdevproc_callout ? penum->cdevproc_result : NULL);
+ if (code == TEXT_PROCESS_CDEVPROC) {
+ penum->cdevproc_callout = true;
+ pte->returned.current_glyph = glyph;
+ scan.returned.current_glyph = glyph;
+ pte->current_font = subfont;
+ scan.current_font = subfont;
+ rcode = TEXT_PROCESS_CDEVPROC;
+ break;
+ }
+ else {
+ penum->cdevproc_callout = false;
+ pte->index = scan.index;
+ }
+ code = gs_matrix_multiply(&subfont->FontMatrix, &pte->orig_font->FontMatrix, &m3);
+ if (code < 0) {
+ outf("returning code=%i", code);
+ return code;
+ }
+ prevFontName = penum->text_state->FontName;
+ code = docx_update_text_state(penum->text_state, (docxw_text_enum_t *)pte, subfont, &m3);
+ if (code < 0) {
+ outf("returning code=%i", code);
+ return code;
+ }
+ if (!prevFontName && penum->text_state->FontName) {
+
+ tdev->x = fixed2float(penum->origin.x) - penum->text_state->matrix.tx;
+
+ if (extract_span_begin(
+ tdev->extract,
+ penum->text_state->FontName,
+ 0 /*font_bold*/,
+ 0 /*font_italic*/,
+ penum->text_state->wmode,
+ penum->text_state->matrix.xx,
+ penum->text_state->matrix.xy,
+ penum->text_state->matrix.yx,
+ penum->text_state->matrix.yy,
+ penum->text_state->matrix.tx,
+ penum->text_state->matrix.ty,
+ penum->text_state->size,
+ 0.0f,
+ 0.0f,
+ penum->text_state->size,
+ 0.0f,
+ 0.0f
+ )) {
+ return s_errno_to_gs();
+ }
+ }
+ txt_char_widths_to_uts(pte->orig_font, &widths); /* convert design->text space */
+ gs_distance_transform(widths.real_width.xy.x * penum->text_state->size,
+ widths.real_width.xy.y * penum->text_state->size,
+ &penum->text_state->matrix, &wanted);
+ pte->returned.total_width.x += wanted.x;
+ pte->returned.total_width.y += wanted.y;
+
+ {
+ unsigned short buffer[4];
+ float glyph_width = widths.real_width.xy.x * penum->text_state->size;
+
+ if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
+ &ctm_only(pte->pgs), &tpt);
+ dpt.x += tpt.x;
+ dpt.y += tpt.y;
+ }
+ if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH && chr == pte->text.space.s_char) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
+ &ctm_only(pte->pgs), &tpt);
+ dpt.x += tpt.x;
+ dpt.y += tpt.y;
+ }
+ pte->returned.total_width.x += dpt.x;
+ pte->returned.total_width.y += dpt.y;
+
+ glyph_width += dpt.x;
+
+ /* We can get up to 4 Unicode points per glyph, and a glyph can be
+ * be represented by as little as one byte. So we make a very large
+ * temporary buffer to hold the Unicode string as we assemble it. When
+ * we copy it to the text fragment we will allocate only as many bytes
+ * as are required to hold the actual nukmber of Unicode values we
+ * decoded, and this temporary buffer will be discarded.
+ */
+
+ txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, chr, &buffer[0]);
+
+ if (extract_add_char(
+ tdev->extract,
+ tdev->x,
+ fixed2float(penum->origin.y) - penum->text_state->matrix.ty,
+ buffer[0] /*ucs*/,
+ glyph_width / penum->text_state->size /*adv*/,
+ 0 /*autosplit*/
+ )) {
+ return s_errno_to_gs();
+ }
+ }
+
+ tdev->x += widths.real_width.xy.x * penum->text_state->size;
+
+ if (rcode || pte->index >= pte->text.size)
+ break;
+ }
+ if (!rcode) rcode = font_final(tdev, penum);
+ return rcode;
+}
+
+static int
+docxwrite_process_plain_text(gx_device_docxwrite_t *tdev, gs_text_enum_t *pte)
+{
+ /* one byte regular font */
+ docxw_text_enum_t *const penum = (docxw_text_enum_t *)pte;
+ gs_font *font = pte->orig_font;
+ const gs_glyph *gdata = NULL;
+ gs_glyph glyph;
+ gs_char ch = 0;
+ int i, code;
+ uint operation = pte->text.operation;
+ txt_glyph_widths_t widths;
+ gs_point wanted; /* user space */
+
+ for (i=pte->index;i<pte->text.size;i++) {
+ const char* prevFontName;
+ float span_delta_x;
+ float glyph_width;
+ unsigned short chr2[4];
+
+ gs_point dpt = {0,0};
+ if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) {
+ ch = pte->text.data.bytes[pte->index];
+ } else if (operation & (TEXT_FROM_CHARS | TEXT_FROM_SINGLE_CHAR)) {
+ ch = pte->text.data.chars[pte->index];
+ } else if (operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH)) {
+ if (operation & TEXT_FROM_GLYPHS) {
+ gdata = pte->text.data.glyphs + (pte->index++ * sizeof (gs_glyph));
+ } else {
+ gdata = &pte->text.data.d_glyph;
+ }
+ }
+ glyph = (gdata == NULL ? pte->orig_font->procs.encode_char(pte->orig_font, ch, GLYPH_SPACE_NAME)
+ : *gdata);
+
+ code = txt_glyph_widths(font, font->WMode, glyph, (gs_font *)font, &widths, NULL);
+ if (code < 0) {
+ if (penum->d1_width_set) {
+ widths.Width.w = widths.Width.xy.x = widths.real_width.w = widths.real_width.xy.x = penum->d1_width;
+ penum->d1_width = 0;
+ penum->d1_width_set = 0;
+ }
+ else
+ return code;
+ }
+
+ prevFontName = penum->text_state->FontName;
+ penum->cdevproc_callout = false;
+ code = docx_update_text_state(penum->text_state, (docxw_text_enum_t *)pte, pte->orig_font, &font->FontMatrix);
+ if (code < 0)
+ return code;
+
+ if (!prevFontName && penum->text_state->FontName) {
+
+ tdev->x = fixed2float(penum->origin.x) - penum->text_state->matrix.tx;
+
+ if (extract_span_begin(
+ tdev->extract,
+ penum->text_state->FontName,
+ 0 /*font_bold*/,
+ 0 /*font_italic*/,
+ penum->text_state->wmode,
+ penum->text_state->matrix.xx,
+ penum->text_state->matrix.xy,
+ penum->text_state->matrix.yx,
+ penum->text_state->matrix.yy,
+ penum->text_state->matrix.tx,
+ penum->text_state->matrix.ty,
+ penum->text_state->size,
+ 0.0f,
+ 0.0f,
+ penum->text_state->size,
+ 0.0f,
+ 0.0f
+ )) {
+ return s_errno_to_gs();
+ }
+ }
+ txt_char_widths_to_uts(pte->orig_font, &widths); /* convert design->text space */
+ gs_distance_transform(widths.real_width.xy.x * penum->text_state->size,
+ widths.real_width.xy.y * penum->text_state->size,
+ &penum->text_state->matrix, &wanted);
+ pte->returned.total_width.x += wanted.x;
+ pte->returned.total_width.y += wanted.y;
+ span_delta_x = widths.real_width.xy.x * penum->text_state->size;
+ glyph_width = widths.real_width.xy.x * penum->text_state->size;
+
+ if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_all.x, pte->text.delta_all.y,
+ &ctm_only(pte->pgs), &tpt);
+ dpt.x += tpt.x;
+ dpt.y += tpt.y;
+ }
+ if (pte->text.operation & TEXT_ADD_TO_SPACE_WIDTH && ch == pte->text.space.s_char) {
+ gs_point tpt;
+
+ gs_distance_transform(pte->text.delta_space.x, pte->text.delta_space.y,
+ &ctm_only(pte->pgs), &tpt);
+ dpt.x += tpt.x;
+ dpt.y += tpt.y;
+ }
+ pte->returned.total_width.x += dpt.x;
+ pte->returned.total_width.y += dpt.y;
+
+ span_delta_x += dpt.x;
+
+ code = txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, ch, &chr2[0]);
+ /* If a single text code returned multiple Unicode values, then we need to set the
+ * 'extra' code points' widths to 0.
+ */
+
+ if (extract_add_char(
+ tdev->extract,
+ tdev->x,
+ fixed2float(penum->origin.y) - penum->text_state->matrix.ty,
+ chr2[0] /*ucs*/,
+ glyph_width / penum->text_state->size /*adv*/,
+ 0 /*autosplit*/
+ )) {
+ return s_errno_to_gs();
+ }
+ tdev->x += span_delta_x;
+ pte->index++;
+ }
+ code = 0;
+ if (!code) code = font_final(tdev, penum);
+
+ return code;
+}
+
+/* This routine selects whether the text needs to be handled as regular glyphs
+ * and character codes, or as CIDs, depending on the font type. This is required
+ * because there are ways that regular text can be handled that aren't possible
+ * with CIDFonts.
+ */
+static int
+textw_text_process(gs_text_enum_t *pte)
+{
+ docxw_text_enum_t *const penum = (docxw_text_enum_t *)pte;
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) pte->dev;
+ gs_font *font = pte->orig_font;
+ int code = 0;
+ gs_text_enum_t *pte_fallback;
+
+ if (pte->text.size == 0)
+ return 0;
+
+ pte_fallback = penum->pte_fallback;
+ if (pte_fallback) {
+ code = gx_default_text_restore_state(pte_fallback);
+ if (code < 0)
+ return code;
+ gs_text_release(NULL, pte_fallback, "docxwrite_text_process");
+ }
+ pte_fallback = penum->pte_fallback = NULL;
+
+ {
+ switch (font->FontType) {
+ case ft_CID_encrypted:
+ case ft_CID_TrueType:
+ case ft_composite:
+ code = docxwrite_process_cmap_text(tdev, pte);
+ break;
+ case ft_encrypted:
+ case ft_encrypted2:
+ case ft_TrueType:
+ case ft_user_defined:
+ case ft_PCL_user_defined:
+ case ft_GL2_stick_user_defined:
+ case ft_GL2_531:
+ code = docxwrite_process_plain_text(tdev, pte);
+ break;
+ default:
+ return_error(gs_error_rangecheck);
+ break;
+ }
+ if (code != 0) {
+ if (code == gs_error_unregistered) /* Debug purpose only. */
+ return code;
+ if (code == gs_error_VMerror)
+ return code;
+ if (code == gs_error_invalidfont) /* Bug 688370. */
+ return code;
+ /* Fall back to the default implementation. */
+ code = gx_default_text_begin(pte->dev, pte->pgs, &pte->text, pte->current_font,
+ pte->path, pte->pdcolor, pte->pcpath, pte->memory, &pte_fallback);
+ if (code < 0)
+ return code;
+ penum->pte_fallback = pte_fallback;
+ gs_text_enum_copy_dynamic(pte_fallback, pte, false);
+
+ code = gs_text_process(pte_fallback);
+ if (code != 0) {
+ penum->returned.current_char = pte_fallback->returned.current_char;
+ penum->returned.current_glyph = pte_fallback->returned.current_glyph;
+ return code;
+ }
+ gs_text_release(NULL, pte_fallback, "docxwrite_text_process");
+ penum->pte_fallback = 0;
+ }
+ }
+ return code;
+}
+
+/* Begin processing text. */
+
+/* Define the auxiliary procedures for text processing. */
+static int
+textw_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
+{
+ return gs_text_resync(pte, pfrom);
+}
+static bool
+textw_text_is_width_only(const gs_text_enum_t *pte)
+{
+ return false;
+}
+static int
+textw_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
+{
+ return gs_text_current_width(pte, pwidth);
+}
+static int
+textw_text_set_cache(gs_text_enum_t *pte, const double *pw,
+ gs_text_cache_control_t control)
+{
+ docxw_text_enum_t *const penum = (docxw_text_enum_t *)pte;
+
+ switch (control) {
+ case TEXT_SET_CHAR_WIDTH:
+ case TEXT_SET_CACHE_DEVICE:
+ if (penum->pte_fallback != NULL) {
+ penum->d1_width = *pw;
+ penum->d1_width_set = true;
+ return 0;
+ }
+ return gs_text_set_cache(pte, pw, control);
+ case TEXT_SET_CACHE_DEVICE2:
+ if (penum->cdevproc_callout) {
+ memcpy(penum->cdevproc_result, pw, sizeof(penum->cdevproc_result));
+ return 0;
+ }
+ return gs_text_set_cache(pte, pw, control);
+ default:
+ return_error(gs_error_rangecheck);
+ }
+ return 0;
+}
+
+static int
+textw_text_retry(gs_text_enum_t *pte)
+{
+ return gs_text_retry(pte);
+}
+static void
+textw_text_release(gs_text_enum_t *pte, client_name_t cname)
+{
+ docxw_text_enum_t *const penum = (docxw_text_enum_t *)pte;
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) pte->dev;
+
+ /* If this is copied away when we complete the text enumeration succesfully, then
+ * we set the pointer to NULL, if we get here with it non-NULL , then there was
+ * an error.
+ */
+ if (penum->text_state)
+ gs_free(tdev->memory, penum->text_state, 1, sizeof(penum->text_state), "txtwrite free text state");
+
+ gs_text_release(NULL, pte, cname);
+}
+
+/* This is the list of methods for the text enumerator */
+static const gs_text_enum_procs_t textw_text_procs = {
+ textw_text_resync, textw_text_process,
+ textw_text_is_width_only, textw_text_current_width,
+ textw_text_set_cache, textw_text_retry,
+ textw_text_release
+};
+
+/* This device method gets called by the interpreter to deal with text. It
+ * must create a text enumerator, which contains the methods for dealing with
+ * the text itself. The interpreter will use the enumerator methods to deal with
+ * the text, it won't refer to the device methods again for this text.
+ */
+static int
+docxwrite_text_begin(gx_device * dev, gs_gstate * pgs,
+ const gs_text_params_t * text, gs_font * font,
+ gx_path * path, const gx_device_color * pdcolor,
+ const gx_clip_path * pcpath,
+ gs_memory_t * mem, gs_text_enum_t ** ppenum)
+{
+ gx_device_docxwrite_t *const tdev = (gx_device_docxwrite_t *) dev;
+ docxw_text_enum_t *penum;
+ int code;
+
+ /* If this is a stringwidth, we must let the default graphics library code handle it
+ * in case there is no current point (this can happen if this is the first operation
+ * we get, the current font is a CIDFont, and its descendant is a substitute type 1
+ * font). If there is no current point we throw an error in text_process and that
+ * messes up all the font handling. The test below is copied from pdfwrite
+ * (gdev_pdf_text_begin) and seems to do the job.
+ */
+ if ((!(text->operation & TEXT_DO_DRAW) && pgs->text_rendering_mode != 3)
+ || path == 0 || !path_position_valid(path))
+ return gx_default_text_begin(dev, pgs, text, font, path, pdcolor,
+ pcpath, mem, ppenum);
+ /* Allocate and initialize one of our text enumerators. */
+ rc_alloc_struct_1(penum, docxw_text_enum_t, &st_textw_text_enum, mem,
+ return_error(gs_error_VMerror), "gdev_textw_text_begin");
+ penum->rc.free = rc_free_text_enum;
+ penum->charproc_accum = false;
+ penum->cdevproc_callout = false;
+ penum->returned.total_width.x = penum->returned.total_width.y = 0;
+ penum->pte_fallback = NULL;
+ penum->d1_width = 0;
+ penum->d1_width_set = false;
+ /* The enumerator's text_release method frees this memory */
+ penum->text_state = (docx_list_entry_t *)gs_malloc(tdev->memory->stable_memory, 1,
+ sizeof(docx_list_entry_t), "txtwrite alloc text state");
+ if (!penum->text_state)
+ return gs_note_error(gs_error_VMerror);
+ memset(penum->text_state, 0x00, sizeof(docx_list_entry_t));
+
+ code = gs_text_enum_init((gs_text_enum_t *)penum, &textw_text_procs,
+ dev, pgs, text, font, path, pdcolor, pcpath, mem);
+ if (code < 0) {
+ /* Belt and braces; I'm not certain this is required, but its safe */
+ gs_free(tdev->memory, penum->text_state, 1, sizeof(docx_list_entry_t), "txtwrite free text state");
+ penum->text_state = NULL;
+ gs_free_object(mem, penum, "textwrite_text_begin");
+ return code;
+ }
+
+ code = gx_path_current_point(penum->path, &penum->origin);
+ if (code != 0)
+ return code;
+
+ *ppenum = (gs_text_enum_t *)penum;
+
+ return 0;
+}
+
+static int
+docxwrite_strip_copy_rop(gx_device * dev,
+ const byte * sdata, int sourcex, uint sraster,
+ gx_bitmap_id id,
+ const gx_color_index * scolors,
+ const gx_strip_bitmap * textures,
+ const gx_color_index * tcolors,
+ int x, int y, int w, int h,
+ int phase_x, int phase_y, gs_logical_operation_t lop)
+{
+ return 0;
+}
+
+int
+docxwrite_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
+{
+ switch (dev_spec_op) {
+ case gxdso_get_dev_param:
+ {
+ int code;
+ dev_param_req_t *request = (dev_param_req_t *)data;
+ code = docxwrite_get_param(pdev, request->Param, request->list);
+ if (code != gs_error_undefined)
+ return code;
+ }
+ }
+ return gx_default_dev_spec_op(pdev, dev_spec_op, data, size);
+}
diff --git a/devices/vector/gdevpdf.c b/devices/vector/gdevpdf.c
index 6752fabb..35dc6dc2 100644
--- a/devices/vector/gdevpdf.c
+++ b/devices/vector/gdevpdf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -38,6 +38,8 @@
#include "gxfcache.h"
#include "gdevpdts.h" /* for sync_text_state */
+#include "gdevpdfo.h"
+
/* Define the default language level and PDF compatibility level. */
/* Acrobat 8 (PDF 1.7) is the default. (1.7 for ICC V4.2.0 profile support) */
#define PSDF_VERSION_INITIAL psdf_version_ll3
@@ -1090,11 +1092,18 @@ round_box_coord(double xy)
static int
pdf_write_page(gx_device_pdf *pdev, int page_num)
{
- long page_id = pdf_page_id(pdev, page_num);
- pdf_page_t *page = &pdev->pages[page_num - 1];
+ long page_id;
+ pdf_page_t *page;
double mediabox[4] = {0, 0};
stream *s;
- const cos_value_t *v_mediabox = cos_dict_find_c_key(page->Page, "/MediaBox");
+ const cos_value_t *v_mediabox;
+
+ if (pdev->pages == NULL)
+ return_error(gs_error_undefined);
+
+ page = &pdev->pages[page_num - 1];
+ v_mediabox = cos_dict_find_c_key(page->Page, "/MediaBox");
+ page_id = pdf_page_id(pdev, page_num);
/* If we have not been given a MediaBox overriding pdfmark, use the current media size. */
s = pdev->strm;
@@ -1383,8 +1392,29 @@ pdf_write_page(gx_device_pdf *pdev, int page_num)
/* Write the annotations array if any. */
if (page->Annots) {
+ const cos_value_t *value = NULL;
+ const cos_array_element_t *e = NULL, *next = NULL;
+ long index = 0;
+
stream_puts(s, "/Annots");
COS_WRITE(page->Annots, pdev);
+ /* More complications caused by cos objects. Simply calling COS_FREE
+ * will free the array, but it won't free the elements of the array
+ * if they have non-zero IDs (see the comments regarding cleanup of
+ * resources in pdf_close at around line 1090 below). Because we've
+ * already written out the annotations, the dictionary contents have
+ * already been freed, but we need the IDs until this point when we
+ * write out the array in the page dictionary. So after using them,
+ * we must go through the array and set the ids to 0 so that COS_FREE
+ * will free the array elements as well as the array itself.
+ */
+ e = cos_array_element_first(page->Annots);
+ while (e != NULL) {
+ next = cos_array_element_next(e, &index, &value);
+ if (value->contents.object != NULL)
+ value->contents.object->id = 0;
+ e = next;
+ }
COS_FREE(page->Annots, "pdf_write_page(Annots)");
page->Annots = 0;
}
@@ -2554,10 +2584,10 @@ pdf_close(gx_device * dev)
{
gx_device_pdf *const pdev = (gx_device_pdf *) dev;
gs_memory_t *mem = pdev->pdf_memory;
- stream *s;
+ stream *s = NULL;
gp_file *tfile = pdev->xref.file;
gs_offset_t xref = 0;
- gs_offset_t resource_pos;
+ gs_offset_t resource_pos = 0;
long Catalog_id = 0, Info_id = 0,
Pages_id = 0, Encrypt_id = 0;
long Threads_id = 0;
@@ -2569,12 +2599,15 @@ pdf_close(gx_device * dev)
bool file_per_page = false;
if (!dev->is_open)
- return_error(gs_error_undefined);
+ return_error(gs_error_undefined);
dev->is_open = false;
- Catalog_id = pdev->Catalog->id;
- Info_id = pdev->Info->id;
- Pages_id = pdev->Pages->id;
+ if (pdev->Catalog)
+ Catalog_id = pdev->Catalog->id;
+ if (pdev->Info)
+ Info_id = pdev->Info->id;
+ if (pdev->Pages)
+ Pages_id = pdev->Pages->id;
memset(&linear_params, 0x00, sizeof(linear_params));
linear_params.Info_id = Info_id;
@@ -2681,7 +2714,7 @@ pdf_close(gx_device * dev)
}
/* Create the Pages tree. */
- if (!(pdev->ForOPDFRead && pdev->ProduceDSC)) {
+ if (!(pdev->ForOPDFRead && pdev->ProduceDSC) && pdev->strm != NULL) {
pdf_open_obj(pdev, Pages_id, resourcePagesTree);
pdf_record_usage(pdev, Pages_id, resource_usage_part9_structure);
@@ -2724,7 +2757,7 @@ pdf_close(gx_device * dev)
if (code >= 0)
code = code1;
pdf_open_obj(pdev, pdev->outlines_id, resourceOutline);
- pprintd1(s, "<< /Count %d", pdev->outlines_open);
+ pprintd1(s, "<< /Type /Outlines /Count %d", pdev->outlines_open);
pprintld2(s, " /First %ld 0 R /Last %ld 0 R >>\n",
pdev->outline_levels[0].first.id,
pdev->outline_levels[0].last.id);
@@ -2844,7 +2877,8 @@ pdf_close(gx_device * dev)
pdf_record_usage(pdev, pdev->Info->id, resource_usage_part9_structure);
} else {
- pdev->Info->id = 0; /* Don't write Info dict for DSC PostScript */
+ if (pdev->Info != NULL)
+ pdev->Info->id = 0; /* Don't write Info dict for DSC PostScript */
}
/*
* Write the definitions of the named objects.
@@ -2852,10 +2886,13 @@ pdf_close(gx_device * dev)
* XObjects, and images named by NI.
*/
- do {
- cos_dict_objects_write(pdev->local_named_objects, pdev);
- } while (pdf_pop_namespace(pdev) >= 0);
- cos_dict_objects_write(pdev->global_named_objects, pdev);
+ if(pdev->local_named_objects != NULL) {
+ do {
+ cos_dict_objects_write(pdev->local_named_objects, pdev);
+ } while (pdf_pop_namespace(pdev) >= 0);
+ }
+ if (pdev->global_named_objects != NULL)
+ cos_dict_objects_write(pdev->global_named_objects, pdev);
if (pdev->ForOPDFRead && pdev->ProduceDSC) {
int pages;
@@ -2870,20 +2907,22 @@ pdf_close(gx_device * dev)
/* Copy the resources into the main file. */
- s = pdev->strm;
- resource_pos = stell(s);
- sflush(pdev->asides.strm);
- {
- gp_file *rfile = pdev->asides.file;
- int64_t res_end = gp_ftell(rfile);
+ if (pdev->strm != NULL) {
+ s = pdev->strm;
+ resource_pos = stell(s);
+ sflush(pdev->asides.strm);
+ {
+ gp_file *rfile = pdev->asides.file;
+ int64_t res_end = gp_ftell(rfile);
- gp_fseek(rfile, 0L, SEEK_SET);
- code1 = pdf_copy_data(s, rfile, res_end, NULL);
- if (code >= 0)
- code = code1;
+ gp_fseek(rfile, 0L, SEEK_SET);
+ code1 = pdf_copy_data(s, rfile, res_end, NULL);
+ if (code >= 0)
+ code = code1;
+ }
}
- if (pdev->ForOPDFRead && pdev->ProduceDSC) {
+ if (pdev->ForOPDFRead && pdev->ProduceDSC && s != NULL) {
int j;
pagecount = 1;
@@ -2959,7 +2998,7 @@ pdf_close(gx_device * dev)
memset(linear_params.Offsets, 0x00, linear_params.LastResource * sizeof(gs_offset_t));
}
- if (!(pdev->ForOPDFRead && pdev->ProduceDSC)) {
+ if (!(pdev->ForOPDFRead && pdev->ProduceDSC) && pdev->strm != NULL) {
/* Write Encrypt. */
if (pdev->OwnerPassword.size > 0) {
Encrypt_id = pdf_obj_ref(pdev);
@@ -3037,7 +3076,7 @@ pdf_close(gx_device * dev)
}
}
- if (pdev->Linearise) {
+ if (pdev->Linearise && pdev->strm != NULL) {
int i;
code = pdf_linearise(pdev, &linear_params);
@@ -3055,13 +3094,13 @@ pdf_close(gx_device * dev)
*/
/* Memory management of resources in pdfwrite is bizarre and complex. Originally there was no means
- * to free any resorucesw on completionj, pdfwrite simply relied on the garbage collector to clean up
+ * to free any resources on completion, pdfwrite simply relied on the garbage collector to clean up
* and all the resource objects are GC-visible. However, this doesn't work well when the interpreter
* does not use GC, ie PCL or XPS, and even when GC is available, the time taken to clean up the
* (sometimes enormous numbers) of objects can be surprisingly significant. So code was added above
- * to handle the simple cases useing pdf_free_resource_object(), and below to handle the more complex
+ * to handle the simple cases using pdf_free_resource_object(), and below to handle the more complex
* situations.
- * The way this works is that for each resrouce type we free the 'object', if the object is itself
+ * The way this works is that for each resource type we free the 'object', if the object is itself
* a 'cos' object (array, dictionary) then we free each of its members. However, if any of the objects
* have an ID which is not zero, then we don't free them (this is true only for contents, all the
* objects of a given type are freed regardless of whether their ID is 0). These are taken to be
@@ -3069,7 +3108,7 @@ pdf_close(gx_device * dev)
* that resource type is freed. For the simple resources, which is most of them, this works well.
*
* However, there are complications; colour spaces and functions can contain cos objects
- * whose members pointers to other objects of the same resoruce type (eg a type 3 stitching function
+ * whose members pointers to other objects of the same resource type (eg a type 3 stitching function
* can point to an array of type 0 functions). We can't afford to have these free the object, because
* the resource chain is still pointing at it, and will try to free it again. The same is also true if
* we should encounter the object which is referenced before we find the reference. So for these cases
@@ -3087,11 +3126,11 @@ pdf_close(gx_device * dev)
* There is a 'gotcha' here; previously we used to free the 'resourceOther' resources *before* calling
* pdf_document_metadata(), now we call it after. The problem is that the metadata is stored as a resourceOther
* resource *and* referenced from the Catalog dictionary, which is a 'global named resource'. We free global
- * named resoruces as the absolute last action. Previously because we had free resourceOther resoruces before
+ * named resoruces as the absolute last action. Previously because we had free resourceOther resources before
* creating the new reference to the Metadata, the fact that it was freed by the action of releasing the
* global named resources wasn't a problem, now it is. If we free the metadata as a 'resourceOther' then when
* we try to free it as a global named resource we will run into trouble again. So pdf_document_metadata() has been
- * specifally altered to remove the reference to the metadata from the resourceOther resource chain immediately
+ * specifically altered to remove the reference to the metadata from the resourceOther resource chain immediately
* after it has been created. Ick.....
*/
{
@@ -3170,7 +3209,7 @@ pdf_close(gx_device * dev)
for (; pres != 0;) {
if (pres->object) {
- gs_free_object(pdev->pdf_memory, (byte *)pres->object, "Free CharProc");
+ cos_free(pres->object, "free CharProc resource");
pres->object = 0;
}
pres = pres->next;
@@ -3366,23 +3405,30 @@ pdf_close(gx_device * dev)
/* Free named objects. */
- cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack");
- gs_free_object(mem, pdev->NI_stack, "Free Name Index stack");
- pdev->NI_stack = 0;
+ if (pdev->NI_stack != NULL) {
+ cos_release((cos_object_t *)pdev->NI_stack, "Release Name Index stack");
+ gs_free_object(mem, pdev->NI_stack, "Free Name Index stack");
+ pdev->NI_stack = 0;
+ }
- cos_dict_objects_delete(pdev->local_named_objects);
- COS_FREE(pdev->local_named_objects, "pdf_close(local_named_objects)");
- pdev->local_named_objects = 0;
+ if (pdev->local_named_objects != NULL) {
+ cos_dict_objects_delete(pdev->local_named_objects);
+ COS_FREE(pdev->local_named_objects, "pdf_close(local_named_objects)");
+ pdev->local_named_objects = 0;
+ }
- /* global resources include the Catalog object and apparently the Info dict */
- cos_dict_objects_delete(pdev->global_named_objects);
- COS_FREE(pdev->global_named_objects, "pdf_close(global_named_objects)");
- pdev->global_named_objects = 0;
+ if (pdev->global_named_objects != NULL) {
+ /* global resources include the Catalog object and apparently the Info dict */
+ cos_dict_objects_delete(pdev->global_named_objects);
+ COS_FREE(pdev->global_named_objects, "pdf_close(global_named_objects)");
+ pdev->global_named_objects = 0;
+ }
/* Wrap up. */
pdev->font_cache = 0;
+ if (pdev->pages != NULL)
{
int i;
for (i=0;i < pdev->next_page;i++) {
@@ -3402,24 +3448,32 @@ pdf_close(gx_device * dev)
gs_free_object(mem, pdev->sbstack, "Free sbstack");
pdev->sbstack = 0;
- text_data_free(mem, pdev->text);
+ if (pdev->text != NULL)
+ text_data_free(mem, pdev->text);
pdev->text = 0;
- cos_release((cos_object_t *)pdev->Pages, "release Pages dict");
- gs_free_object(mem, pdev->Pages, "Free Pages dict");
- pdev->Pages = 0;
+ if (pdev->Pages != NULL) {
+ cos_release((cos_object_t *)pdev->Pages, "release Pages dict");
+ gs_free_object(mem, pdev->Pages, "Free Pages dict");
+ pdev->Pages = 0;
+ }
+ if (pdev->vgstack != NULL)
{
int i;
- for (i=0;i < pdev->vgstack_depth;i++)
- gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "pdfwrite final free stored dash in gstate");
+ for (i=0;i < pdev->vgstack_size;i++) {
+ if (pdev->vgstack[i].dash_pattern != NULL)
+ gs_free_object(pdev->memory->non_gc_memory, pdev->vgstack[i].dash_pattern, "pdfwrite final free stored dash in gstate");
+ }
+ gs_free_object(pdev->pdf_memory, pdev->vgstack, "pdf_close(graphics state stack)");
+ pdev->vgstack = 0;
}
- gs_free_object(pdev->pdf_memory, pdev->vgstack, "pdf_close(graphics state stack)");
- pdev->vgstack = 0;
- cos_release((cos_object_t *)pdev->Namespace_stack, "release Name space stack");
- gs_free_object(mem, pdev->Namespace_stack, "Free Name space stack");
- pdev->Namespace_stack = 0;
+ if (pdev->Namespace_stack != NULL) {
+ cos_release((cos_object_t *)pdev->Namespace_stack, "release Name space stack");
+ gs_free_object(mem, pdev->Namespace_stack, "Free Name space stack");
+ pdev->Namespace_stack = 0;
+ }
pdev->Catalog = 0;
pdev->Info = 0;
@@ -3429,6 +3483,7 @@ pdf_close(gx_device * dev)
pdev->outline_depth = -1;
pdev->max_outline_depth = 0;
+ if (s != NULL)
{
/* pdf_open_dcument could set up filters for entire document.
Removing them now. */
diff --git a/devices/vector/gdevpdfb.c b/devices/vector/gdevpdfb.c
index 20339038..a7b36d82 100644
--- a/devices/vector/gdevpdfb.c
+++ b/devices/vector/gdevpdfb.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -496,7 +496,7 @@ gdev_pdf_copy_color(gx_device * dev, const byte * base, int sourcex,
/* Fill a mask. */
int
gdev_pdf_fill_mask(gx_device * dev,
- const byte * data, int data_x, int raster, gx_bitmap_id id,
+ const byte * data, int data_x, int raster, gx_bitmap_id id,
int x, int y, int width, int height,
const gx_drawing_color * pdcolor, int depth,
gs_logical_operation_t lop, const gx_clip_path * pcpath)
@@ -505,6 +505,50 @@ gdev_pdf_fill_mask(gx_device * dev,
if (width <= 0 || height <= 0)
return 0;
+
+ /* If OCRStage is 'OCR_Rendering' then we are handling an image which is a rendered glyph
+ * that we want to have OCR software process and return a Unicode code point for.
+ * We specifically do *not* want to send the image to the output PDF file!
+ */
+ if (pdev->OCRStage == OCR_Rendering) {
+ int code = 0;
+ ocr_glyph_t *new_glyph = NULL;
+ int index;
+
+ new_glyph = (ocr_glyph_t *)gs_alloc_bytes(pdev->pdf_memory, sizeof(ocr_glyph_t), "");
+ if (new_glyph == NULL)
+ return_error(gs_error_VMerror);
+ new_glyph->data = gs_alloc_bytes(pdev->pdf_memory, raster*height, "");
+ if (new_glyph->data == NULL)
+ return_error(gs_error_VMerror);
+ memcpy(new_glyph->data, data, raster * height);
+ new_glyph->height = height;
+ new_glyph->width = width;
+ new_glyph->raster = raster;
+ new_glyph->x = x;
+ new_glyph->y = y;
+ new_glyph->char_code = pdev->OCR_char_code;
+ new_glyph->glyph = pdev->OCR_glyph;
+ new_glyph->next = NULL;
+ new_glyph->is_space = true;
+ for(index = 0; index < height * raster;index++){
+ if(data[index] != 0x00) {
+ new_glyph->is_space = false;
+ break;
+ }
+ }
+ if (pdev->ocr_glyphs == NULL)
+ pdev->ocr_glyphs = new_glyph;
+ else {
+ ocr_glyph_t *next = pdev->ocr_glyphs;
+
+ while (next->next != NULL)
+ next = next->next;
+ next->next = new_glyph;
+ }
+ return code;
+ }
+
if (depth > 1 || (!gx_dc_is_pure(pdcolor) != 0 && !(gx_dc_is_pattern1_color(pdcolor))))
return gx_default_fill_mask(dev, data, data_x, raster, id,
x, y, width, height, pdcolor, depth, lop,
diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h
index 16521e0d..c0c3d220 100644
--- a/devices/vector/gdevpdfb.h
+++ b/devices/vector/gdevpdfb.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -116,11 +116,11 @@ const gx_device_pdf PDF_DEVICE_IDENT =
-1, /* EndPage */
1, /* StartPage */
1 /*true*/, /* Optimize */
- 0 /*false*/, /* ParseDSCCommentsForDocInfo */
+ 1 /*true*/, /* ParseDSCCommentsForDocInfo */
1 /*true*/, /* ParseDSCComments */
0 /*false*/, /* EmitDSCWarnings */
0 /*false*/, /* CreateJobTicket */
- 0 /*false*/, /* PreserveEPSInfo */
+ 1 /*true*/, /* PreserveEPSInfo */
1 /*true*/, /* AutoPositionEPSFiles */
1 /*true*/, /* PreserveCopyPage */
0 /*false*/, /* UsePrologue */
@@ -128,6 +128,8 @@ const gx_device_pdf PDF_DEVICE_IDENT =
{0,0}, /* PDFXTrimBoxToMediaBoxOffset */
{0,0}, /* PDFXBleedBoxToTrimBoxOffset */
1 /* true */, /* PDFXSetBleedBoxToMediaBox */
+ "", /* ocr_language */
+ 0, /* ocr_engine */
1 /*true*/, /* ReAssignCharacters */
1 /*true*/, /* ReEncodeCharacters */
1, /* FirstObjectNumber */
@@ -263,6 +265,7 @@ const gx_device_pdf PDF_DEVICE_IDENT =
0, /* image_mask_id */
0, /* image_mask_is_SMask */
0, /* image_mask_skip */
+ 0, /* smask_construction */
0, /* image_with_SMask */
{0,0,0,0,0,0}, /* gs_matrix converting_image_matrix */
0, /* image_mask_scale */
@@ -283,6 +286,7 @@ const gx_device_pdf PDF_DEVICE_IDENT =
true, /* DetectDuplicateImages */
false, /* AllowIncrementalCFF */
!PDF_FOR_OPDFREAD, /* WantsToUnicode */
+ !PDF_FOR_OPDFREAD, /* PdfmarkCapable */
!PDF_FOR_OPDFREAD, /* WantsPageLabels */
PDF_FOR_OPDFREAD, /* AllowPSRepeatFunctions */
true, /* IsDistiller (true even for ps2write!) */
@@ -298,7 +302,14 @@ const gx_device_pdf PDF_DEVICE_IDENT =
0, /* ExtensionMetadata */
0, /* PDFFormName */
0, /* PassThroughWriter */
- 1.0 /* UserUnit */
+ 1.0, /* UserUnit */
+ 0, /* UseOCR */
+ NULL, /* OCRSaved */
+ 0, /* OCRStage */
+ NULL, /* OCRUnicode */
+ 0, /* OCR_char_code */
+ 0, /* OCR_glyph */
+ NULL /* ocr_glyphs */
};
#else
diff --git a/devices/vector/gdevpdfc.c b/devices/vector/gdevpdfc.c
index 3a3096c4..c573ad84 100644
--- a/devices/vector/gdevpdfc.c
+++ b/devices/vector/gdevpdfc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -527,7 +527,7 @@ pdf_separation_color_space(gx_device_pdf *pdev, const gs_gstate * pgs,
}
if ((code = cos_array_add(pca, cos_c_string_value(&v, csname))) < 0 ||
- (code = cos_array_add_no_copy(pca, snames)) < 0 ||
+ (code = cos_array_add(pca, snames)) < 0 ||
(code = pdf_color_space_named(pdev, pgs, &v, &ranges, alt_space, pcsn, false, NULL, 0, false)) < 0 ||
(code = cos_array_add(pca, &v)) < 0 ||
(code = pdf_function_scaled(pdev, pfn, ranges, &v)) < 0 ||
@@ -1154,9 +1154,13 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
for (i = 0; i < pcs->params.device_n.num_components; ++i) {
name_string = (byte *)pcs->params.device_n.names[i];
name_string_length = strlen(pcs->params.device_n.names[i]);
- if ((code = pdf_string_to_cos_name(pdev, name_string,
- name_string_length, &v)) < 0 ||
- (code = cos_array_add_no_copy(psna, &v)) < 0)
+
+ code = pdf_string_to_cos_name(pdev, name_string, name_string_length, &v);
+ if (code < 0)
+ return code;
+ code = cos_array_add(psna, &v);
+ cos_value_free((const cos_value_t *)&v, pdev->pdf_memory, "pdf_color_space(DeviceN component)");
+ if (code < 0)
return code;
}
COS_OBJECT_VALUE(&v, psna);
@@ -1185,6 +1189,7 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
return gs_note_error(gs_error_typecheck);
}
code = cos_dict_put((cos_dict_t *)pres_attributes->object, (const byte *)"/Subtype", 8, &v_Subtype_name);
+ cos_value_free((const cos_value_t *)&v_Subtype_name, pdev->pdf_memory, "pdf_color_space(Subtype)");
if (code < 0)
return code;
}
@@ -1212,6 +1217,7 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
return code;
code = cos_dict_put(process, v_process_name.contents.chars.data,
v_process_name.contents.chars.size, &v_process_space);
+ cos_value_free((const cos_value_t *)&v_process_name, pdev->pdf_memory, "pdf_color_space(ColorSpace)");
if (code < 0)
return code;
@@ -1229,6 +1235,7 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
if (code < 0)
return code;
code = cos_array_put(components, m, &v_process_name);
+ cos_value_free((const cos_value_t *)&v_process_name, pdev->pdf_memory, "pdf_color_space(process_name)");
if (code < 0)
return code;
}
@@ -1258,6 +1265,7 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
return code;
code = cos_dict_put(colorants, v_colorant_name.contents.chars.data,
v_colorant_name.contents.chars.size, &v_separation);
+ cos_value_free((const cos_value_t *)&v_colorant_name, pdev->pdf_memory, "pdf_color_space(Subtype)");
if (code < 0)
return code;
}
@@ -1270,9 +1278,14 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
va = &v_attributes;
COS_OBJECT_VALUE(va, pres_attributes->object);
}
- if ((code = pdf_separation_color_space(pdev, pgs, pca, "/DeviceN", &v,
+ code = pdf_separation_color_space(pdev, pgs, pca, "/DeviceN", &v,
pcs->base_space,
- pfn, &pdf_color_space_names, va)) < 0)
+ pfn, &pdf_color_space_names, va);
+ if (v.value_type == COS_VALUE_SCALAR)
+ cos_value_free((const cos_value_t *)&v, pdev->pdf_memory, "pdf_color_space(Devicen)");
+ if (va != NULL && va->value_type == COS_VALUE_SCALAR)
+ cos_value_free((const cos_value_t *)&va, pdev->pdf_memory, "pdf_color_space(Devicen)");
+ if (code < 0)
return code;
}
break;
@@ -1285,12 +1298,18 @@ pdf_color_space_named(gx_device_pdf *pdev, const gs_gstate * pgs,
if (pfn == 0)
return_error(gs_error_rangecheck);
{
- if ((code = pdf_string_to_cos_name(pdev, (const byte *)pcs->params.separation.sep_name,
- strlen(pcs->params.separation.sep_name), &v)) < 0 ||
- (code = pdf_separation_color_space(pdev, pgs, pca, "/Separation", &v,
+ code = pdf_string_to_cos_name(pdev, (const byte *)pcs->params.separation.sep_name,
+ strlen(pcs->params.separation.sep_name), &v);
+ if (code < 0)
+ return code;
+
+ code = pdf_separation_color_space(pdev, pgs, pca, "/Separation", &v,
pcs->base_space,
- pfn, &pdf_color_space_names, NULL)) < 0)
- return code;
+ pfn, &pdf_color_space_names, NULL);
+ if (v.value_type == COS_VALUE_SCALAR)
+ cos_value_free((const cos_value_t *)&v, pdev->pdf_memory, "pdf_color_space(Separation name)");
+ if (code < 0)
+ return code;
}
break;
diff --git a/devices/vector/gdevpdfc.h b/devices/vector/gdevpdfc.h
index e9056be3..02a03634 100644
--- a/devices/vector/gdevpdfc.h
+++ b/devices/vector/gdevpdfc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c
index 32a6c41b..32f75555 100644
--- a/devices/vector/gdevpdfd.c
+++ b/devices/vector/gdevpdfd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdfe.c b/devices/vector/gdevpdfe.c
index f9544c5d..e083ee11 100644
--- a/devices/vector/gdevpdfe.c
+++ b/devices/vector/gdevpdfe.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -492,6 +492,7 @@ pdf_xmp_write_translated(gx_device_pdf *pdev, stream *s, const byte *data, int d
if (code < 0)
return code;
write(s, (const byte *)buf1, buf1b - buf1);
+ gs_free_object(pdev->memory, buf1, "pdf_xmp_write_translated");
}
gs_free_object(pdev->memory, buf0, "pdf_xmp_write_translated");
return 0;
@@ -840,8 +841,6 @@ pdf_write_document_metadata(gx_device_pdf *pdev, const byte digest[6])
int
pdf_document_metadata(gx_device_pdf *pdev)
{
- int j;
-
if (pdev->CompatibilityLevel < 1.4)
return 0;
if (cos_dict_find_c_key(pdev->Catalog, "/Metadata"))
@@ -889,33 +888,6 @@ pdf_document_metadata(gx_device_pdf *pdev)
if (code < 0)
return code;
- /* By storing the Metadata in the Catalog dictionary we have referenced it from the
- * 'global named objects', and the object will be freed when we free those objects.
- * We *don't* want it referenced by any resource because if it is then we will free
- * it before we free the global named resources. So remove the Metadata cos_stream
- * object from the resourceOther resource type chains.
- */
- for (j = 0; j < NUM_RESOURCE_CHAINS; ++j) {
- pdf_resource_t *pres1, *head = pdev->resources[resourceOther].chains[j];
-
- pres1 = head;
-
- if (pres1 == pres) {
- pdev->resources[resourceOther].chains[j] = pres1->next;
- break;
- } else {
- while (pres1->next) {
- if (pres1->next == pres) {
- pres1->next = pres->next;
- break;
- }
- if (pres1->next == pres->next)
- break;
-
- pres1 = pres1->next;
- }
- }
- }
}
return 0;
}
diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c
index 39da7ea4..f08acb7c 100644
--- a/devices/vector/gdevpdfg.c
+++ b/devices/vector/gdevpdfg.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -2371,7 +2371,7 @@ pdf_write_spot_function(gx_device_pdf *pdev, const gx_ht_order *porder,
return code;
}
-/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
+/* if (memcmp(order.levels, porder->levels, order.num_levels * sizeof(*order.levels))) */
static int
compare_gx_ht_order_levels(const gx_ht_order *order1, const gx_ht_order *order2) {
int i;
diff --git a/devices/vector/gdevpdfg.h b/devices/vector/gdevpdfg.h
index e9faa670..85e67d9f 100644
--- a/devices/vector/gdevpdfg.h
+++ b/devices/vector/gdevpdfg.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -296,6 +296,8 @@ pdf_complete_image_data(gx_device_pdf *pdev, pdf_image_writer *piw, int data_h,
int pdf_end_image_binary(gx_device_pdf *pdev, pdf_image_writer *piw,
int data_h);
+int pdf_end_abort_image(gx_device_pdf * pdev, pdf_image_writer * piw);
+
/*
* Finish writing an image. If in-line, write the BI/dict/ID/data/EI and
* return 1; if a resource, write the resource definition and return 0.
diff --git a/devices/vector/gdevpdfi.c b/devices/vector/gdevpdfi.c
index c6bdee9d..08e217fa 100644
--- a/devices/vector/gdevpdfi.c
+++ b/devices/vector/gdevpdfi.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -958,6 +958,86 @@ static int setup_image_colorspace(gx_device_pdf *pdev, image_union_t *image, con
return 0;
}
+/* Basically, sets up the BBox for Eps2Write case */
+static int
+pdf_image_handle_eps(gx_device_pdf *pdev, const gs_gstate * pgs,
+ const gs_matrix *pmat, const gs_image_common_t *pic,
+ const gs_int_rect *prect,
+ const gx_clip_path * pcpath)
+{
+ int code = 0;
+ gs_rect sbox, dbox, *Box;
+ gs_point corners[4];
+ gs_fixed_rect ibox;
+ gs_matrix * pmat1 = (gs_matrix *)pmat;
+ gs_matrix mat;
+
+ if (!pdev->Eps2Write)
+ return 0;
+
+ if (!pdev->accumulating_charproc)
+ Box = &pdev->BBox;
+ else
+ Box = &pdev->charproc_BBox;
+ if (pmat1 == 0)
+ pmat1 = (gs_matrix *)&ctm_only(pgs);
+ if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
+ (code = gs_matrix_multiply(&mat, pmat1, &mat)) < 0)
+ goto exit;
+ sbox.p.x = prect->p.x;
+ sbox.p.y = prect->p.y;
+ sbox.q.x = prect->q.x;
+ sbox.q.y = prect->q.y;
+ gs_bbox_transform_only(&sbox, &mat, corners);
+ gs_points_bbox(corners, &dbox);
+ ibox.p.x = float2fixed(dbox.p.x);
+ ibox.p.y = float2fixed(dbox.p.y);
+ ibox.q.x = float2fixed(dbox.q.x);
+ ibox.q.y = float2fixed(dbox.q.y);
+ if (pcpath != NULL &&
+ !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
+ ibox.q.x, ibox.q.y)
+ ) {
+ /* Let the target do the drawing, but drive two triangles */
+ /* through the clipping path to get an accurate bounding box. */
+ gx_device_clip cdev;
+ gx_drawing_color devc;
+
+ fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
+ fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;
+
+ pdev->AccumulatingBBox++;
+ gx_make_clip_device_on_stack(&cdev, pcpath, (gx_device *)pdev);
+ set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev)); /* any non-white color will do */
+ gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
+ float2fixed(corners[1].x) - x0,
+ float2fixed(corners[1].y) - y0,
+ bx2, by2, &devc, lop_default);
+ gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
+ float2fixed(corners[3].x) - x0,
+ float2fixed(corners[3].y) - y0,
+ bx2, by2, &devc, lop_default);
+ pdev->AccumulatingBBox--;
+ } else {
+ /* Just use the bounding box. */
+ float x0, y0, x1, y1;
+ x0 = fixed2float(ibox.p.x) / (pdev->HWResolution[0] / 72.0);
+ y0 = fixed2float(ibox.p.y) / (pdev->HWResolution[1] / 72.0);
+ x1 = fixed2float(ibox.q.x) / (pdev->HWResolution[0] / 72.0);
+ y1 = fixed2float(ibox.q.y) / (pdev->HWResolution[1] / 72.0);
+ if (Box->p.x > x0)
+ Box->p.x = x0;
+ if (Box->p.y > y0)
+ Box->p.y = y0;
+ if (Box->q.x < x1)
+ Box->q.x = x1;
+ if (Box->q.y < y1)
+ Box->q.y = y1;
+ }
+ exit:
+ return code;
+}
+
static int
pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
const gs_matrix *pmat, const gs_image_common_t *pic,
@@ -967,7 +1047,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
gx_image_enum_common_t ** pinfo,
pdf_typed_image_context_t context)
{
- int code, i;
+ int code = 0, i;
unsigned int use_fallback = 0, in_line = 0, is_mask = 0,
force_lossless = 0, convert_to_process_colors = 0;
int width, height;
@@ -976,9 +1056,9 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
const gs_pixel_image_t *pim;
gs_int_rect rect;
gs_image_format_t format;
- gs_color_space *pcs;
+ gs_color_space *pcs = NULL;
int num_components;
- pdf_image_enum *pie;
+ pdf_image_enum *pie = NULL;
const pdf_color_space_names_t *names;
gs_color_space *pcs_orig = NULL;
gs_color_space *pcs_device = NULL;
@@ -1006,14 +1086,15 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
until the mask is completed due to equal image merging. */
pdev->image_mask_id = gs_no_id;
+ pim = (const gs_pixel_image_t *)pic;
+
/* Check for the image types we can handle. */
switch (pic->type->index) {
case 1:
is_mask = ((const gs_image_t *)pic)->ImageMask;
code = setup_type1_image(pdev, pic, pdcolor, image, context);
- if (code < 0) {
+ if (code < 0)
use_fallback = 1;
- }
else
in_line = code;
break;
@@ -1039,55 +1120,107 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
(prect && !(prect->p.x == 0 && prect->p.y == 0 &&
prect->q.x == ((const gs_image3_t *)pic)->Width &&
prect->q.y == ((const gs_image3_t *)pic)->Height))) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return (gx_default_begin_typed_image((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor,
- pcpath, mem, pinfo));
+ use_fallback = 1;
+ goto exit;
}
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return (setup_type3_image(pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image));
- break;
+ code = setup_type3_image(pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo, image);
+ goto exit;
case IMAGE3X_IMAGETYPE:
pdev->JPEG_PassThrough = 0;
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
if (pdev->CompatibilityLevel < 1.4 ||
(prect && !(prect->p.x == 0 && prect->p.y == 0 &&
prect->q.x == ((const gs_image3x_t *)pic)->Width &&
prect->q.y == ((const gs_image3x_t *)pic)->Height))) {
- return (gx_default_begin_typed_image((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor,
- pcpath, mem, pinfo));
+ use_fallback = 1;
+ goto exit;
}
pdev->image_mask_is_SMask = true;
- return gx_begin_image3x_generic((gx_device *)pdev, pgs, pmat, pic,
+ code = gx_begin_image3x_generic((gx_device *)pdev, pgs, pmat, pic,
prect, pdcolor, pcpath, mem,
pdf_image3x_make_mid,
pdf_image3x_make_mcde, pinfo);
- break;
+ goto exit;
case 4:
+ /* If we are colour converting then we may not be able to preserve the
+ * type 4 image, if it has a /Mask entry which is a range of colours
+ * (chroma-key masking). If its a stencil mask then we can just conver the
+ * underlying image and leave the mask alone.
+ */
+ if (pdev->params.ColorConversionStrategy != ccs_LeaveColorUnchanged) {
+ gs_color_space *pcs2;
+ int csi = 0;
+ bool fallback = false;
+ gs_image4_t *pim4 = (gs_image4_t *)pic;
+
+ /* If the /Mask is chroma-key rather than a stencil */
+ if (pim4->MaskColor_is_range) {
+ /* Find the colour space */
+ pcs2 = pim->ColorSpace;
+ csi = gs_color_space_get_index(pcs2);
+ /* If its /Indexed, get the base space */
+ if (csi == gs_color_space_index_Indexed) {
+ pcs2 = pim->ColorSpace->base_space;
+ csi = gs_color_space_get_index(pcs2);
+ }
+ if (csi == gs_color_space_index_ICC)
+ csi = gsicc_get_default_type(pcs2->cmm_icc_profile_data);
+ /* If the base space matches the target for colour conversion
+ * then no conversion is needed, so we can preserve the type
+ * 4 image.
+ */
+ switch(csi) {
+ case gs_color_space_index_DeviceGray:
+ if (pdev->params.ColorConversionStrategy != ccs_Gray)
+ fallback = true;
+ break;
+ case gs_color_space_index_DeviceRGB:
+ if (pdev->params.ColorConversionStrategy != ccs_RGB)
+ fallback = true;
+ break;
+ case gs_color_space_index_DeviceCMYK:
+ if (pdev->params.ColorConversionStrategy != ccs_CMYK)
+ fallback = true;
+ break;
+ default:
+ fallback = true;
+ break;
+ }
+ if (fallback == true && pdev->CompatibilityLevel > 1.2) {
+ /* We've arrived at the point where we have a chroma-keyed
+ * type 4 image, and the image needs to be converted to a
+ * different space. We can't do that, so fall back to a
+ * default implementation, create a clip path and apply it to
+ * the image.
+ */
+ pdev->JPEG_PassThrough = 0;
+ use_fallback = 0;
+ code = convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
+ pcpath, mem,pinfo);
+ goto exit;
+ }
+ /* Note that we fall through to the original code, so if we are not
+ * producing at least PDF 1.2 (for image mask support) then we will
+ * fall back further filled to rectangles.
+ */
+ }
+ }
pdev->JPEG_PassThrough = 0;
code = convert_type4_image(pdev, pgs, pmat, pic, prect, pdcolor,
pcpath, mem, pinfo, context, image, pnamed);
- if (code < 0) {
+ if (code < 0)
use_fallback = 1;
- }
- if (code == 0) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return code;
- }
+ if (code == 0)
+ goto exit;
/* No luck. Masked images require PDF 1.3 or higher. */
- if (pdev->CompatibilityLevel < 1.2) {
+ if (pdev->CompatibilityLevel < 1.2)
use_fallback = 1;
- }
if (pdev->CompatibilityLevel < 1.3 && !pdev->PatternImagemask) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return (convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
- pcpath, mem,pinfo));
+ use_fallback = 0;
+ code = convert_type4_to_masked_image(pdev, pgs, pic, prect, pdcolor,
+ pcpath, mem,pinfo);
+ goto exit;
}
image[0].type4 = *(const gs_image4_t *)pic;
break;
@@ -1097,7 +1230,6 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
break;
}
- pim = (const gs_pixel_image_t *)pic;
format = pim->format;
switch (format) {
case gs_image_format_chunky:
@@ -1115,14 +1247,12 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
case 2:
case 4:
case 8:
- break;
case 12:
case 16:
break;
default:
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return_error(gs_error_rangecheck);
+ code = gs_note_error(gs_error_rangecheck);
+ goto exit;
}
if (prect)
rect = *prect;
@@ -1135,82 +1265,15 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
(is_mask && pim->CombineWithColor))
use_fallback = 1;
- if (pdev->Eps2Write) {
- gs_rect sbox, dbox, *Box;
- gs_point corners[4];
- gs_fixed_rect ibox;
- gs_matrix * pmat1 = (gs_matrix *)pmat;
- gs_matrix mat;
-
- if (!pdev->accumulating_charproc)
- Box = &pdev->BBox;
- else
- Box = &pdev->charproc_BBox;
- if (pmat1 == 0)
- pmat1 = (gs_matrix *)&ctm_only(pgs);
- if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 ||
- (code = gs_matrix_multiply(&mat, pmat1, &mat)) < 0)
- return code;
- sbox.p.x = rect.p.x;
- sbox.p.y = rect.p.y;
- sbox.q.x = rect.q.x;
- sbox.q.y = rect.q.y;
- gs_bbox_transform_only(&sbox, &mat, corners);
- gs_points_bbox(corners, &dbox);
- ibox.p.x = float2fixed(dbox.p.x);
- ibox.p.y = float2fixed(dbox.p.y);
- ibox.q.x = float2fixed(dbox.q.x);
- ibox.q.y = float2fixed(dbox.q.y);
- if (pcpath != NULL &&
- !gx_cpath_includes_rectangle(pcpath, ibox.p.x, ibox.p.y,
- ibox.q.x, ibox.q.y)
- ) {
- /* Let the target do the drawing, but drive two triangles */
- /* through the clipping path to get an accurate bounding box. */
- gx_device_clip cdev;
- gx_drawing_color devc;
-
- fixed x0 = float2fixed(corners[0].x), y0 = float2fixed(corners[0].y);
- fixed bx2 = float2fixed(corners[2].x) - x0, by2 = float2fixed(corners[2].y) - y0;
-
- pdev->AccumulatingBBox++;
- gx_make_clip_device_on_stack(&cdev, pcpath, (gx_device *)pdev);
- set_nonclient_dev_color(&devc, gx_device_black((gx_device *)pdev)); /* any non-white color will do */
- gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
- float2fixed(corners[1].x) - x0,
- float2fixed(corners[1].y) - y0,
- bx2, by2, &devc, lop_default);
- gx_default_fill_triangle((gx_device *) & cdev, x0, y0,
- float2fixed(corners[3].x) - x0,
- float2fixed(corners[3].y) - y0,
- bx2, by2, &devc, lop_default);
- pdev->AccumulatingBBox--;
- } else {
- /* Just use the bounding box. */
- float x0, y0, x1, y1;
- x0 = fixed2float(ibox.p.x) / (pdev->HWResolution[0] / 72.0);
- y0 = fixed2float(ibox.p.y) / (pdev->HWResolution[1] / 72.0);
- x1 = fixed2float(ibox.q.x) / (pdev->HWResolution[0] / 72.0);
- y1 = fixed2float(ibox.q.y) / (pdev->HWResolution[1] / 72.0);
- if (Box->p.x > x0)
- Box->p.x = x0;
- if (Box->p.y > y0)
- Box->p.y = y0;
- if (Box->q.x < x1)
- Box->q.x = x1;
- if (Box->q.y < y1)
- Box->q.y = y1;
- }
+ /* Handle BBox for Eps2Write, if applicable */
+ code = pdf_image_handle_eps(pdev, pgs, pmat, pic, &rect, pcpath);
+ if (code < 0) {
+ use_fallback = 0;
+ goto exit;
}
- if (use_fallback) {
- pdev->JPEG_PassThrough = 0;
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return gx_default_begin_typed_image
- ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
- pinfo);
- }
+ if (use_fallback)
+ goto exit;
pcs = pim->ColorSpace;
rc_increment_cs(pcs);
@@ -1218,19 +1281,13 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
if (code < 0)
- return code;
+ goto exit;
if (pdf_must_put_clip_path(pdev, pcpath))
code = pdf_unclip(pdev);
else
code = pdf_open_page(pdev, PDF_IN_STREAM);
- if (code < 0) {
- pdev->JPEG_PassThrough = 0;
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return gx_default_begin_typed_image
- ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
- pinfo);
- }
+ if (code < 0)
+ goto fail_and_fallback;
if (context == PDF_IMAGE_TYPE3_MASK) {
/*
@@ -1247,21 +1304,14 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
code = pdf_prepare_imagemask(pdev, pgs, pdcolor);
else
code = pdf_prepare_image(pdev, pgs);
- if (code < 0) {
- pdev->JPEG_PassThrough = 0;
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return gx_default_begin_typed_image
- ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
- pinfo);
- }
+ if (code < 0)
+ goto fail_and_fallback;
pie = gs_alloc_struct(mem, pdf_image_enum, &st_pdf_image_enum,
"pdf_begin_image");
if (pie == 0) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- return_error(gs_error_VMerror);
+ code = gs_note_error(gs_error_VMerror);
+ goto exit;
}
memset(pie, 0, sizeof(*pie)); /* cleanup entirely for GC to work in all cases. */
*pinfo = (gx_image_enum_common_t *) pie;
@@ -1305,24 +1355,18 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
if ((code = gs_matrix_invert(&pim->ImageMatrix, &mat)) < 0 ||
(code = gs_matrix_multiply(&bmat, &mat, &mat)) < 0 ||
(code = gs_matrix_multiply(&mat, pmat, &pie->mat)) < 0
- ) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- gs_free_object(mem, pie, "pdf_begin_image");
- return code;
- }
+ )
+ goto exit;
/* AR3,AR4 show no image when CTM is singular; AR5 reports an error */
- if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx)
+ if (pie->mat.xx * pie->mat.yy == pie->mat.xy * pie->mat.yx) {
+ use_fallback = 1;
goto fail_and_fallback;
+ }
}
code = pdf_put_clip_path(pdev, pcpath);
- if (code < 0) {
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- gs_free_object(mem, pie, "pdf_begin_image");
- return code;
- }
+ if (code < 0)
+ goto exit;
pdf_image_writer_init(&pie->writer);
/* Note : Possible values for alt_writer_count are 1,2,3,4.
1 means no alternative streams.
@@ -1352,8 +1396,10 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
if (image[0].pixel.ColorSpace != NULL && !(context == PDF_IMAGE_TYPE3_MASK))
convert_to_process_colors = setup_image_colorspace(pdev, &image[0], pcs, &pcs_orig, names, &cs_value);
- if (pim->BitsPerComponent > 8 && convert_to_process_colors)
+ if (pim->BitsPerComponent > 8 && convert_to_process_colors) {
+ use_fallback = 1;
goto fail_and_fallback;
+ }
if (convert_to_process_colors == 4) {
code = convert_DeviceN_alternate(pdev, pgs, pcs, NULL, NULL, NULL, NULL, &cs_value, in_line);
if (code < 0)
@@ -1368,6 +1414,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
code = make_device_color_space(pdev, pdev->pcm_color_info_index, &pcs_device);
if (code < 0)
goto fail_and_fallback;
+ rc_decrement(image[0].pixel.ColorSpace, "pdf_begin_typed_image(pixel.ColorSpace)");
image[0].pixel.ColorSpace = pcs_device;
image[0].pixel.BitsPerComponent = 8;
code = pdf_color_space_named(pdev, pgs, &cs_value, &pranges, pcs_device, names,
@@ -1400,53 +1447,6 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
if (code < 0)
goto fail_and_fallback;
- if (pdev->params.TransferFunctionInfo == tfi_Apply && pdev->transfer_not_identity && !is_mask)
- pdev->JPEG_PassThrough = 0;
-
- /* Code below here deals with setting up the multiple data stream writing.
- * We can have up to 4 stream writers, which we keep in an array. We must
- * always have at least one which writes the uncompressed stream. If we
- * are writing compressed streams, we have one for the compressed stream
- * and one for the compression chooser.
- * For type 4 images being converted (for old versions of PDF or for ps2write)
- * we need an additional stream to write a mask, which masks the real
- * image.
- * For colour conversion we will place an additional filter in front of all
- * the streams which does the conversion.
- */
- if (in_line) {
- pdev->JPEG_PassThrough = 0;
- code = new_setup_lossless_filters((gx_device_psdf *) pdev,
- &pie->writer.binary[0],
- &image[0].pixel, in_line, convert_to_process_colors, (gs_matrix *)pmat, (gs_gstate *)pgs);
- } else {
- if (force_lossless) {
- /*
- * Some regrettable PostScript code (such as LanguageLevel 1 output
- * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
- * function to accomplish the equivalent of indexed color.
- * Downsampling (well, only averaging) or JPEG compression are not
- * compatible with this. Play it safe by using only lossless
- * filters if the transfer function(s) is/are other than the
- * identity and by setting the downsample type to Subsample..
- */
- int saved_downsample = pdev->params.ColorImage.DownsampleType;
-
- pdev->params.ColorImage.DownsampleType = ds_Subsample;
- code = new_setup_image_filters((gx_device_psdf *) pdev,
- &pie->writer.binary[0], &image[0].pixel,
- pmat, pgs, true, in_line, convert_to_process_colors);
- pdev->params.ColorImage.DownsampleType = saved_downsample;
- } else {
- code = new_setup_image_filters((gx_device_psdf *) pdev,
- &pie->writer.binary[0], &image[0].pixel,
- pmat, pgs, true, in_line, convert_to_process_colors);
- }
- }
-
- if (code < 0)
- goto fail_and_fallback;
-
if (!convert_to_process_colors)
{
gs_color_space_index csi;
@@ -1501,10 +1501,53 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
}
}
}
- /* If we are not preserving the colour space unchanged, thenwe can't pass through JPEG */
+ /* If we are not preserving the colour space unchanged, then we can't pass through JPEG */
else
pdev->JPEG_PassThrough = 0;
+ /* Code below here deals with setting up the multiple data stream writing.
+ * We can have up to 4 stream writers, which we keep in an array. We must
+ * always have at least one which writes the uncompressed stream. If we
+ * are writing compressed streams, we have one for the compressed stream
+ * and one for the compression chooser.
+ * For type 4 images being converted (for old versions of PDF or for ps2write)
+ * we need an additional stream to write a mask, which masks the real
+ * image.
+ * For colour conversion we will place an additional filter in front of all
+ * the streams which does the conversion.
+ */
+ if (in_line) {
+ pdev->JPEG_PassThrough = 0;
+ code = new_setup_lossless_filters((gx_device_psdf *) pdev,
+ &pie->writer.binary[0],
+ &image[0].pixel, in_line, convert_to_process_colors, (gs_matrix *)pmat, (gs_gstate *)pgs);
+ } else {
+ if (force_lossless) {
+ /*
+ * Some regrettable PostScript code (such as LanguageLevel 1 output
+ * from Microsoft's PSCRIPT.DLL driver) misuses the transfer
+ * function to accomplish the equivalent of indexed color.
+ * Downsampling (well, only averaging) or JPEG compression are not
+ * compatible with this. Play it safe by using only lossless
+ * filters if the transfer function(s) is/are other than the
+ * identity and by setting the downsample type to Subsample..
+ */
+ int saved_downsample = pdev->params.ColorImage.DownsampleType;
+
+ pdev->params.ColorImage.DownsampleType = ds_Subsample;
+ code = new_setup_image_filters((gx_device_psdf *) pdev,
+ &pie->writer.binary[0], &image[0].pixel,
+ pmat, pgs, true, in_line, convert_to_process_colors);
+ pdev->params.ColorImage.DownsampleType = saved_downsample;
+ } else {
+ code = new_setup_image_filters((gx_device_psdf *) pdev,
+ &pie->writer.binary[0], &image[0].pixel,
+ pmat, pgs, true, in_line, convert_to_process_colors);
+ }
+ }
+
+ if (code < 0)
+ goto fail_and_fallback;
if (convert_to_process_colors) {
image[0].pixel.ColorSpace = pcs_orig;
@@ -1529,9 +1572,8 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
if (pie->writer.alt_writer_count > 1) {
code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
- if (code) {
+ if (code < 0)
goto fail_and_fallback;
- }
code = new_setup_image_filters((gx_device_psdf *) pdev,
&pie->writer.binary[1], &image[1].pixel,
pmat, pgs, force_lossless, in_line, convert_to_process_colors);
@@ -1542,8 +1584,11 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
cos_stream_t *pcos = cos_stream_from_pipeline(pie->writer.binary[i].strm);
s_close_filters(&s, NULL);
gs_free_object(pdev->pdf_memory, s, "compressed image stream");
- if (pcos == 0L)
- return gs_note_error(gs_error_ioerror);
+ if (pcos == 0L) {
+ /* TODO: Seems like something should be freed here */
+ code = gs_note_error(gs_error_ioerror);
+ goto exit;
+ }
pcos->cos_procs->release((cos_object_t *)pcos, "pdf_begin_typed_image_impl");
gs_free_object(pdev->pdf_memory, pcos, "compressed image cos_stream");
}
@@ -1558,9 +1603,8 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
image[1].pixel.BitsPerComponent = pim->BitsPerComponent;
code = psdf_setup_image_colors_filter(&pie->writer.binary[1],
(gx_device_psdf *)pdev, pim, &image[1].pixel, pgs);
- if (code < 0) {
+ if (code < 0)
goto fail_and_fallback;
- }
image[1].pixel.ColorSpace = pcs_device;
}
}
@@ -1588,7 +1632,7 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
/* Won't use image[2]. */
code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
height, NULL, false);
- if (code)
+ if (code < 0)
goto fail_and_fallback;
code = psdf_setup_image_filters((gx_device_psdf *) pdev,
&pie->writer.binary[i], &image[i].pixel,
@@ -1609,20 +1653,38 @@ pdf_begin_typed_image(gx_device_pdf *pdev, const gs_gstate * pgs,
++pie->writer.alt_writer_count;
}
- gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
- "pdf_begin_typed_image(image)");
- rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
- return 0;
+ /* use_fallback = 0, so this will drop through the below labels, doing only the cleanup parts */
+ code = 0;
+
+ /* This label is used when code < 0 and we want to do the fallback code */
+ fail_and_fallback:
+ if (code != 0)
+ use_fallback = 1;
-fail_and_fallback:
+ /* This label is used either when there's no error and we are just exiting normally
+ * (possibly with use_fallback=1), or there is an error but we don't want to do
+ * the fallback code.
+ */
+ exit:
+ /* Free everything */
rc_decrement(pcs, "pdf_begin_typed_image(pcs)");
- pdev->JPEG_PassThrough = 0;
+ rc_decrement(pcs_device, "pdf_begin_typed_image(pcs_device)");
gs_free(mem->non_gc_memory, image, 4, sizeof(image_union_t),
"pdf_begin_typed_image(image)");
- gs_free_object(mem, pie, "pdf_begin_image");
- return gx_default_begin_typed_image
- ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem,
- pinfo);
+
+ /* Free pie only if there was an error or we are falling back */
+ if (code < 0 || use_fallback) {
+ if (pie)
+ gs_free_object(mem, pie, "pdf_begin_typed_image(pie)");
+ *pinfo = NULL;
+ }
+ /* Do the fallback */
+ if (use_fallback) {
+ pdev->JPEG_PassThrough = 0;
+ code = gx_default_begin_typed_image
+ ((gx_device *)pdev, pgs, pmat, pic, prect, pdcolor, pcpath, mem, pinfo);
+ }
+ return code;
}
int
@@ -1730,7 +1792,7 @@ pdf_image_plane_data(gx_image_enum_common_t * info,
if (pie->JPEG_PassThrough) {
pie->rows_left -= height;
*rows_used = height;
- return 0;
+ return !pie->rows_left;
}
for (i = 0; i < pie->writer.alt_writer_count; i++) {
@@ -1922,6 +1984,10 @@ pdf_image_end_image_data(gx_image_enum_common_t * info, bool draw_last,
} else
code = pdf_end_and_do_image(pdev, &pie->writer, &pie->mat, info->id, do_image);
pie->writer.alt_writer_count--; /* For GC. */
+ } else {
+ code = pdf_end_image_binary(pdev, &pie->writer, data_height);
+ code = pdf_end_abort_image(pdev, &pie->writer);
+ pie->writer.alt_writer_count--; /* For GC. */
}
if (pie->initial_colorspace != pdev->pcm_color_info_index)
pdf_set_process_color_model(pdev, pie->initial_colorspace);
@@ -2286,7 +2352,7 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
if (code < 0)
return code;
pcd = cos_stream_dict((cos_stream_t *)pres->object);
- pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
+ pcd_Resources = cos_dict_alloc(pdev, "pdf_form(Resources)");
if (pcd == NULL || pcd_Resources == NULL)
return_error(gs_error_VMerror);
code = cos_dict_put_c_strings(pcd, "/Type", "/XObject");
@@ -2467,6 +2533,13 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
pres->where_used |= pdev->used_mask;
} else if (pres->object->id < 0)
pdf_reserve_object_id(pdev, pres, 0);
+ pdev->LastFormID = pdf_resource_id(pres);
+ pdev->HighLevelForm--;
+ if (pdev->accumulating_substream_resource) {
+ code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
+ if (code < 0)
+ return code;
+ }
if (pdev->PDFFormName) {
cos_value_t value;
@@ -2476,19 +2549,14 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
if (code < 0)
return code;
pdf_drop_resource_from_chain(pdev, pres, resourceXObject);
+ pres->object = NULL;
+ gs_free_object(pdev->pdf_memory, pres, "free redundant resource");
- gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name oof Form for pdfmark");
+ gs_free_object(pdev->memory->non_gc_memory, pdev->PDFFormName, "free Name of Form for pdfmark");
pdev->PDFFormName = 0x00;
} else {
pprintld1(pdev->strm, "/R%ld Do Q\n", pdf_resource_id(pres));
}
- pdev->HighLevelForm--;
- if (pdev->accumulating_substream_resource) {
- code = pdf_add_resource(pdev, pdev->substream_Resources, "/XObject", pres);
- if (code < 0)
- return code;
- }
- pdev->LastFormID = pdf_resource_id(pres);
}
return 0;
case gxdso_get_form_ID:
@@ -2690,6 +2758,8 @@ gdev_pdf_dev_spec_op(gx_device *pdev1, int dev_spec_op, void *data, int size)
return 0;
}
break;
+ case gxdso_in_smask_construction:
+ return pdev->smask_construction;
case gxdso_get_dev_param:
{
int code;
diff --git a/devices/vector/gdevpdfj.c b/devices/vector/gdevpdfj.c
index 4c73e171..6140d4d6 100644
--- a/devices/vector/gdevpdfj.c
+++ b/devices/vector/gdevpdfj.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -528,6 +528,21 @@ smask_image_check(gx_device_pdf * pdev, pdf_resource_t *pres0, pdf_resource_t *p
return 1;
}
+
+/* Abort an image without writing it.
+ * Frees any associated memory.
+ */
+int
+pdf_end_abort_image(gx_device_pdf * pdev, pdf_image_writer * piw)
+{
+ pdf_resource_t *pres = piw->pres;
+
+ if (!pres) {
+ COS_FREE(piw->data, "pdf_end_write_image");
+ }
+ return 0;
+}
+
/*
* Finish writing an image. If in-line, write the BI/dict/ID/data/EI and
* return 1; if a resource, write the resource definition and return 0.
diff --git a/devices/vector/gdevpdfk.c b/devices/vector/gdevpdfk.c
index e48718d1..c682c6ea 100644
--- a/devices/vector/gdevpdfk.c
+++ b/devices/vector/gdevpdfk.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -115,7 +115,7 @@ cie_to_xyz(const double *in, double out[3], const gs_color_space *pcs,
handles mapping to CIE D50. This forces an achromatic result */
xyz_float[0] = pWhitePoint->u * xyz_float[1];
xyz_float[2] = pWhitePoint->w * xyz_float[1];
- }
+ }
/* Do wp mapping to D50 in XYZ for now. We should do bradford correction.
Will add that in next release */
diff --git a/devices/vector/gdevpdfm.c b/devices/vector/gdevpdfm.c
index 18ea50c5..ba00700a 100644
--- a/devices/vector/gdevpdfm.c
+++ b/devices/vector/gdevpdfm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -832,8 +832,10 @@ pdfmark_put_ao_pairs(gx_device_pdf * pdev, cos_dict_t *pcd,
cos_dict_put_string(adict, key.data, key.size,
value.data, value.size);
}
- if (code <= 0 || !pdf_key_eq(&key, ">>"))
+ if (code <= 0 || !pdf_key_eq(&key, ">>")) {
+ cos_free((cos_object_t *)adict, "action dict");
return_error(gs_error_rangecheck);
+ }
cos_dict_put(pcd, (const byte *)"/A", 2,
COS_OBJECT_VALUE(&avalue, adict));
} else if (pdf_key_eq(Action + 1, "/GoTo"))
@@ -1174,20 +1176,28 @@ pdfmark_annot(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
if (code < 0)
return code;
code = cos_dict_put_c_strings(pcd, "/Type", "/Annot");
- if (code < 0)
+ if (code < 0) {
+ cos_free((cos_object_t *)pcd, "pdfmark_annot");
return code;
+ }
code = pdfmark_put_ao_pairs(pdev, pcd, pairs, count, pctm, &params, false);
- if (code < 0)
+ if (code < 0) {
+ cos_free((cos_object_t *)pcd, "pdfmark_annot");
return code;
+ }
if (params.src_pg >= 0)
page_index = params.src_pg;
- if (pdf_page_id(pdev, page_index + 1) <= 0)
+ if (pdf_page_id(pdev, page_index + 1) <= 0) {
+ cos_free((cos_object_t *)pcd, "pdfmark_annot");
return_error(gs_error_rangecheck);
+ }
annots = pdev->pages[page_index].Annots;
if (annots == 0) {
annots = cos_array_alloc(pdev, "pdfmark_annot");
- if (annots == 0)
+ if (annots == 0) {
+ cos_free((cos_object_t *)pcd, "pdfmark_annot");
return_error(gs_error_VMerror);
+ }
pdev->pages[page_index].Annots = annots;
}
if (!objname) {
@@ -1334,8 +1344,10 @@ pdfmark_OUT(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
ao.src_pg = -1;
code = pdfmark_put_ao_pairs(pdev, node.action, pairs, count, pctm, &ao,
true);
- if (code < 0)
+ if (code < 0) {
+ cos_free((cos_object_t *)node.action, "pdfmark_OUT");
return code;
+ }
if (pdev->outlines_id == 0)
pdev->outlines_id = pdf_obj_ref(pdev);
node.id = pdf_obj_ref(pdev);
@@ -1944,25 +1956,41 @@ pdfmark_DOCINFO(gx_device_pdf * pdev, gs_param_string * pairs, uint count,
if (pdev->PDFA !=0) {
const gs_param_string *p = pairs + i + 1;
- if (p->size > 9 && memcmp(p->data, "(\\376\\377", 9) == 0) {
+ bool abort = false;
+
+ if (p->size > 9 && memcmp(p->data, "(\\376\\377", 9) == 0)
+ abort = true;
+ else {
+ int j;
+ for (j = 0;j < p->size;j++)
+ {
+ if (p->data[j] == '\\' || p->data[j] > 0x7F || p->data[j] < 0x20)
+ {
+ abort = true;
+ break;
+ }
+ }
+ }
+ if (abort == true)
+ {
/* Can't handle UTF16BE in PDF/A1, so abort this pair or abort PDF/A or just abort,
* depending on PDFACompatibilityPolicy
*/
switch (pdev->PDFACompatibilityPolicy) {
case 0:
emprintf(pdev->memory,
- "UTF16BE text string detected in DOCINFO cannot be represented in XMP for PDF/A1, reverting to normal PDF output\n");
+ "Text string detected in DOCINFO cannot be represented in XMP for PDF/A1, reverting to normal PDF output\n");
pdev->AbortPDFAX = true;
pdev->PDFX = 0;
break;
case 1:
emprintf(pdev->memory,
- "UTF16BE text string detected in DOCINFO cannot be represented in XMP for PDF/A1, discarding DOCINFO\n");
+ "Text string detected in DOCINFO cannot be represented in XMP for PDF/A1, discarding DOCINFO\n");
continue;
break;
case 2:
emprintf(pdev->memory,
- "UTF16BE text string detected in DOCINFO cannot be represented in XMP for PDF/A1, aborting conversion.\n");
+ "Text string detected in DOCINFO cannot be represented in XMP for PDF/A1, aborting conversion.\n");
/* If we don't return a fatal error then zputdeviceparams simply ignores it (!) */
return_error(gs_error_Fatal);
break;
@@ -2456,7 +2484,16 @@ pdfmark_BDC(gx_device_pdf *pdev, gs_param_string *pairs, uint count,
/* strip << and >> */
if ((pairs[1].data)[0]=='<'&&(pairs[1].data)[1]=='<')
{
- pairs[1].data=&(pairs[1].data[2]);
+ int ix = 0;
+ byte *p = (byte *)pairs[1].data;
+
+ /* Fortunately we don't use the 'size' when freeing the memory
+ * so we can quickly copy the string content up two places and reduce
+ * the size by 2 to remove the '<<'. This saves an alloc and free of the
+ * string data.
+ */
+ for (ix = 0; ix < pairs[1].size - 2;ix++)
+ p[ix] = pairs[1].data[ix + 2];
pairs[1].size-=2;
}
else
@@ -2831,7 +2868,7 @@ pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
gs_memory_t *mem = pdev->pdf_memory;
int odd_ok = (pmn->options & PDFMARK_ODD_OK) != 0;
gs_param_string *pairs;
- int j;
+ int j, index;
/*
* Our coordinate system is scaled so that user space is always
@@ -2866,9 +2903,25 @@ pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
"pdfmark_process(pairs)");
if (!pairs)
return_error(gs_error_VMerror);
- memcpy(pairs, data, j * sizeof(*data));
- memcpy(pairs + j, data + j + 2,
- (size - j) * sizeof(*data));
+
+ for (index=0;index < size;index++)
+ pairs[index].data = NULL;
+ for (index=0;index < j;index++) {
+ pairs[index].data = gs_alloc_bytes(mem, data[index].size, "pdfmark_process(pairs)");
+ if (pairs[index].data == NULL)
+ goto error;
+ memcpy((byte *)pairs[index].data, data[index].data, data[index].size);
+ pairs[index].size = data[index].size;
+ pairs[index].persistent = 1;
+ }
+ for (index=j+2;index < size + 2;index++) {
+ pairs[index - 2].data = gs_alloc_bytes(mem, data[index].size, "pdfmark_process(pairs)");
+ if (pairs[index - 2].data == NULL)
+ goto error;
+ memcpy((byte *)pairs[index - 2].data, data[index].data, data[index].size);
+ pairs[index - 2].size = data[index].size;
+ pairs[index - 2].persistent = 1;
+ }
goto copied;
}
}
@@ -2879,8 +2932,17 @@ pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
"pdfmark_process(pairs)");
if (!pairs)
return_error(gs_error_VMerror);
- memcpy(pairs, data, size * sizeof(*data));
- copied: /* Substitute object references for names. */
+ for (j=0;j < size;j++)
+ pairs[j].data = NULL;
+ for (j=0;j < size;j++) {
+ pairs[j].data = gs_alloc_bytes(mem, data[j].size, "pdfmark_process(pairs)");
+ if (pairs[j].data == NULL)
+ goto error;
+ memcpy((byte *)pairs[j].data, data[j].data, data[j].size);
+ pairs[j].size = data[j].size;
+ pairs[j].persistent = 1;
+ }
+copied: /* Substitute object references for names. */
if (!(pmn->options & PDFMARK_NO_REFS)) {
for (j = (pmn->options & PDFMARK_KEEP_NAME ? 1 : 1 - odd_ok);
j < size; j += 2 - odd_ok
@@ -2893,6 +2955,9 @@ pdfmark_process(gx_device_pdf * pdev, const gs_param_string_array * pma)
}
}
code = (*pmn->proc) (pdev, pairs, size, &ctm, objname);
+error:
+ for (j=0;j < size;j++)
+ gs_free_object(mem, (byte *)pairs[j].data, "pdfmark_process(pairs)");
gs_free_object(mem, pairs, "pdfmark_process(pairs)");
break;
}
diff --git a/devices/vector/gdevpdfo.c b/devices/vector/gdevpdfo.c
index 70b66c6b..a1c18012 100644
--- a/devices/vector/gdevpdfo.c
+++ b/devices/vector/gdevpdfo.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -281,12 +281,12 @@ cos_resource_value(cos_value_t *pcv, cos_object_t *pco)
/* Free a value. */
void
-cos_value_free(const cos_value_t *pcv, const cos_object_t *pco,
+cos_value_free(const cos_value_t *pcv, gs_memory_t *mem,
client_name_t cname)
{
switch (pcv->value_type) {
case COS_VALUE_SCALAR:
- gs_free_string(cos_object_memory(pco), pcv->contents.chars.data,
+ gs_free_string(mem, pcv->contents.chars.data,
pcv->contents.chars.size, cname);
case COS_VALUE_CONST:
break;
@@ -517,7 +517,7 @@ cos_array_release(cos_object_t *pco, client_name_t cname)
for (cur = pca->elements; cur; cur = next) {
next = cur->next;
- cos_value_free(&cur->value, pco, cname);
+ cos_value_free(&cur->value, cos_object_memory(pco), cname);
gs_free_object(cos_object_memory(pco), cur, cname);
}
pca->elements = 0;
@@ -654,7 +654,7 @@ cos_array_put_no_copy(cos_array_t *pca, long index, const cos_value_t *pvalue)
ppcae = &next->next;
if (next && next->index == index) {
/* We're replacing an existing element. */
- cos_value_free(&next->value, COS_OBJECT(pca),
+ cos_value_free(&next->value, mem,
"cos_array_put(old value)");
pcae = next;
} else {
@@ -807,7 +807,7 @@ cos_dict_element_free(cos_dict_t *pcd, cos_dict_element_t *pcde,
{
gs_memory_t *mem = COS_OBJECT_MEMORY(pcd);
- cos_value_free(&pcde->value, COS_OBJECT(pcd), cname);
+ cos_value_free(&pcde->value, mem, cname);
if (pcde->owns_key)
gs_free_string(mem, pcde->key.data, pcde->key.size, cname);
gs_free_object(mem, pcde, cname);
@@ -1308,10 +1308,7 @@ cos_dict_put_copy(cos_dict_t *pcd, const byte *key_data, uint key_size,
(flags & DICT_COPY_VALUE) != 0);
if (code < 0)
return code;
- if (flags & DICT_FREE_KEY)
- gs_free_const_string(mem, key_data, key_size,
- "cos_dict_put(new key)");
- cos_value_free(&next->value, COS_OBJECT(pcd),
+ cos_value_free(&next->value, mem,
"cos_dict_put(old value)");
pcde = next;
} else {
diff --git a/devices/vector/gdevpdfo.h b/devices/vector/gdevpdfo.h
index b30e9676..d358993b 100644
--- a/devices/vector/gdevpdfo.h
+++ b/devices/vector/gdevpdfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -347,7 +347,7 @@ int cos_write_object(cos_object_t *pco, gx_device_pdf *pdev, pdf_resource_type_t
#define COS_WRITE_OBJECT(pc, pdev, type) cos_write_object(COS_OBJECT(pc), pdev, type)
/* Free a Cos value owned by a Cos object. */
-void cos_value_free(const cos_value_t *, const cos_object_t *, client_name_t);
+void cos_value_free(const cos_value_t *, gs_memory_t *, client_name_t);
/* Free a cos object. */
void cos_free(cos_object_t *pco, client_name_t cname);
diff --git a/devices/vector/gdevpdfp.c b/devices/vector/gdevpdfp.c
index d06e585c..e78d9596 100644
--- a/devices/vector/gdevpdfp.c
+++ b/devices/vector/gdevpdfp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -119,6 +119,7 @@ static const gs_param_item_t pdf_param_items[] = {
pi("DetectDuplicateImages", gs_param_type_bool, DetectDuplicateImages),
pi("AllowIncrementalCFF", gs_param_type_bool, AllowIncrementalCFF),
pi("WantsToUnicode", gs_param_type_bool, WantsToUnicode),
+ pi("PdfmarkCapable", gs_param_type_bool, PdfmarkCapable),
pi("AllowPSRepeatFunctions", gs_param_type_bool, AllowPSRepeatFunctions),
pi("IsDistiller", gs_param_type_bool, IsDistiller),
pi("PreserveSMask", gs_param_type_bool, PreserveSMask),
@@ -254,6 +255,48 @@ gdev_pdf_get_param(gx_device *dev, char *Param, void *list)
return(param_write_null(plist, "DSC"));
}
}
+
+#if OCR_VERSION > 0
+ if (strcmp(Param, "OCRLanguage") == 0) {
+ gs_param_string langstr;
+ if (pdev->ocr_language[0]) {
+ langstr.data = (const byte *)pdev->ocr_language;
+ langstr.size = strlen(pdev->ocr_language);
+ langstr.persistent = false;
+ } else {
+ langstr.data = (const byte *)"eng";
+ langstr.size = 3;
+ langstr.persistent = false;
+ }
+ return param_write_string(plist, "OCRLanguage", &langstr);
+ }
+ if (strcmp(Param, "OCREngine") == 0)
+ return param_write_int(plist, "OCREngine", &pdev->ocr_engine);
+
+ if (strcmp(Param, "UseOCR") == 0) {
+ gs_param_string ocrstr;
+
+ switch(pdev->UseOCR) {
+ case UseOCRNever:
+ ocrstr.data = (const byte *)"Never";
+ ocrstr.size = 5;
+ ocrstr.persistent = false;
+ break;
+ UseOCRAsNeeded:
+ ocrstr.data = (const byte *)"AsNeeded";
+ ocrstr.size = 8;
+ ocrstr.persistent = false;
+ break;
+ UseOCRAlways:
+ ocrstr.data = (const byte *)"Always";
+ ocrstr.size = 8;
+ ocrstr.persistent = false;
+ break;
+ }
+ return param_write_string(plist, "UseOCR", &ocrstr);
+ }
+#endif
+
return gdev_psdf_get_param(dev, Param, list);
}
@@ -268,6 +311,49 @@ gdev_pdf_get_params(gx_device * dev, gs_param_list * plist)
int code;
int cdv = CoreDistVersion;
+#if OCR_VERSION > 0
+ gs_param_string langstr;
+
+ if (pdev->ocr_language[0]) {
+ langstr.data = (const byte *)pdev->ocr_language;
+ langstr.size = strlen(pdev->ocr_language);
+ langstr.persistent = false;
+ } else {
+ langstr.data = (const byte *)"eng";
+ langstr.size = 3;
+ langstr.persistent = false;
+ }
+
+ {
+ gs_param_string ocrstr;
+
+ switch(pdev->UseOCR) {
+ case UseOCRNever:
+ ocrstr.data = (const byte *)"Never";
+ ocrstr.size = 5;
+ ocrstr.persistent = false;
+ break;
+ UseOCRAsNeeded:
+ ocrstr.data = (const byte *)"AsNeeded";
+ ocrstr.size = 8;
+ ocrstr.persistent = false;
+ break;
+ UseOCRAlways:
+ ocrstr.data = (const byte *)"Always";
+ ocrstr.size = 8;
+ ocrstr.persistent = false;
+ break;
+ }
+ code = param_write_string(plist, "UseOCR", &ocrstr);
+ }
+ code = param_write_string(plist, "OCRLanguage", &langstr);
+ if(code < 0)
+ return code;
+ code = param_write_int(plist, "OCREngine", &pdev->ocr_engine);
+ if(code < 0)
+ return code;
+#endif
+
pdev->ParamCompatibilityLevel = cl;
code = gdev_psdf_get_params(dev, plist);
if (code < 0 ||
@@ -366,6 +452,83 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
}
}
+#if OCR_VERSION > 0
+ {
+ int len;
+ gs_param_string langstr;
+ switch (code = param_read_string(plist, (param_name = "OCRLanguage"), &langstr)) {
+ case 0:
+ len = langstr.size;
+ if (len >= sizeof(pdev->ocr_language))
+ len = sizeof(pdev->ocr_language)-1;
+ memcpy(pdev->ocr_language, langstr.data, len);
+ pdev->ocr_language[len] = 0;
+ break;
+ case 1:
+ break;
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
+ }
+
+ {
+ int engine;
+ switch (code = param_read_int(plist, (param_name = "OCREngine"), &engine)) {
+ case 0:
+ pdev->ocr_engine = engine;
+ break;
+ case 1:
+ break;
+ default:
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
+ }
+
+ {
+ gs_param_string ocrstr;
+
+ code = param_read_string(plist, (param_name = "UseOCR"), &ocrstr);
+ switch(code) {
+ case 0:
+ if (ocrstr.size == 5 && memcmp(ocrstr.data, "Never", 5) == 0)
+ pdev->UseOCR = UseOCRNever;
+ if (ocrstr.size == 8 && memcmp(ocrstr.data, "AsNeeded", 8) == 0)
+ pdev->UseOCR = UseOCRAsNeeded;
+ if (ocrstr.size == 6 && memcmp(ocrstr.data, "Always", 6) == 0)
+ pdev->UseOCR = UseOCRAlways;
+ break;
+ case 1:
+ break;
+ default:
+ param_signal_error(plist, param_name, code);
+ break;
+ }
+ }
+
+ {
+ gs_param_string ocrstr;
+
+ code = param_read_string(plist, (param_name = "UseOCR"), &ocrstr);
+ switch(code) {
+ case 0:
+ if (ocrstr.size == 5 && memcmp(ocrstr.data, "Never", 5) == 0)
+ pdev->UseOCR = UseOCRNever;
+ if (ocrstr.size == 8 && memcmp(ocrstr.data, "AsNeeded", 8) == 0)
+ pdev->UseOCR = UseOCRAsNeeded;
+ if (ocrstr.size == 6 && memcmp(ocrstr.data, "Always", 6) == 0)
+ pdev->UseOCR = UseOCRAlways;
+ break;
+ case 1:
+ break;
+ default:
+ param_signal_error(plist, param_name, code);
+ break;
+ }
+ }
+#endif
+
/*
* Check for LockDistillerParams before doing anything else.
* If LockDistillerParams is true and is not being set to false,
@@ -594,9 +757,6 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
if (pdev->params.ColorConversionStrategy == ccs_Gray) {
emprintf(pdev->memory, "ConvertCMYKImagesToRGB is not compatible with ColorConversionStrategy of Gray\n");
} else {
- if (pdev->icc_struct)
- rc_decrement(pdev->icc_struct,
- "reset default profile\n");
pdf_set_process_color_model(pdev,1);
ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
if (ecode < 0)
@@ -613,18 +773,12 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
pdev->params.TransferFunctionInfo = tfi_Apply;
break;
case ccs_CMYK:
- if (pdev->icc_struct)
- rc_decrement(pdev->icc_struct,
- "reset default profile\n");
pdf_set_process_color_model(pdev, 2);
ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
if (ecode < 0)
goto fail;
break;
case ccs_Gray:
- if (pdev->icc_struct)
- rc_decrement(pdev->icc_struct,
- "reset default profile\n");
pdf_set_process_color_model(pdev,0);
ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
if (ecode < 0)
@@ -634,9 +788,6 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
case ccs_RGB:
/* Only bother to do this if we didn't handle it above */
if (!pdev->params.ConvertCMYKImagesToRGB) {
- if (pdev->icc_struct)
- rc_decrement(pdev->icc_struct,
- "reset default profile\n");
pdf_set_process_color_model(pdev,1);
ecode = gsicc_init_device_profile_struct((gx_device *)pdev, NULL, 0);
if (ecode < 0)
@@ -701,6 +852,11 @@ gdev_pdf_put_params_impl(gx_device * dev, const gx_device_pdf * save_dev, gs_par
}
}
+ if (pdev->Linearise && pdev->file != NULL && !gp_fseekable(pdev->file)) {
+ emprintf(pdev->memory, "Can't linearise a non-seekable output file, ignoring\n");
+ pdev->Linearise = false;
+ }
+
if (pdev->Linearise && pdev->is_ps2write) {
emprintf(pdev->memory, "Can't linearise PostScript output, ignoring\n");
pdev->Linearise = false;
diff --git a/devices/vector/gdevpdfr.c b/devices/vector/gdevpdfr.c
index b0ee06c4..7aca15a6 100644
--- a/devices/vector/gdevpdfr.c
+++ b/devices/vector/gdevpdfr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -320,12 +320,12 @@ pdf_scan_token(const byte **pscan, const byte * end, const byte **ptoken)
int status;
s_PSSD_init((stream_state *)&ss);
- r.ptr = p; /* skip the '(' */
- r.limit = end - 1;
- w.limit = buf + sizeof(buf) - 1;
+
+ /* "p + 1" - skip the '(' */
+ stream_cursor_read_init(&r, p + 1, (end - p) - 1);
+
do {
- /* One picky compiler complains if we initialize to buf - 1. */
- w.ptr = buf; w.ptr--;
+ stream_cursor_write_init(&w, buf, sizeof(buf));
status = (*s_PSSD_template.process)
((stream_state *) & ss, &r, &w, true);
}
@@ -337,6 +337,7 @@ pdf_scan_token(const byte **pscan, const byte * end, const byte **ptoken)
if (end - p < 2)
return_error(gs_error_syntaxerror);
if (p[1] != '<') {
+ /* This is handling a hex string, just skips across the entire string to the '>' */
/*
* We need the cast because some compilers declare memchar as
* returning a char * rather than a void *.
@@ -344,12 +345,19 @@ pdf_scan_token(const byte **pscan, const byte * end, const byte **ptoken)
p = (const byte *)memchr(p + 1, '>', end - p - 1);
if (p == 0)
return_error(gs_error_syntaxerror);
+ *pscan = p + 1;
+ return 1;
+ } else {
+ /* This case is is beginning of a dict, "<<". Return it as a token. */
+ *pscan = p + 2;
+ return 1;
}
- goto m2;
+ break;
case '>':
+ /* This case is the end of a dict, ">>". Return it as a token. */
if (end - p < 2 || p[1] != '>')
return_error(gs_error_syntaxerror);
-m2: *pscan = p + 2;
+ *pscan = p + 2;
return 1;
case '[': case ']': case '{': case '}':
*pscan = p + 1;
@@ -447,7 +455,7 @@ pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from,
{
const byte *start = from->data;
const byte *end = start + from->size;
- const byte *scan;
+ const byte *scan, *to_free = NULL;
uint size = 0;
cos_object_t *pco;
bool any = false;
@@ -477,13 +485,17 @@ pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from,
}
to->persistent = true; /* ??? */
if (!any) {
- to->data = start;
+ if (to->data != start) {
+ gs_free_object(pdev->pdf_memory, (byte *)to->data, "pdf_replace_names");
+ to->data = start;
+ }
to->size = size;
return 0;
}
sto = gs_alloc_bytes(pdev->pdf_memory, size, "pdf_replace_names");
if (sto == 0)
return_error(gs_error_VMerror);
+ to_free = to->data;
to->data = sto;
to->size = size;
/* Do a second pass to do the actual substitutions. */
@@ -508,5 +520,6 @@ pdf_replace_names(gx_device_pdf * pdev, const gs_param_string * from,
}
scan = next;
}
+ gs_free_object(pdev->pdf_memory, (byte *)to_free, "pdf_replace_names");
return 0;
}
diff --git a/devices/vector/gdevpdft.c b/devices/vector/gdevpdft.c
index a963cb51..8b5a2094 100644
--- a/devices/vector/gdevpdft.c
+++ b/devices/vector/gdevpdft.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -334,6 +334,7 @@ pdf_begin_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev,
} else {
int code;
+ pdev->smask_construction = true;
code = pdf_make_soft_mask_dict(pdev, pparams);
if (code < 0)
return code;
@@ -348,6 +349,7 @@ static int
pdf_end_transparency_mask(gs_gstate * pgs, gx_device_pdf * pdev,
const gs_pdf14trans_params_t * pparams)
{
+ pdev->smask_construction = false;
if (pdev->image_mask_skip)
pdev->image_mask_skip = false;
else {
diff --git a/devices/vector/gdevpdfu.c b/devices/vector/gdevpdfu.c
index e5a9df01..325af7c2 100644
--- a/devices/vector/gdevpdfu.c
+++ b/devices/vector/gdevpdfu.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -39,12 +39,6 @@
#include "sstring.h"
#include "strmio.h"
#include "szlibx.h"
-#ifdef USE_LDF_JB2
-#include "sjbig2_luratech.h"
-#endif
-#ifdef USE_LWF_JP2
-#include "sjpx_luratech.h"
-#endif
#include "opdfread.h"
#include "gdevagl.h"
@@ -768,6 +762,9 @@ pdf_open_obj(gx_device_pdf * pdev, long id, pdf_resource_type_t type)
{
stream *s = pdev->strm;
+ if (s == NULL)
+ return_error(gs_error_ioerror);
+
if (id <= 0) {
id = pdf_obj_ref(pdev);
} else {
@@ -777,10 +774,10 @@ pdf_open_obj(gx_device_pdf * pdev, long id, pdf_resource_type_t type)
if (gp_fseek(tfile, ((int64_t)(id - pdev->FirstObjectNumber)) * sizeof(pos),
SEEK_SET) != 0)
- return_error(gs_error_ioerror);
+ return_error(gs_error_ioerror);
gp_fwrite(&pos, sizeof(pos), 1, tfile);
if (gp_fseek(tfile, tpos, SEEK_SET) != 0)
- return_error(gs_error_ioerror);
+ return_error(gs_error_ioerror);
}
if (pdev->ForOPDFRead && pdev->ProduceDSC) {
switch(type) {
@@ -1887,7 +1884,7 @@ pdf_page_id(gx_device_pdf * pdev, int page_num)
{
cos_dict_t *Page;
- if (page_num < 1)
+ if (page_num < 1 || pdev->pages == NULL)
return 0;
if (page_num >= pdev->num_pages) { /* Grow the pages array. */
uint new_num_pages;
@@ -2394,14 +2391,6 @@ pdf_put_filters(cos_dict_t *pcd, gx_device_pdf *pdev, stream *s,
filter_name = pfn->FlateDecode;
else if (TEMPLATE_IS(s_LZWE_template))
filter_name = pfn->LZWDecode;
-#ifdef USE_LDF_JB2
- else if (TEMPLATE_IS(s_jbig2encode_template))
- filter_name = pfn->JBIG2Decode;
-#endif
-#ifdef USE_LWF_JP2
- else if (TEMPLATE_IS(s_jpxe_template))
- filter_name = pfn->JPXDecode;
-#endif
else if (TEMPLATE_IS(s_PNGPE_template)) {
/* This is a predictor for FlateDecode or LZWEncode. */
const stream_PNGP_state *const ss =
diff --git a/devices/vector/gdevpdfv.c b/devices/vector/gdevpdfv.c
index dd7d4c7c..6b3c5c97 100644
--- a/devices/vector/gdevpdfv.c
+++ b/devices/vector/gdevpdfv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h
index c8b44b46..2db4f77a 100644
--- a/devices/vector/gdevpdfx.h
+++ b/devices/vector/gdevpdfx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -547,6 +547,33 @@ typedef enum {
pdf_compress_Flate
} pdf_compression_type;
+typedef enum {
+ OCR_UnInit,
+ OCR_Rendering,
+ OCR_Rendered,
+ OCR_UnicodeAvailable,
+ OCR_Failed
+} pdf_OCR_stage;
+
+typedef enum {
+ UseOCRNever,
+ UseOCRAsNeeded,
+ UseOCRAlways
+} pdf_OCR_usage;
+
+typedef struct ocr_glyph_s{
+ byte *data;
+ int x;
+ int y;
+ int width;
+ int height;
+ int raster;
+ void *next;
+ gs_char char_code;
+ gs_glyph glyph;
+ bool is_space;
+} ocr_glyph_t;
+
/* Define the device structure. */
struct gx_device_pdf_s {
gx_device_psdf_common;
@@ -572,6 +599,9 @@ struct gx_device_pdf_s {
gs_param_float_array PDFXTrimBoxToMediaBoxOffset;
gs_param_float_array PDFXBleedBoxToTrimBoxOffset;
bool PDFXSetBleedBoxToMediaBox;
+ /* OCR Parameters */
+ char ocr_language[1024];
+ int ocr_engine;
/* Other parameters */
bool ReAssignCharacters;
bool ReEncodeCharacters;
@@ -838,6 +868,7 @@ struct gx_device_pdf_s {
gs_id image_mask_id;
bool image_mask_is_SMask;
bool image_mask_skip; /* A flag for pdf_begin_transparency_mask */
+ bool smask_construction; /* True when pdfwrite is constructing a soft mask */
uint image_with_SMask; /* A flag for pdf_begin_transparency_group. In order to
* deal with nested groups we set/test the bit according
* to the FormDepth
@@ -863,6 +894,7 @@ struct gx_device_pdf_s {
bool DetectDuplicateImages;
bool AllowIncrementalCFF;
bool WantsToUnicode;
+ bool PdfmarkCapable;
bool WantsPageLabels;
bool AllowPSRepeatFunctions;
bool IsDistiller;
@@ -907,6 +939,13 @@ struct gx_device_pdf_s {
* anything in the image processing routines.
*/
float UserUnit;
+ pdf_OCR_usage UseOCR; /* Never, AsNeeded or Always */
+ gs_text_enum_t* OCRSaved; /* Saved state of the text enumerator before rendering glyph bitmaps for later OCR */
+ pdf_OCR_stage OCRStage; /* Used to control a (sort of) state machine when using OCR to get a Unicode value for a glyph */
+ int *OCRUnicode; /* Used to pass back the Unicode value from the OCR engine to the text processing */
+ gs_char OCR_char_code; /* Passes the current character code from text processing to the image processing code when rendering glyph bitmaps for OCR */
+ gs_glyph OCR_glyph; /* Passes the current glyph code from text processing to the image processing code when rendering glyph bitmaps for OCR */
+ ocr_glyph_t *ocr_glyphs; /* Records bitmaps and other data from text processing when doing OCR */
};
#define is_in_page(pdev)\
diff --git a/devices/vector/gdevpdt.c b/devices/vector/gdevpdt.c
index 970dd76a..754737ac 100644
--- a/devices/vector/gdevpdt.c
+++ b/devices/vector/gdevpdt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdt.h b/devices/vector/gdevpdt.h
index ee7a1c1e..1ce7e1d6 100644
--- a/devices/vector/gdevpdt.h
+++ b/devices/vector/gdevpdt.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtb.c b/devices/vector/gdevpdtb.c
index 61961c4a..c0a148c3 100644
--- a/devices/vector/gdevpdtb.c
+++ b/devices/vector/gdevpdtb.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -29,6 +29,7 @@
#include "gdevpdfo.h"
#include "gdevpdtb.h"
#include "gdevpdtf.h"
+#include "gdevpdtd.h"
#include "smd5.h"
#include "gxfcache.h" /* for gs_purge_font_from_char_caches_completely */
/*
@@ -372,7 +373,7 @@ pdf_base_font_alloc(gx_device_pdf *pdev, pdf_base_font_t **ppbfont,
*ppbfont = pbfont;
return 0;
fail:
- gs_free_object(mem, pbfont, "pdf_base_font_alloc");
+ pdf_base_font_free(pdev, pbfont);
return code;
}
@@ -412,6 +413,11 @@ pdf_base_font_is_subset(const pdf_base_font_t *pbfont)
void
pdf_base_font_drop_complete(pdf_base_font_t *pbfont)
{
+ /* gs_font is a subset of gs_font_base and we only want to
+ * free the members which are common to both, so this cast is
+ * (at the time of writing) safe.
+ */
+ gs_free_copied_font((gs_font *)pbfont->complete);
pbfont->complete = NULL;
}
@@ -654,11 +660,18 @@ pdf_write_embedded_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, font_type
/* Write the type 1 font with no converting to CFF. */
int lengths[3];
- code = psf_write_type1_font(writer.binary.strm,
+ if (pbfont->do_subset != DO_SUBSET_NO)
+ code = psf_write_type1_font(writer.binary.strm,
(gs_font_type1 *)out_font,
WRITE_TYPE1_WITH_LENIV | WRITE_TYPE1_EEXEC |
WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_ASCIIHEX,
NULL, 0, &fnstr, lengths);
+ else
+ code = psf_write_type1_font(writer.binary.strm,
+ (gs_font_type1 *)out_font,
+ WRITE_TYPE1_WITH_LENIV | WRITE_TYPE1_EEXEC |
+ WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_ASCIIHEX | WRITE_TYPE1_XUID,
+ NULL, 0, &fnstr, lengths);
if (lengths[0] > 0) {
if (code < 0)
goto finish;
@@ -689,7 +702,8 @@ pdf_write_embedded_font(gx_device_pdf *pdev, pdf_base_font_t *pbfont, font_type
code = psf_write_type2_font(writer.binary.strm,
(gs_font_type1 *)out_font,
TYPE2_OPTIONS |
- (pdev->CompatibilityLevel < 1.3 ? WRITE_TYPE2_AR3 : 0),
+ (pdev->CompatibilityLevel < 1.3 ? WRITE_TYPE2_AR3 : 0) |
+ (pbfont->do_subset == DO_SUBSET_NO ? WRITE_TYPE2_XUID : 0),
NULL, 0, &fnstr, FontBBox);
}
goto finish;
diff --git a/devices/vector/gdevpdtb.h b/devices/vector/gdevpdtb.h
index 8753aa98..e8540c28 100644
--- a/devices/vector/gdevpdtb.h
+++ b/devices/vector/gdevpdtb.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtc.c b/devices/vector/gdevpdtc.c
index 5c6da535..c2b76b7c 100644
--- a/devices/vector/gdevpdtc.c
+++ b/devices/vector/gdevpdtc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtd.c b/devices/vector/gdevpdtd.c
index ce6efa05..33cb012b 100644
--- a/devices/vector/gdevpdtd.c
+++ b/devices/vector/gdevpdtd.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -221,10 +221,8 @@ pdf_font_descriptor_alloc(gx_device_pdf *pdev, pdf_font_descriptor_t **ppfd,
return 0;
}
-int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
+int pdf_base_font_free(gx_device_pdf *pdev, pdf_base_font_t *pbfont)
{
- pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
- pdf_base_font_t *pbfont = pfd->base_font;
gs_font *copied = NULL, *complete = NULL;
if (pbfont) {
@@ -239,14 +237,27 @@ int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
gs_free_copied_font(copied);
if (pbfont) {
+ if (pbfont->CIDSet)
+ gs_free_object(pdev->pdf_memory, pbfont->CIDSet, "Free base font CIDSet from FontDescriptor)");
+
if (pbfont->font_name.size) {
gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string");
pbfont->font_name.data = (byte *)0L;
pbfont->font_name.size = 0;
}
- gs_free_object(cos_object_memory(pres->object), pbfont, "Free base font from FontDescriptor)");
- pfd->base_font = 0;
+ gs_free_object(pdev->pdf_memory, pbfont, "Free base font from FontDescriptor)");
}
+ return 0;
+}
+
+int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
+{
+ pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
+ pdf_base_font_t *pbfont = pfd->base_font;
+
+ pdf_base_font_free(pdev, pbfont);
+ pfd->base_font = 0;
+
if (pres->object) {
gs_free_object(pdev->pdf_memory, pres->object, "free FontDescriptor object");
pres->object = NULL;
diff --git a/devices/vector/gdevpdtd.h b/devices/vector/gdevpdtd.h
index 92e64758..abf76552 100644
--- a/devices/vector/gdevpdtd.h
+++ b/devices/vector/gdevpdtd.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -104,6 +104,8 @@ int pdf_font_descriptor_alloc(gx_device_pdf *pdev,
pdf_font_descriptor_t **ppfd,
gs_font_base *font, bool embed);
+int pdf_base_font_free(gx_device_pdf *pdev, pdf_base_font_t *pbfont);
+
int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres);
/*
diff --git a/devices/vector/gdevpdte.c b/devices/vector/gdevpdte.c
index 6f0eb158..7a6b145e 100644
--- a/devices/vector/gdevpdte.c
+++ b/devices/vector/gdevpdte.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -43,6 +43,7 @@
#include "gxcpath.h"
#include "gsfcmap.h"
+#include "tessocr.h"
static int pdf_char_widths(gx_device_pdf *const pdev,
pdf_font_resource_t *pdfont, int ch,
@@ -80,6 +81,216 @@ pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
return pdf_process_string(penum, pstr, pfmat, ppts, gdata);
}
+static int OCRText(gx_device_pdf *pdev, gs_glyph glyph, gs_char ch, gs_char *length, byte **unicode)
+{
+#if OCR_VERSION > 0
+ int code = 0;
+
+ if(pdev->OCRStage == OCR_Rendered) {
+ int llx, lly, urx, ury, char_count = 0, returned_count = 0, *returned;
+ ocr_glyph_t *next_glyph = pdev->ocr_glyphs;
+ int rows, stride, row, column;
+ byte *bitmap = NULL, *src, *dest, *rowptr, srcmask, destmask;
+ void *state;
+ const char *language = pdev->ocr_language;
+ gp_file *DbgFile;
+
+ if(language == NULL || language[0] == 0)
+ language = "eng";
+
+ /* We should alredy have rendered a bitmap for all the glyphs in the
+ * text operation, so this shuld be redundant, but best to be safe.
+ */
+ if(next_glyph == NULL)
+ return_error(gs_error_unknownerror);
+
+ /* Identify the bounding box of the returned glyphs by examing the bounds and position
+ * of each glyph. At the same time count the number of expected returned characters.
+ * We treat any empty bitmap (all 0x00 bytes) as a space because, obviously, the
+ * OCR engine can't tell differentiate between a space character and no character at all.
+ */
+ llx = next_glyph->x;
+ lly = next_glyph->y;
+ urx = llx + next_glyph->width;
+ ury = lly + next_glyph->height;
+ if(next_glyph != NULL && !next_glyph->is_space)
+ char_count++;
+ next_glyph = (ocr_glyph_t *)next_glyph->next;
+ while(next_glyph) {
+ if(!next_glyph->is_space)
+ char_count++;
+ if(next_glyph->x < llx)
+ llx = next_glyph->x;
+ if(next_glyph->y < lly)
+ lly = next_glyph->y;
+ if(next_glyph->x + next_glyph->width > urx)
+ urx = next_glyph->x + next_glyph->width;
+ if(next_glyph->y + next_glyph->height > ury)
+ ury = next_glyph->y + next_glyph->height;
+ next_glyph = next_glyph->next;
+ }
+
+ /* Allocate and initialise the 'strip' bitmap which will receive all the
+ * individual glyph bitmaps.
+ */
+ rows = ury - lly;
+ stride = (((urx - llx) + 7) / 8) + 1;
+ bitmap = gs_alloc_bytes(pdev->memory, rows * stride, "working OCR memory");
+ if(bitmap == NULL)
+ return_error(gs_error_VMerror);
+ memset(bitmap, 0x00, rows * stride);
+
+ /* Allocate a buffer for the OCR engine to return the Unicode code points. This needs work,
+ * we might want more information returned (bounding boxes and confidence levels) and we
+ * need to think about the possibility that the OCR engine finds more character than we
+ * expected (eg fi ligatures returned as 'f' and 'i'.
+ */
+ returned = (int *)gs_alloc_bytes(pdev->memory, char_count * sizeof(int), "returned unicodes");
+ if(returned == NULL) {
+ gs_free_object(pdev->memory, bitmap, "working OCR memory");
+ return_error(gs_error_VMerror);
+ }
+ memset(returned, 0x00, char_count * sizeof(int));
+
+ /* Now copy each glyph bitmap to the correct position in the strip. This is complicated
+ * by the fact that bitmaps are monochrome pcaked into bytes and so the destination
+ * may not be aligned on a byte boundary.
+ */
+ next_glyph = (ocr_glyph_t *)pdev->ocr_glyphs;
+ while(next_glyph) {
+ rowptr = bitmap + ((next_glyph->y - lly) * stride) + (int)floor((next_glyph->x - llx) / 8);
+ for(row = 0;row < next_glyph->height;row++) {
+ dest = rowptr + row * stride;
+ src = next_glyph->data + (row * next_glyph->raster);
+ destmask = 0x80 >> (next_glyph->x - llx) % 8;
+ srcmask = 0x80;
+ for(column = 0; column < next_glyph->width;column++) {
+ if(*src & srcmask) {
+ *dest = *dest | destmask;
+ }
+ srcmask = srcmask >> 1;
+ if(srcmask == 0) {
+ srcmask = 0x80;
+ src++;
+ }
+ destmask = destmask >> 1;
+ if(destmask == 0) {
+ destmask = 0x80;
+ dest++;
+ }
+ }
+ }
+ next_glyph = next_glyph->next;
+ }
+
+#if 0
+ DbgFile = gp_fopen(pdev->memory, "d:/temp/bits.txt", "wb+");
+ for(row = 0;row < rows;row++) {
+ for(column = 0;column < stride;column++) {
+ dest = bitmap + (row * stride);
+ gp_fprintf(DbgFile, "%02x", dest[column]);
+ }
+ gp_fprintf(DbgFile, "\n");
+ }
+ gp_fclose(DbgFile);
+#endif
+ /* Initialise the OCR engine */
+ code = ocr_init_api(pdev->memory->non_gc_memory, language,
+ pdev->ocr_engine, &state);
+ if(code < 0) {
+ gs_free_object(pdev->memory, bitmap, "working OCR memory");
+ gs_free_object(pdev->memory, returned, "returned unicodes");
+ return 0;
+ }
+ returned_count = char_count;
+
+ /* Pass our strip to the OCR engine */
+ code = ocr_bitmap_to_unicodes(state,
+ bitmap, 0, stride * 8, rows, stride,
+ (int)pdev->HWResolution[0],
+ (int)pdev->HWResolution[1],
+ returned, &returned_count);
+
+ /* and close the engine back down again */
+ ocr_fin_api(pdev->memory->non_gc_memory, state);
+ gs_free_object(pdev->memory, bitmap, "working OCR memory");
+
+ if(code < 0) {
+ pdev->OCRStage = OCR_Failed;
+ gs_free_object(pdev->memory, returned, "returned unicodes");
+ return code;
+ }
+
+ /* Future enhancement we should fall back to trying the individual bitmap here */
+ if(returned_count != char_count) {
+ pdev->OCRStage = OCR_Failed;
+ gs_free_object(pdev->memory, returned, "returned unicodes");
+ return 0;
+ }
+ pdev->OCRUnicode = returned;
+
+ /* Actually perform OCR on the stored bitmaps */
+ pdev->OCRStage = OCR_UnicodeAvailable;
+ }
+
+ if(pdev->OCRStage == OCR_UnicodeAvailable) {
+ /* We've OCR'ed the bitmaps already, find the unicode value */
+ ocr_glyph_t *new_glyph = (ocr_glyph_t *)pdev->ocr_glyphs;
+ int ocr_index = 0;
+ uint mask = 0xFF;
+ int ix;
+ char *u;
+
+ /* Find the bitmap which matches the character/glyph we are processing */
+ while(new_glyph) {
+ if(new_glyph->char_code == ch || new_glyph->glyph == glyph) {
+ ocr_glyph_t *g1 = pdev->ocr_glyphs;
+
+ /* Spaces are handled specially, so just jump out now */
+ if(new_glyph->is_space)
+ break;
+
+ /* Otherwise, find all the bitmaps which lie to the left of the
+ * one we found (we are assuming for now that the returned
+ * Unicode values are left to right)
+ */
+ while(g1) {
+ if(!g1->is_space) {
+ if(g1->x < new_glyph->x)
+ ocr_index++;
+ }
+ g1 = g1->next;
+ }
+ break;
+ }
+ new_glyph = new_glyph->next;
+ }
+
+ /* If we found a matching bitmap, get the corresponding unicode code point from
+ * the stored values returned by the OCR engine.
+ */
+ if(new_glyph) {
+ *unicode = (byte *)gs_alloc_bytes(pdev->memory, 2 * sizeof(ushort), "temporary Unicode array");
+ if(*unicode == NULL)
+ return_error(gs_error_VMerror);
+ u = (char *)(*unicode);
+ if(new_glyph->is_space) {
+ memset(u, 0x00, 3);
+ u[3] = 0x20;
+ }
+ else {
+ for(ix = 0;ix < 4;ix++) {
+ u[3 - ix] = (pdev->OCRUnicode[ocr_index] & mask) >> (8 * ix);
+ mask = mask << 8;
+ }
+ }
+ *length = 4;
+ }
+ }
+ #endif
+ return 0;
+}
+
/*
* Add char code pair to ToUnicode CMap,
* creating the CMap on neccessity.
@@ -87,27 +298,43 @@ pdf_process_string_aux(pdf_text_enum_t *penum, gs_string *pstr,
int
pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfont,
gs_glyph glyph, gs_char ch, const gs_const_string *gnstr)
-{ int code;
- gs_char length;
+{ int code = 0;
+ gs_char length = 0;
ushort *unicode = 0;
if (glyph == GS_NO_GLYPH)
return 0;
- length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
- if ((length == 0 || length == GS_NO_CHAR) && gnstr != NULL && gnstr->size == 7) {
- if (!memcmp(gnstr->data, "uni", 3)) {
- static const char *hexdigits = "0123456789ABCDEF";
- char *d0 = strchr(hexdigits, gnstr->data[3]);
- char *d1 = strchr(hexdigits, gnstr->data[4]);
- char *d2 = strchr(hexdigits, gnstr->data[5]);
- char *d3 = strchr(hexdigits, gnstr->data[6]);
-
- unicode = (ushort *)gs_alloc_bytes(pdev->memory, sizeof(ushort), "temporary Unicode array");
- if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
- char *u = (char *)unicode;
- u[0] = ((d0 - hexdigits) << 4) + ((d1 - hexdigits));
- u[1] = ((d2 - hexdigits) << 4) + ((d3 - hexdigits));
- length = 2;
+ if(pdev->UseOCR == UseOCRAlways) {
+ code = OCRText(pdev, glyph, ch, &length, (byte **)&unicode);
+ if(code < 0)
+ return code;
+ }
+ else {
+ length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
+ if(length == 0 || length == GS_NO_CHAR) {
+ if(gnstr != NULL && gnstr->size == 7) {
+ if(!memcmp(gnstr->data, "uni", 3)) {
+ static const char *hexdigits = "0123456789ABCDEF";
+ char *d0 = strchr(hexdigits, gnstr->data[3]);
+ char *d1 = strchr(hexdigits, gnstr->data[4]);
+ char *d2 = strchr(hexdigits, gnstr->data[5]);
+ char *d3 = strchr(hexdigits, gnstr->data[6]);
+
+ unicode = (ushort *)gs_alloc_bytes(pdev->memory, sizeof(ushort), "temporary Unicode array");
+ if(d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
+ char *u = (char *)unicode;
+ u[0] = ((d0 - hexdigits) << 4) + ((d1 - hexdigits));
+ u[1] = ((d2 - hexdigits) << 4) + ((d3 - hexdigits));
+ length = 2;
+ }
+ }
+ }
+ else {
+ if(pdev->UseOCR != UseOCRNever) {
+ code = OCRText(pdev, glyph, ch, &length, (byte **)&unicode);
+ if(code < 0)
+ return code;
+ }
}
}
}
@@ -163,6 +390,7 @@ pdf_add_ToUnicode(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_t *pdfon
if (length > 2 && pdfont->u.simple.Encoding != NULL)
pdfont->TwoByteToUnicode = 0;
}
+
if (unicode)
gs_free_object(pdev->memory, unicode, "temporary Unicode array");
return 0;
@@ -255,8 +483,11 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_
pet = &pdfont->u.simple.Encoding[ch];
glyph = (gdata == NULL ? font->procs.encode_char(font, ch, GLYPH_SPACE_NAME)
: *gdata);
- if (glyph == GS_NO_GLYPH || glyph == pet->glyph)
+ if (glyph == GS_NO_GLYPH || glyph == pet->glyph) {
+ if((pdfont->cmap_ToUnicode == NULL || !gs_cmap_ToUnicode_check_pair(pdfont->cmap_ToUnicode, ch)) && pdev->UseOCR != UseOCRNever)
+ (void)pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
return 0;
+ }
if (pet->glyph != GS_NO_GLYPH) { /* encoding conflict */
return_error(gs_error_rangecheck);
/* Must not happen because pdf_obtain_font_resource
@@ -358,7 +589,7 @@ pdf_encode_string_element(gx_device_pdf *pdev, gs_font *font, pdf_font_resource_
* The decision about writing it out is deferred until pdf_write_font_resource.
*/
code = pdf_add_ToUnicode(pdev, font, pdfont, glyph, ch, &gnstr);
- if (code < 0)
+ if(code < 0)
return code;
pet->glyph = glyph;
pet->str = gnstr;
@@ -1035,6 +1266,7 @@ process_text_return_width(const pdf_text_enum_t *pte, gs_font_base *font,
{ const gs_glyph *gdata_i = (gdata != NULL ? gdata + i : 0);
code = pdf_encode_string_element(pdev, (gs_font *)font, pdfont, ch, gdata_i);
+
if (code < 0)
return code;
}
diff --git a/devices/vector/gdevpdtf.c b/devices/vector/gdevpdtf.c
index c823b18c..0972e02d 100644
--- a/devices/vector/gdevpdtf.c
+++ b/devices/vector/gdevpdtf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -32,6 +32,7 @@
#include "gdevpdtf.h"
#include "gdevpdtw.h"
#include "gdevpdti.h"
+#include "gdevpdfo.h" /* for cos_free() */
#include "whitelst.h" /* Checks whether protected fonta cna be embedded */
#include "gscencs.h"
@@ -336,7 +337,9 @@ pdf_outline_fonts_alloc(gs_memory_t *mem)
pdf_standard_font_t *
pdf_standard_fonts(const gx_device_pdf *pdev)
{
- return pdev->text->outline_fonts->standard_fonts;
+ if (pdev->text != NULL && pdev->text->outline_fonts != NULL)
+ return pdev->text->outline_fonts->standard_fonts;
+ return NULL;
}
/*
@@ -347,7 +350,8 @@ pdf_clean_standard_fonts(const gx_device_pdf *pdev)
{
pdf_standard_font_t *ppsf = pdf_standard_fonts(pdev);
- memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
+ if (ppsf != NULL)
+ memset(ppsf, 0, PDF_NUM_STANDARD_FONTS * sizeof(*ppsf));
}
/* ---------------- Font resources ---------------- */
@@ -471,6 +475,14 @@ int font_resource_free(gx_device_pdf *pdev, pdf_font_resource_t *pdfont)
pdf_free_charproc_ownership(pdev, (pdf_resource_t *)pdfont->u.simple.s.type3.char_procs);
pdfont->u.simple.s.type3.char_procs = 0;
}
+ if (pdfont->u.simple.s.type3.cached) {
+ gs_free_object(pdev->pdf_memory, pdfont->u.simple.s.type3.cached, "Free type 3 cached array");
+ pdfont->u.simple.s.type3.cached = NULL;
+ }
+ if (pdfont->u.simple.s.type3.Resources != NULL) {
+ cos_free((cos_object_t *)pdfont->u.simple.s.type3.Resources, "Free type 3 Resources dictionary");
+ pdfont->u.simple.s.type3.Resources = NULL;
+ }
break;
case ft_CID_encrypted:
case ft_CID_TrueType:
diff --git a/devices/vector/gdevpdtf.h b/devices/vector/gdevpdtf.h
index f0006641..f13c0eac 100644
--- a/devices/vector/gdevpdtf.h
+++ b/devices/vector/gdevpdtf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdti.c b/devices/vector/gdevpdti.c
index 0205604a..d1b39e99 100644
--- a/devices/vector/gdevpdti.c
+++ b/devices/vector/gdevpdti.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -557,7 +557,12 @@ pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
int
pdf_write_bitmap_fonts_Encoding(gx_device_pdf *pdev)
{
- pdf_bitmap_fonts_t *pbfs = pdev->text->bitmap_fonts;
+ pdf_bitmap_fonts_t *pbfs;
+
+ if (pdev->text == NULL || pdev->text->bitmap_fonts == NULL)
+ return 0;
+
+ pbfs = pdev->text->bitmap_fonts;
if (pbfs->bitmap_encoding_id) {
stream *s;
diff --git a/devices/vector/gdevpdti.h b/devices/vector/gdevpdti.h
index 81409e67..ccee9fd2 100644
--- a/devices/vector/gdevpdti.h
+++ b/devices/vector/gdevpdti.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdts.c b/devices/vector/gdevpdts.c
index aa41f516..ec946ac4 100644
--- a/devices/vector/gdevpdts.c
+++ b/devices/vector/gdevpdts.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdts.h b/devices/vector/gdevpdts.h
index b3699eb2..9355473e 100644
--- a/devices/vector/gdevpdts.h
+++ b/devices/vector/gdevpdts.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtt.c b/devices/vector/gdevpdtt.c
index 5884115e..952f41db 100644
--- a/devices/vector/gdevpdtt.c
+++ b/devices/vector/gdevpdtt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -299,13 +299,29 @@ static void
pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
{
pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
+ gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
+ ocr_glyph_t *next;
if (penum->pte_default) {
- gs_text_release(penum->pte_default, cname);
+ gs_text_release(NULL, penum->pte_default, cname);
penum->pte_default = 0;
}
pdf_text_release_cgp(penum);
+
+ while (pdev->ocr_glyphs != NULL)
+ {
+ next = pdev->ocr_glyphs->next;
+
+ gs_free_object(pdev->memory, pdev->ocr_glyphs->data, "free bitmap");
+ gs_free_object(pdev->memory, pdev->ocr_glyphs, "free bitmap");
+ pdev->ocr_glyphs = next;
+ }
+ if (pdev->OCRUnicode != NULL)
+ gs_free_object(pdev->memory, pdev->OCRUnicode, "free returned unicodes");
+ pdev->OCRUnicode = NULL;
+
gx_default_text_release(pte, cname);
+ pdev->OCRStage = 0;
}
void
pdf_text_release_cgp(pdf_text_enum_t *penum)
@@ -591,7 +607,7 @@ gdev_pdf_text_begin(gx_device * dev, gs_gstate * pgs,
if (penum->fstack.items[penum->fstack.depth].font->FontType == 3)
user_defined = 1;
}
- gs_text_release((gs_text_enum_t *)penum, "pdf_text_process");
+ gs_text_release(NULL, (gs_text_enum_t *)penum, "pdf_text_process");
}
if (!user_defined || !(text->operation & TEXT_DO_ANY_CHARPATH)) {
@@ -633,9 +649,12 @@ gdev_pdf_text_begin(gx_device * dev, gs_gstate * pgs,
penum->cdevproc_callout = false;
penum->returned.total_width.x = penum->returned.total_width.y = 0;
penum->cgp = NULL;
+ penum->returned.current_glyph = GS_NO_GLYPH;
penum->output_char_code = GS_NO_CHAR;
code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
dev, pgs, text, font, path, pdcolor, pcpath, mem);
+ penum->k_text_release = 1; /* early release of black_text_state */
+
if (code < 0) {
gs_free_object(mem, penum, "gdev_pdf_text_begin");
return code;
@@ -678,12 +697,23 @@ pdf_font_cache_elem_t **
pdf_locate_font_cache_elem(gx_device_pdf *pdev, gs_font *font)
{
pdf_font_cache_elem_t **e = &pdev->font_cache;
+ pdf_font_cache_elem_t *prev = NULL;
long id = pdf_font_cache_elem_id(font);
- for (; *e != 0; e = &(*e)->next)
+ for (; *e != 0; e = &(*e)->next) {
if ((*e)->font_id == id) {
- return e;
+ if (prev != NULL) {
+ pdf_font_cache_elem_t *curr = *e;
+
+ /* move the curr font to head of list (Most Recently Used) */
+ prev->next = curr->next;
+ curr->next = pdev->font_cache;
+ pdev->font_cache = curr;
+ }
+ return &(pdev->font_cache);
}
+ prev = *e;
+ }
return 0;
}
@@ -757,6 +787,13 @@ alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e,
font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars);
len = (num_chars + 7) / 8;
+ if (e->glyph_usage != NULL)
+ gs_free_object(pdev->pdf_memory, e->glyph_usage,
+ "pdf_attach_font_resource, reallocating");
+ if (e->real_widths != NULL)
+ gs_free_object(pdev->pdf_memory, e->real_widths,
+ "alloc_font_cache_elem_arrays, reallocating");
+
e->glyph_usage = gs_alloc_bytes(pdev->pdf_memory,
len, "alloc_font_cache_elem_arrays");
@@ -3085,7 +3122,7 @@ static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte,
code = gx_default_text_restore_state(pte_default);
if (code < 0)
return code;
- gs_text_release(pte_default, "pdf_text_process");
+ gs_text_release(NULL, pte_default, "pdf_text_process");
penum->pte_default = 0;
return 0;
@@ -3132,6 +3169,57 @@ static int pdf_query_purge_cached_char(const gs_memory_t *mem, cached_char *cc,
return 0;
}
+static int ProcessTextForOCR(gs_text_enum_t *pte)
+{
+ pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
+ gx_device_pdf *pdev = (gx_device_pdf *)penum->dev;
+ gs_text_enum_t *pte_default;
+ int code;
+
+ if (pdev->OCRStage == OCR_UnInit) {
+ gs_gsave(pte->pgs);
+ pdev->OCRSaved = (gs_text_enum_t*)gs_alloc_bytes(pdev->memory,sizeof(gs_text_enum_t),"saved enumerator for OCR");
+ if(pdev->OCRSaved == NULL)
+ return_error(gs_error_VMerror);
+ *(pdev->OCRSaved) = *pte;
+ gs_text_enum_copy_dynamic(pdev->OCRSaved,pte,true);
+
+ code = pdf_default_text_begin(pte, &pte->text, &pte_default);
+ if (code < 0)
+ return code;
+ penum->pte_default = pte_default;
+ gs_text_enum_copy_dynamic(pte_default, pte, false);
+ pdev->OCRStage = OCR_Rendering;
+ }
+
+ if (pdev->OCRStage == OCR_Rendering) {
+ penum->pte_default->can_cache = 0;
+ code = gs_text_process(penum->pte_default);
+ pdev->OCR_char_code = penum->pte_default->returned.current_char;
+ pdev->OCR_glyph = penum->pte_default->returned.current_glyph;
+ gs_text_enum_copy_dynamic(pte, penum->pte_default, true);
+ if (code == TEXT_PROCESS_RENDER)
+ return code;
+ if (code != 0) {
+ gs_free_object(pdev->memory, pdev->OCRSaved,"saved enumerator for OCR");
+ pdev->OCRSaved = NULL;
+ gs_grestore(pte->pgs);
+ gs_text_release(pte->pgs, penum->pte_default, "pdf_text_process");
+ penum->pte_default = NULL;
+ return code;
+ }
+ gs_grestore(pte->pgs);
+ *pte = *(pdev->OCRSaved);
+ gs_text_enum_copy_dynamic(pte, pdev->OCRSaved, true);
+ gs_free_object(pdev->memory, pdev->OCRSaved,"saved enumerator for OCR");
+ pdev->OCRSaved = NULL;
+ gs_text_release(pte->pgs, penum->pte_default, "pdf_text_process");
+ penum->pte_default = NULL;
+ pdev->OCRStage = OCR_Rendered;
+ }
+ return 0;
+}
+
/*
* Continue processing text. This is the 'process' procedure in the text
* enumerator. Per the check in pdf_text_begin, we know the operation is
@@ -3142,7 +3230,7 @@ pdf_text_process(gs_text_enum_t *pte)
{
pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
uint operation = pte->text.operation;
- uint size = pte->text.size - pte->index;
+ uint size = 0;
gs_text_enum_t *pte_default;
PROCESS_TEXT_PROC((*process));
int code = 0, early_accumulator = 0;
@@ -3187,6 +3275,15 @@ pdf_text_process(gs_text_enum_t *pte)
goto default_impl;
}
+ if (pdev->UseOCR != UseOCRNever) {
+ code = ProcessTextForOCR(pte);
+ if (code != 0)
+ return code;
+ }
+
+ operation = pte->text.operation;
+ size = pte->text.size - pte->index;
+
code = -1; /* to force default implementation */
/*
@@ -3352,10 +3449,13 @@ pdf_text_process(gs_text_enum_t *pte)
pdev->procs.get_initial_matrix = pdf_type3_get_initial_matrix;
pdev->pte = (gs_text_enum_t *)penum; /* CAUTION: See comment in gdevpdfx.h . */
+ /* In case of error, text_process will restore back to the enumerator 'level'
+ * we must make certain we do not restore back too far!
+ */
+ pte_default->level = penum->pgs->level;
code = gs_text_process(pte_default);
if (code < 0) {
(void)complete_charproc(pdev, pte, pte_default, penum, false);
- gs_grestore(pgs);
return code;
}
pdev->pte = NULL; /* CAUTION: See comment in gdevpdfx.h . */
@@ -3524,9 +3624,10 @@ pdf_text_process(gs_text_enum_t *pte)
}
gs_text_enum_copy_dynamic(pte, pte_default, true);
+
if (code)
return code;
- gs_text_release(pte_default, "pdf_text_process");
+ gs_text_release(NULL, pte_default, "pdf_text_process");
penum->pte_default = 0;
if (pdev->type3charpath)
pdev->type3charpath = false;
diff --git a/devices/vector/gdevpdtt.h b/devices/vector/gdevpdtt.h
index 9a710151..9d25d48c 100644
--- a/devices/vector/gdevpdtt.h
+++ b/devices/vector/gdevpdtt.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtv.c b/devices/vector/gdevpdtv.c
index a16a48d7..47b9d798 100644
--- a/devices/vector/gdevpdtv.c
+++ b/devices/vector/gdevpdtv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtv.h b/devices/vector/gdevpdtv.h
index 5e27ecd1..54db170c 100644
--- a/devices/vector/gdevpdtv.h
+++ b/devices/vector/gdevpdtv.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtw.c b/devices/vector/gdevpdtw.c
index 6d197bd5..19438685 100644
--- a/devices/vector/gdevpdtw.c
+++ b/devices/vector/gdevpdtw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtw.h b/devices/vector/gdevpdtw.h
index 34feeed2..0bf3526d 100644
--- a/devices/vector/gdevpdtw.h
+++ b/devices/vector/gdevpdtw.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpdtx.h b/devices/vector/gdevpdtx.h
index d5fe6177..43ecca3d 100644
--- a/devices/vector/gdevpdtx.h
+++ b/devices/vector/gdevpdtx.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsdf.h b/devices/vector/gdevpsdf.h
index a20c61b0..700278e2 100644
--- a/devices/vector/gdevpsdf.h
+++ b/devices/vector/gdevpsdf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsdi.c b/devices/vector/gdevpsdi.c
index f093edf1..8ac9735a 100644
--- a/devices/vector/gdevpsdi.c
+++ b/devices/vector/gdevpsdi.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -33,12 +33,6 @@
#include "spngpx.h"
#include "szlibx.h"
#include "gsicc_manage.h"
-#ifdef USE_LDF_JB2
-#include "sjbig2_luratech.h"
-#endif
-#ifdef USE_LWF_JP2
-#include "sjpx_luratech.h"
-#endif
#include "sisparam.h"
/* Define parameter-setting procedures. */
@@ -250,10 +244,6 @@ setup_image_compression(psdf_binary_writer *pbw, const psdf_image_params *pdip,
stream_state *st;
int code;
-# ifdef USE_LWF_JP2
- if (lossless && templat == &s_jpxe_template && !Indexed)
- lossless_template = &s_jpxe_template;
-# endif
if (!pdip->Encode) /* no compression */
return 0;
if (pdip->AutoFilter) {
@@ -356,41 +346,6 @@ setup_image_compression(psdf_binary_writer *pbw, const psdf_image_params *pdip,
goto fail;
/* psdf_DCT_filter already did the psdf_encode_binary. */
return 0;
- } else {
-# ifdef USE_LDF_JB2
- if (templat == &s_jbig2encode_template) {
- stream_jbig2encode_state *state = (stream_jbig2encode_state *)st;
-
- state->width = pim->Width;
- state->height = pim->Height;
- }
-# endif
-# ifdef USE_LWF_JP2
- if (templat == &s_jpxe_template) {
- stream_jpxe_state *state = (stream_jpxe_state *)st;
- int ncomps = pim->ColorSpace->type->num_components(pim->ColorSpace);
-
- /* HACK : We choose a JPX color space from the number of components :
- CIEBasedA goes as gs_jpx_cs_gray,
- CIEBasedABC and DeviceN(3) go as gs_jpx_cs_rgb,
- CIEBasedABCD and DeviceN(4) go as gs_jpx_cs_cmyk.
- */
- switch (ncomps) {
- case 1 : state->colorspace = gs_jpx_cs_gray; break;
- case 3 : state->colorspace = gs_jpx_cs_rgb; break;
- case 4 : state->colorspace = gs_jpx_cs_cmyk; break;
- default:
- return_error(gs_error_unregistered); /* Must not happen. */
- }
- state->width = pim->Width;
- state->height = pim->Height;
- state->bpc = pim->BitsPerComponent;
- state->components = ncomps;
- state->lossless = lossless;
- /* Other encode parameters are not implemented yet.
- Therefore ACSDict is being ignored. */
- }
-# endif
}
code = psdf_encode_binary(pbw, templat, st);
if (code >= 0)
@@ -600,39 +555,6 @@ psdf_is_converting_image_to_RGB(const gx_device_psdf * pdev,
gs_color_space_index_DeviceCMYK));
}
-static inline void
-adjust_auto_filter_strategy(gx_device_psdf *pdev,
- psdf_image_params *params, gs_c_param_list *plist,
- const gs_pixel_image_t * pim, bool in_line)
-{
-#ifdef USE_LWF_JP2
- if (!in_line && params->Depth > 1 && pdev->ParamCompatibilityLevel >= 1.5 &&
- pim->ColorSpace->type->index != gs_color_space_index_Indexed &&
- params->AutoFilter &&
- params->AutoFilterStrategy != af_Jpeg) {
- params->Filter = "/JPXEncode";
- params->filter_template = &s_jpxe_template;
- params->Dict = plist;
- }
-#endif
-}
-
-static inline void
-adjust_auto_filter_strategy_mono(gx_device_psdf *pdev,
- psdf_image_params *params, gs_c_param_list *plist,
- const gs_pixel_image_t * pim, bool in_line)
-{
-#ifdef USE_LDF_JB2
- if (!in_line && pdev->ParamCompatibilityLevel >= 1.5 &&
- params->AutoFilter &&
- pim->ColorSpace->type->index != gs_color_space_index_Indexed) {
- params->Filter = "/JBIG2Encode";
- params->filter_template = &s_jbig2encode_template;
- params->Dict = plist;
- }
-#endif
-}
-
/* Set up compression and downsampling filters for an image. */
/* Note that this may modify the image parameters. */
int
@@ -714,16 +636,13 @@ psdf_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw,
params.Filter = pdev->params.MonoImage.Filter;
params.filter_template = pdev->params.MonoImage.filter_template;
params.Dict = pdev->params.MonoImage.Dict;
- adjust_auto_filter_strategy_mono(pdev, &params, pdev->params.MonoImage.Dict, pim, in_line);
} else {
params.Filter = pdev->params.GrayImage.Filter;
params.filter_template = pdev->params.GrayImage.filter_template;
params.Dict = pdev->params.GrayImage.Dict;
- adjust_auto_filter_strategy(pdev, &params, pdev->params.GrayImage.Dict, pim, in_line);
}
code = setup_downsampling(pbw, &params, pim, pgs, resolution, lossless);
} else {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.GrayImage.Dict, pim, in_line);
code = setup_image_compression(pbw, &params, pim, pgs, lossless);
}
if (code < 0)
@@ -745,10 +664,8 @@ psdf_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw,
if (params.Depth == -1)
params.Depth = (cmyk_to_rgb ? 8 : bpc_out);
if (do_downsample(&params, pim, resolution)) {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.ColorImage.Dict, pim, in_line);
code = setup_downsampling(pbw, &params, pim, pgs, resolution, lossless);
} else {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.ColorImage.Dict, pim, in_line);
code = setup_image_compression(pbw, &params, pim, pgs, lossless);
}
if (code < 0)
@@ -981,17 +898,16 @@ new_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw,
params.Filter = pdev->params.MonoImage.Filter;
params.filter_template = pdev->params.MonoImage.filter_template;
params.Dict = pdev->params.MonoImage.Dict;
- adjust_auto_filter_strategy_mono(pdev, &params, pdev->params.MonoImage.Dict, pim, in_line);
} else {
+ if (params.Depth > 8)
+ params.Depth = bpc_out;
params.Filter = pdev->params.GrayImage.Filter;
params.filter_template = pdev->params.GrayImage.filter_template;
params.Dict = pdev->params.GrayImage.Dict;
- adjust_auto_filter_strategy(pdev, &params, pdev->params.GrayImage.Dict, pim, in_line);
}
pdev->JPEG_PassThrough = 0;
code = setup_downsampling(pbw, &params, pim, pgs, resolution, lossless);
} else {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.GrayImage.Dict, pim, in_line);
code = setup_image_compression(pbw, &params, pim, pgs, lossless);
}
if (code < 0)
@@ -1002,11 +918,9 @@ new_setup_image_filters(gx_device_psdf * pdev, psdf_binary_writer * pbw,
if (params.Depth == -1)
params.Depth = (colour_conversion ? 8 : bpc_out);
if (do_downsample(&params, pim, resolution)) {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.ColorImage.Dict, pim, in_line);
pdev->JPEG_PassThrough = 0;
code = setup_downsampling(pbw, &params, pim, pgs, resolution, lossless);
} else {
- adjust_auto_filter_strategy(pdev, &params, pdev->params.ColorImage.Dict, pim, in_line);
code = setup_image_compression(pbw, &params, pim, pgs, lossless);
}
if (code < 0)
diff --git a/devices/vector/gdevpsdp.c b/devices/vector/gdevpsdp.c
index c8a48ee5..d995dc5c 100644
--- a/devices/vector/gdevpsdp.c
+++ b/devices/vector/gdevpsdp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -30,12 +30,6 @@
#include "srlx.h"
#include "szlibx.h"
#include "gdevvec.h"
-#ifdef USE_LDF_JB2
-#include "sjbig2_luratech.h"
-#endif
-#ifdef USE_LWF_JP2
-#include "sjpx_luratech.h"
-#endif
/* Define a (bogus) GC descriptor for gs_param_string. */
/* The only ones we use are GC-able and not persistent. */
@@ -98,9 +92,6 @@ static const psdf_image_filter_name Poly_filters[] = {
{"DCTEncode", &s_DCTE_template},
{"FlateEncode", &s_zlibE_template, psdf_version_ll3},
{"LZWEncode", &s_LZWE_template},
-#ifdef USE_LWF_JP2
- {"JPXEncode", &s_jpxe_template},
-#endif
{0, 0}
};
@@ -109,9 +100,6 @@ static const psdf_image_filter_name Mono_filters[] = {
{"FlateEncode", &s_zlibE_template, psdf_version_ll3},
{"LZWEncode", &s_LZWE_template},
{"RunLengthEncode", &s_RLE_template},
-#ifdef USE_LDF_JB2
- {"JBIG2Encode", &s_jbig2encode_template},
-#endif
{0, 0}
};
@@ -415,12 +403,6 @@ int gdev_psdf_get_image_param(gx_device_psdf *pdev, const psdf_image_param_names
(params->Filter == 0 ?
image_names->filter_names[0].pname :
params->Filter));
-#ifdef USE_LWF_JP2
- if (image_names->AutoFilterStrategy != 0)
- if (strcmp(Param, image_names->AutoFilterStrategy) == 0)
- return psdf_write_name(plist, image_names->AutoFilterStrategy,
- AutoFilterStrategy_names[params->AutoFilterStrategy]);
-#endif
return_error(gs_error_undefined);
}
int
@@ -1055,11 +1037,8 @@ psdf_put_image_params(const gx_device_psdf * pdev, gs_param_list * plist,
*/
static int psdf_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, gs_param_string_array *sa, gs_param_string_array *da)
{
- int code;
-
if (sa->size > 0) {
int ix;
- byte **dest;
if (da->data != NULL) {
for (ix = 0; ix < da->size;ix++)
@@ -1088,7 +1067,7 @@ static int psdf_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist,
return 0;
}
-static int psdf_read_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, char *Key, gs_param_string_array *da)
+static int psdf_read_copy_param_string_array(gs_memory_t *mem, gs_param_list * plist, const char *Key, gs_param_string_array *da)
{
gs_param_string_array sa;
int code;
diff --git a/devices/vector/gdevpsds.c b/devices/vector/gdevpsds.c
index bc932902..6be0dd67 100644
--- a/devices/vector/gdevpsds.c
+++ b/devices/vector/gdevpsds.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsds.h b/devices/vector/gdevpsds.h
index 207e54c4..44e2e845 100644
--- a/devices/vector/gdevpsds.h
+++ b/devices/vector/gdevpsds.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsdu.c b/devices/vector/gdevpsdu.c
index c4be6ac0..c4957691 100644
--- a/devices/vector/gdevpsdu.c
+++ b/devices/vector/gdevpsdu.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -408,8 +408,8 @@ psdf_DCT_filter(gs_param_list *plist /* may be NULL */,
/* Make sure we get at least a full scan line of input. */
ss->scan_line_size = jcdp->cinfo.input_components *
jcdp->cinfo.image_width;
- /* Profile not used in pdfwrite output */
- ss->icc_profile = NULL;
+ /* Profile not used in pdfwrite output */
+ ss->icc_profile = NULL;
jcdp->templat.min_in_size =
max(s_DCTE_template.min_in_size, ss->scan_line_size);
/* Make sure we can write the user markers in a single go. */
@@ -510,10 +510,6 @@ psdf_create_compositor(
if (gs_is_overprint_compositor(pct)) {
*pcdev = dev;
return 0;
- } else {
- if (dev->parent)
- return gx_default_create_compositor(dev->parent, pcdev, pct, pgs, mem, cdev);
- else
- return gx_default_create_compositor(dev, pcdev, pct, pgs, mem, cdev);
}
+ return gx_default_create_compositor(dev, pcdev, pct, pgs, mem, cdev);
}
diff --git a/devices/vector/gdevpsf.h b/devices/vector/gdevpsf.h
index 9105eb86..6db85801 100644
--- a/devices/vector/gdevpsf.h
+++ b/devices/vector/gdevpsf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -166,6 +166,7 @@ int psf_get_type1_glyphs(psf_outline_glyphs_t *pglyphs,
#define WRITE_TYPE1_EEXEC_MARK 8 /* assume 512 0s will be added */
#define WRITE_TYPE1_POSTSCRIPT 16 /* don't observe ATM restrictions */
#define WRITE_TYPE1_WITH_LENIV 32 /* don't allow lenIV = -1 */
+#define WRITE_TYPE1_XUID 64
int psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
gs_glyph *subset_glyphs, uint subset_size,
const gs_const_string *alt_font_name,
@@ -181,6 +182,7 @@ int psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
#define WRITE_TYPE2_CHARSTRINGS 2 /* convert T1 charstrings to T2 */
#define WRITE_TYPE2_AR3 4 /* work around bugs in Acrobat Reader 3 */
#define WRITE_TYPE2_NO_GSUBRS 8 /* omit GlobalSubrs */
+#define WRITE_TYPE2_XUID 16
int psf_write_type2_font(stream *s, gs_font_type1 *pfont, int options,
gs_glyph *subset_glyphs, uint subset_size,
const gs_const_string *alt_font_name,
diff --git a/devices/vector/gdevpsf1.c b/devices/vector/gdevpsf1.c
index feed79eb..672ce241 100644
--- a/devices/vector/gdevpsf1.c
+++ b/devices/vector/gdevpsf1.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -75,13 +75,19 @@ write_float_array(gs_param_list *plist, const char *key, const float *values,
/* Write a UniqueID and/or XUID. */
static void
-write_uid(stream *s, const gs_uid *puid)
+write_uid(stream *s, const gs_uid *puid, int options)
{
if (uid_is_UniqueID(puid))
pprintld1(s, "/UniqueID %ld def\n", puid->id);
- else if (uid_is_XUID(puid)) {
+ else if (uid_is_XUID(puid) && (options & WRITE_TYPE1_XUID) != 0) {
uint i, n = uid_XUID_size(puid);
+ /* Adobe products (specifically Acrobat but the same limitation is mentioned
+ * in the PLRM) cannot handle XUIDs > 16 entries.
+ */
+ if (n > 16)
+ n = 16;
+
stream_puts(s, "/XUID [");
for (i = 0; i < n; ++i)
pprintld1(s, "%ld ", uid_XUID_values(puid)[i]);
@@ -530,7 +536,7 @@ write_Private(stream *s, gs_font_type1 *pfont,
gs_glyph *subset_glyphs, uint subset_size,
gs_glyph notdef, int lenIV,
int (*write_CharString)(stream *, const void *, uint),
- const param_printer_params_t *ppp)
+ const param_printer_params_t *ppp, int options)
{
const gs_type1_data *const pdata = &pfont->data;
printer_param_list_t rlist;
@@ -596,7 +602,7 @@ write_Private(stream *s, gs_font_type1 *pfont,
write_float_array(plist, "StemSnapV", pdata->StemSnapV.values,
pdata->StemSnapV.count);
}
- write_uid(s, &pfont->UID);
+ write_uid(s, &pfont->UID, options);
stream_puts(s, "/MinFeature{16 16} def\n");
stream_puts(s, "/password 5839 def\n");
@@ -860,7 +866,7 @@ psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
pfont->FontMatrix.xx, pfont->FontMatrix.xy,
pfont->FontMatrix.yx, pfont->FontMatrix.yy,
pfont->FontMatrix.tx, pfont->FontMatrix.ty);
- write_uid(s, &pfont->UID);
+ write_uid(s, &pfont->UID, options);
pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n",
pfont->FontBBox.p.x, pfont->FontBBox.p.y,
pfont->FontBBox.q.x, pfont->FontBBox.q.y);
@@ -929,7 +935,7 @@ psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
stream_puts(es, "****");
}
code = write_Private(es, pfont, glyphs.subset_glyphs, glyphs.subset_size,
- glyphs.notdef, lenIV, write_CharString, &ppp);
+ glyphs.notdef, lenIV, write_CharString, &ppp, options);
if (code < 0)
return code;
stream_puts(es, "dup/FontName get exch definefont pop\n");
diff --git a/devices/vector/gdevpsf2.c b/devices/vector/gdevpsf2.c
index 3c38e988..4c56c450 100644
--- a/devices/vector/gdevpsf2.c
+++ b/devices/vector/gdevpsf2.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -575,9 +575,14 @@ cff_write_Top_common(cff_writer_t *pcw, gs_font_base *pbfont,
}
if (uid_is_UniqueID(&pbfont->UID))
cff_put_int_value(pcw, pbfont->UID.id, TOP_UniqueID);
- else if (uid_is_XUID(&pbfont->UID)) {
- int j;
+ else if (uid_is_XUID(&pbfont->UID) && (pcw->options & WRITE_TYPE2_XUID) != 0) {
+ int j, k = uid_XUID_size(&pbfont->UID);
+ /* Adobe products (specifically Acrobat but the same limitation is mentioned
+ * in the PLRM) cannot handle XUIDs > 16 entries.
+ */
+ if (k > 16)
+ k = 16;
for (j = 0; j < uid_XUID_size(&pbfont->UID); ++j)
cff_put_int(pcw, uid_XUID_values(&pbfont->UID)[j]);
cff_put_op(pcw, TOP_XUID);
diff --git a/devices/vector/gdevpsfm.c b/devices/vector/gdevpsfm.c
index b38266c2..fc85c356 100644
--- a/devices/vector/gdevpsfm.c
+++ b/devices/vector/gdevpsfm.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsft.c b/devices/vector/gdevpsft.c
index 9bc00312..ae6600be 100644
--- a/devices/vector/gdevpsft.c
+++ b/devices/vector/gdevpsft.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsfu.c b/devices/vector/gdevpsfu.c
index e848bdc8..52bd0395 100644
--- a/devices/vector/gdevpsfu.c
+++ b/devices/vector/gdevpsfu.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsfx.c b/devices/vector/gdevpsfx.c
index 43459327..4420422e 100644
--- a/devices/vector/gdevpsfx.c
+++ b/devices/vector/gdevpsfx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsu.c b/devices/vector/gdevpsu.c
index 5e3e5a2b..83b8bdbb 100644
--- a/devices/vector/gdevpsu.c
+++ b/devices/vector/gdevpsu.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpsu.h b/devices/vector/gdevpsu.h
index c62ed8c6..b5927c2f 100644
--- a/devices/vector/gdevpsu.h
+++ b/devices/vector/gdevpsu.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/gdevpx.c b/devices/vector/gdevpx.c
index 5195339f..2002219d 100644
--- a/devices/vector/gdevpx.c
+++ b/devices/vector/gdevpx.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -1353,7 +1353,7 @@ pclxl_setdash(gx_device_vector * vdev, const float *pattern, uint count,
pattern_length += (uint) (pattern[i]);
if (pattern_length == 0)
return_error(gs_error_rangecheck);
-
+
spputc(s, pxt_uint16_array);
px_put_ub(s, (byte) count);
for (i = 0; i < count; ++i)
@@ -2078,7 +2078,7 @@ pclxl_begin_image(gx_device * dev,
goto use_default;
}
- /*
+ /*
* NOTE: this predicate should be fixed to be readable and easily
* debugged. Each condition should be separate. See the large
* similar conditional in clist_begin_typed_image which has
diff --git a/devices/vector/gdevtxtw.c b/devices/vector/gdevtxtw.c
index d46a935e..687581d5 100644
--- a/devices/vector/gdevtxtw.c
+++ b/devices/vector/gdevtxtw.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -36,30 +36,9 @@
#include "gdevkrnlsclass.h" /* 'standard' built in subclasses, currently First/Last Page and obejct filter */
#include "gxchar.h"
-/* #define TRACE_TXTWRITE 1 */
+#include "doc_common.h"
-extern single_glyph_list_t SingleGlyphList[];
-extern double_glyph_list_t DoubleGlyphList[];
-extern treble_glyph_list_t TrebleGlyphList[];
-extern quad_glyph_list_t QuadGlyphList[];
-/*
- * Define the structure used to return glyph width information. Note that
- * there are two different sets of width information: real-number (x,y)
- * values, which give the true advance width, and an integer value, which
- * gives an X advance width for WMode = 0 or a Y advance width for WMode = 1.
- * The return value from txt_glyph_width() indicates which of these is/are
- * valid.
- */
-typedef struct txt_glyph_width_s {
- double w;
- gs_point xy;
- gs_point v; /* glyph origin shift */
-} txt_glyph_width_t;
-typedef struct txt_glyph_widths_s {
- txt_glyph_width_t Width; /* unmodified, for Widths */
- txt_glyph_width_t real_width; /* possibly modified, for rendering */
- bool replaced_v;
-} txt_glyph_widths_t;
+/* #define TRACE_TXTWRITE 1 */
/* Structure to record the Unicode characters, the total width of the text
* recorded, and various useful attributes such as the font, size, colour
@@ -75,6 +54,8 @@ typedef struct text_list_entry_s {
gs_point FontBBox_bottomleft, FontBBox_topright;
float *Widths;
float *Advs;
+ float *GlyphWidths;
+ float *SpanDeltaX;
unsigned short *Unicode_Text;
int Unicode_Text_Size;
int render_mode;
@@ -150,15 +131,17 @@ typedef struct textw_text_enum_s {
double cdevproc_result[10];
float *Widths;
float *Advs;
+ float *GlyphWidths;
+ float *SpanDeltaX;
unsigned short *TextBuffer;
int TextBufferIndex;
text_list_entry_t *text_state;
} textw_text_enum_t;
#define private_st_textw_text_enum()\
extern_st(st_gs_text_enum);\
- gs_private_st_suffix_add0(st_textw_text_enum, textw_text_enum_t,\
+ gs_private_st_suffix_add1(st_textw_text_enum, textw_text_enum_t,\
"textw_text_enum_t", textw_text_enum_enum_ptrs, textw_text_enum_reloc_ptrs,\
- st_gs_text_enum)
+ st_gs_text_enum, pte_fallback)
private_st_textw_text_enum();
@@ -435,16 +418,30 @@ static int merge_horizontally(gx_device_txtwrite_t *tdev)
if (to->start.x - from->end.x < average_width / 2) {
/* consolidate fragments */
- unsigned short *NewText;
- float *NewWidths;
+ unsigned short *NewText = NULL;
+ float *NewWidths = NULL, *NewAdvs = NULL, *NewGlyphWidths = NULL, *NewSpanDeltaX = NULL;
NewText = (unsigned short *)gs_malloc(tdev->memory->stable_memory,
(from->Unicode_Text_Size + to->Unicode_Text_Size), sizeof(unsigned short), "txtwrite alloc working text buffer");
NewWidths = (float *)gs_malloc(tdev->memory->stable_memory,
(from->Unicode_Text_Size + to->Unicode_Text_Size), sizeof(float), "txtwrite alloc Widths array");
- if (!NewText || !NewWidths) {
+ NewAdvs = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size), sizeof(float), "txtwrite alloc Advs array");
+ NewGlyphWidths = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size), sizeof(float), "txtwrite alloc GlyphWidths array");
+ NewSpanDeltaX = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size), sizeof(float), "txtwrite alloc SpanDeltaX array");
+ if (!NewText || !NewWidths || !NewAdvs || !NewGlyphWidths || !NewSpanDeltaX) {
if (NewText)
gs_free(tdev->memory, NewText, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewWidths)
+ gs_free(tdev->memory, NewWidths, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewAdvs)
+ gs_free(tdev->memory, NewAdvs, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewGlyphWidths)
+ gs_free(tdev->memory, NewGlyphWidths, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewSpanDeltaX)
+ gs_free(tdev->memory, NewSpanDeltaX, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
/* ran out of memory, don't consolidate */
from = from->next;
to = to->next;
@@ -459,14 +456,31 @@ static int merge_horizontally(gx_device_txtwrite_t *tdev)
memcpy(&NewText[from->Unicode_Text_Size], to->Unicode_Text, to->Unicode_Text_Size * sizeof(unsigned short));
memcpy(NewWidths, from->Widths, from->Unicode_Text_Size * sizeof(float));
memcpy(&NewWidths[from->Unicode_Text_Size], to->Widths, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewAdvs, from->Advs, from->Unicode_Text_Size * sizeof(float));
+ memcpy(&NewAdvs[from->Unicode_Text_Size], to->Advs, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewGlyphWidths, from->GlyphWidths, from->Unicode_Text_Size * sizeof(float));
+ memcpy(&NewGlyphWidths[from->Unicode_Text_Size], to->GlyphWidths, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewSpanDeltaX, from->SpanDeltaX, from->Unicode_Text_Size * sizeof(float));
+ memcpy(&NewSpanDeltaX[from->Unicode_Text_Size], to->SpanDeltaX, to->Unicode_Text_Size * sizeof(float));
+
gs_free(tdev->memory, from->Unicode_Text, from->Unicode_Text_Size, sizeof (unsigned short), "free consolidated text fragment");
gs_free(tdev->memory, to->Unicode_Text, to->Unicode_Text_Size, sizeof (unsigned short), "free consolidated text fragment");
gs_free(tdev->memory, from->Widths, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
gs_free(tdev->memory, to->Widths, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->Advs, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->Advs, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->GlyphWidths, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->GlyphWidths, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->SpanDeltaX, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->SpanDeltaX, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
gs_free(tdev->memory, to->FontName, 1, strlen(from->FontName) + 1, "free FontName");
+
from->Unicode_Text = NewText;
from->Unicode_Text_Size += to->Unicode_Text_Size;
from->Widths = NewWidths;
+ from->Advs = NewAdvs;
+ from->GlyphWidths = NewGlyphWidths;
+ from->SpanDeltaX = NewSpanDeltaX;
#ifdef TRACE_TXTWRITE
gp_fprintf(tdev->DebugFile, "After:\n\t");
gp_fwrite(from->Unicode_Text, sizeof(unsigned short), from->Unicode_Text_Size, tdev->DebugFile);
@@ -480,16 +494,30 @@ static int merge_horizontally(gx_device_txtwrite_t *tdev)
}
} else {
if (to->start.x - from->end.x < average_width *2){
- unsigned short *NewText;
- float *NewWidths;
+ unsigned short *NewText = NULL;
+ float *NewWidths = NULL, *NewAdvs = NULL, *NewGlyphWidths = NULL, *NewSpanDeltaX = NULL;
NewText = (unsigned short *)gs_malloc(tdev->memory->stable_memory,
(from->Unicode_Text_Size + to->Unicode_Text_Size + 1), sizeof(unsigned short), "txtwrite alloc text state");
NewWidths = (float *)gs_malloc(tdev->memory->stable_memory,
(from->Unicode_Text_Size + to->Unicode_Text_Size + 1), sizeof(float), "txtwrite alloc Widths array");
- if (!NewText || !NewWidths) {
+ NewAdvs = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size + 1), sizeof(float), "txtwrite alloc Advs array");
+ NewGlyphWidths = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size + 1), sizeof(float), "txtwrite alloc GlyphWidths array");
+ NewSpanDeltaX = (float *)gs_malloc(tdev->memory->stable_memory,
+ (from->Unicode_Text_Size + to->Unicode_Text_Size + 1), sizeof(float), "txtwrite alloc SpanDeltaX array");
+ if (!NewText || !NewWidths || !NewAdvs || !NewGlyphWidths || !NewSpanDeltaX) {
if (NewText)
gs_free(tdev->memory, NewText, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewWidths)
+ gs_free(tdev->memory, NewWidths, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewAdvs)
+ gs_free(tdev->memory, NewAdvs, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewGlyphWidths)
+ gs_free(tdev->memory, NewGlyphWidths, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
+ if (NewSpanDeltaX)
+ gs_free(tdev->memory, NewSpanDeltaX, from->Unicode_Text_Size + to->Unicode_Text_Size, sizeof (unsigned short), "free working text fragment");
/* ran out of memory, don't consolidate */
from = from->next;
to = to->next;
@@ -500,14 +528,34 @@ static int merge_horizontally(gx_device_txtwrite_t *tdev)
memcpy(NewWidths, from->Widths, from->Unicode_Text_Size * sizeof(float));
NewWidths[from->Unicode_Text_Size] = to->start.x - from->end.x;
memcpy(&NewWidths[from->Unicode_Text_Size + 1], to->Widths, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewAdvs, from->Advs, from->Unicode_Text_Size * sizeof(float));
+ NewAdvs[from->Unicode_Text_Size] = to->start.x - from->end.x;
+ memcpy(&NewAdvs[from->Unicode_Text_Size + 1], to->Advs, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewGlyphWidths, from->GlyphWidths, from->Unicode_Text_Size * sizeof(float));
+ NewGlyphWidths[from->Unicode_Text_Size] = 0.0;
+ memcpy(&NewGlyphWidths[from->Unicode_Text_Size + 1], to->GlyphWidths, to->Unicode_Text_Size * sizeof(float));
+ memcpy(NewSpanDeltaX, from->SpanDeltaX, from->Unicode_Text_Size * sizeof(float));
+ NewSpanDeltaX[from->Unicode_Text_Size] = 0;
+ memcpy(&NewSpanDeltaX[from->Unicode_Text_Size + 1], to->SpanDeltaX, to->Unicode_Text_Size * sizeof(float));
+
gs_free(tdev->memory, from->Unicode_Text, from->Unicode_Text_Size, sizeof (unsigned short), "free consolidated text fragment");
gs_free(tdev->memory, to->Unicode_Text, to->Unicode_Text_Size, sizeof (unsigned short), "free consolidated text fragment");
gs_free(tdev->memory, from->Widths, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
gs_free(tdev->memory, to->Widths, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->Advs, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->Advs, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->GlyphWidths, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->GlyphWidths, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, from->SpanDeltaX, from->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
+ gs_free(tdev->memory, to->SpanDeltaX, to->Unicode_Text_Size, sizeof (float), "free consolidated Widths array");
gs_free(tdev->memory, to->FontName, 1, strlen(from->FontName) + 1, "free FontName");
+
from->Unicode_Text = NewText;
from->Unicode_Text_Size += to->Unicode_Text_Size + 1;
from->Widths = NewWidths;
+ from->Advs = NewAdvs;
+ from->GlyphWidths = NewGlyphWidths;
+ from->SpanDeltaX = NewSpanDeltaX;
from->end = to->end;
from->next = to->next;
if (from->next)
@@ -839,34 +887,54 @@ static int decorated_text_output(gx_device_txtwrite_t *tdev)
static int extract_text_output(gx_device_txtwrite_t *tdev)
{
text_list_entry_t* entry;
+ gp_fprintf(tdev->file, "<?xml version=\"1.0\"?>\n");
gp_fprintf(tdev->file, "<page>\n");
for (entry = tdev->PageData.unsorted_text_list;
entry;
entry = entry->next
) {
- float x = entry->start.x;
+
int i;
- gp_fprintf(tdev->file,
- "<span bbox=\"%0.4f %0.4f %0.4f %0.4f\" font=\"%s\" size=\"%0.4f\">\n",
- entry->start.x,
- entry->start.y,
- entry->end.x,
- entry->end.y,
- entry->FontName,
- entry->size
+ float x = entry->start.x - entry->matrix.tx;
+ gp_fprintf(tdev->file, "<span");
+ gp_fprintf(tdev->file, " ctm=\"%f %f %f %f %f %f\"",
+ entry->matrix.xx,
+ entry->matrix.xy,
+ entry->matrix.yx,
+ entry->matrix.yy,
+ entry->matrix.tx,
+ entry->matrix.ty
+ );
+ gp_fprintf(tdev->file, " ctm_orig=\"%f %f %f %f %f %f\"",
+ entry->matrix.xx,
+ entry->matrix.xy,
+ entry->matrix.yx,
+ entry->matrix.yy,
+ entry->matrix.tx,
+ entry->matrix.ty
+ );
+ gp_fprintf(tdev->file, " trm=\"%lf %f %f %lf %f %f\"",
+ entry->size,
+ 0.0f,
+ 0.0f,
+ entry->size,
+ 0.0f,
+ 0.0f
);
+ gp_fprintf(tdev->file, " len=\"%i\"", entry->Unicode_Text_Size);
+ gp_fprintf(tdev->file, " wmode=\"%i\"", entry->wmode);
+ gp_fprintf(tdev->file, " font_name=\"%s\"", entry->FontName);
+ gp_fprintf(tdev->file, ">\n");
for (i=0; i<entry->Unicode_Text_Size; i++) {
- float x_next = x + entry->Widths[i];
- char escaped[32];
- escaped_Unicode(entry->Unicode_Text[i], escaped);
+ float x_next = x + entry->SpanDeltaX[i];
+ int c = entry->Unicode_Text[i];
gp_fprintf(tdev->file,
- "<char bbox=\"%0.4f %0.4f %0.4f %0.4f\" c=\"%s\" adv=\"%0.4f\"/>\n",
+ "<char x=\"%f\" y=\"%f\" c=\"%c\" ucs=\"%u\" adv=\"%f\"/>\n",
x,
- entry->start.y,
- x_next,
- entry->end.y,
- escaped,
- entry->Advs[i]
+ entry->start.y - entry->matrix.ty,
+ (c >= 32 && c < 127 && c != '"') ? c : '.',
+ c,
+ entry->GlyphWidths[i] / entry->size
);
x = x_next;
}
@@ -935,6 +1003,8 @@ txtwrite_output_page(gx_device * dev, int num_copies, int flush)
gs_free(tdev->memory, x_entry->Unicode_Text, x_entry->Unicode_Text_Size, sizeof (usnigned short), "txtwrite free text fragment text buffer");
gs_free(tdev->memory, x_entry->Widths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array");
gs_free(tdev->memory, x_entry->Advs, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array");
+ gs_free(tdev->memory, x_entry->GlyphWidths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array");
+ gs_free(tdev->memory, x_entry->SpanDeltaX, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array");
gs_free(tdev->memory, x_entry->FontName, 1, strlen(x_entry->FontName) + 1, "txtwrite free Font Name");
if (x_entry->next) {
x_entry = x_entry->next;
@@ -961,6 +1031,8 @@ txtwrite_output_page(gx_device * dev, int num_copies, int flush)
gs_free(tdev->memory, x_entry->Unicode_Text, x_entry->Unicode_Text_Size, sizeof (usnigned short), "txtwrite free unsorted text fragment text buffer");
gs_free(tdev->memory, x_entry->Widths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array");
gs_free(tdev->memory, x_entry->Advs, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array");
+ gs_free(tdev->memory, x_entry->GlyphWidths, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free widths array");
+ gs_free(tdev->memory, x_entry->SpanDeltaX, x_entry->Unicode_Text_Size, sizeof (float), "txtwrite free advs array");
gs_free(tdev->memory, x_entry->FontName, 1, strlen(x_entry->FontName) + 1, "txtwrite free Font Name");
gs_free(tdev->memory, x_entry, 1, sizeof(text_list_entry_t), "txtwrite free unsorted text fragment");
x_entry = next_x;
@@ -1231,134 +1303,6 @@ txtwrite_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
/* ------ Text imaging ------ */
-static int
-txtwrite_font_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat)
-{
- int code;
-
- switch (font->FontType) {
- case ft_composite: /* subfonts have their own FontMatrix */
- case ft_TrueType:
- case ft_CID_TrueType:
- /* The TrueType FontMatrix is 1 unit per em, which is what we want. */
- gs_make_identity(pmat);
- return 0;
- case ft_encrypted:
- case ft_encrypted2:
- case ft_CID_encrypted:
- case ft_user_defined:
- case ft_PCL_user_defined:
- case ft_GL2_stick_user_defined:
- case ft_GL2_531:
- /*
- * Type 1 fonts are supposed to use a standard FontMatrix of
- * [0.001 0 0 0.001 0 0], with a 1000-unit cell. However,
- * Windows NT 4.0 creates Type 1 fonts, apparently derived from
- * TrueType fonts, that use a 2048-unit cell and corresponding
- * FontMatrix. Also, some PS programs perform font scaling by
- * replacing FontMatrix like this :
- *
- * /f12 /Times-Roman findfont
- * copyfont % (remove FID)
- * dup /FontMatrix [0.012 0 0 0.012 0 0] put
- * definefont
- * /f12 1 selectfont
- *
- * Such fonts are their own "base font", but the orig_matrix
- * must still be set to 0.001, not 0.012 .
- *
- * The old code used a heuristic to detect and correct for this here.
- * Unfortunately it doesn't work properly when it meets a font
- * with FontMatrix like this :
- *
- * /FontMatrix [1 2288 div 0 0 1 2288 div 0 0 ] def
- *
- * (the bug 686970). Also comparefiles\455690.pdf appears to
- * have similar problem. Therefore we added a support to lib/gs_fonts.ps,
- * src/zbfont.c, src/gsfont.c that provides an acces to the original
- * font via a special key OrigFont added to the font dictionary while definefont.
- * Now we work through this access with PS interpreter,
- * but keep the old heuristic for other clients.
- */
- {
- const gs_font *base_font = font;
-
- while (base_font->base != base_font)
- base_font = base_font->base;
- if (font->FontType == ft_user_defined ||
- font->FontType == ft_PCL_user_defined ||
- font->FontType == ft_GL2_stick_user_defined ||
- font->FontType == ft_GL2_531)
- *pmat = base_font->FontMatrix;
- else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 ||
- base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0)
- *pmat = base_font->orig_FontMatrix;
- else {
- /* Must not happen with PS interpreter.
- Provide a hewuristic for other clients.
- */
- if (base_font->FontMatrix.xx == 1.0/2048 &&
- base_font->FontMatrix.xy == 0 &&
- base_font->FontMatrix.yx == 0 &&
- any_abs(base_font->FontMatrix.yy) == 1.0/2048
- )
- *pmat = base_font->FontMatrix;
- else
- gs_make_scaling(0.001, 0.001, pmat);
- }
- }
- if (font->FontType == ft_CID_encrypted && cid != -1) {
- int fidx;
-
- if (cid < GS_MIN_CID_GLYPH)
- cid = GS_MIN_CID_GLYPH;
- code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
- cid, NULL, &fidx);
- if (code < 0) {
- code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
- (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx);
- }
- if (code >= 0) {
- gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix),
- pmat, pmat);
- }
- }
- return 0;
- default:
- return_error(gs_error_rangecheck);
- }
-}
-
-/*
- * Special version of txtwrite_font_orig_matrix(), that considers FDArray font's FontMatrix too.
- * Called only by txt_glyph_width().
- * 'cid' is only consulted if 'font' is a CIDFontType 0 CID font.
- */
-static int
-glyph_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat)
-{
- int code = txtwrite_font_orig_matrix(font, cid, pmat);
- if (code >= 0) {
- if (font->FontType == ft_CID_encrypted) {
- int fidx;
-
- if (cid < GS_MIN_CID_GLYPH)
- cid = GS_MIN_CID_GLYPH;
- code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
- cid, NULL, &fidx);
- if (code < 0) {
- code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font,
- (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx);
- }
- if (code >= 0) {
- gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix),
- pmat, pmat);
- }
- }
- }
- return code;
-}
-
/*
* Compute the cached values in the text processing state from the text
* parameters, current_font, and pgs->ctm. Return either an error code (<
@@ -1389,42 +1333,6 @@ transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat,
return 0;
}
-static
-float txt_calculate_text_size(gs_gstate *pgs, gs_font *ofont,
- const gs_matrix *pfmat, gs_matrix *smat, gs_matrix *tmat,
- gs_font *font, gx_device *pdev)
-{
- gs_matrix orig_matrix;
- double
- sx = pdev->HWResolution[0] / 72.0,
- sy = pdev->HWResolution[1] / 72.0;
- float size;
-
- /* Get the original matrix of the base font. */
-
- txtwrite_font_orig_matrix(ofont, -1, &orig_matrix);
- /* Compute the scaling matrix and combined matrix. */
-
- if (gs_matrix_invert(&orig_matrix, smat) < 0) {
- gs_make_identity(smat);
- return 1; /* Arbitrary */
- }
- gs_matrix_multiply(smat, pfmat, smat);
- *tmat = ctm_only(pgs);
- tmat->tx = tmat->ty = 0;
- gs_matrix_multiply(smat, tmat, tmat);
-
- /* Try to find a reasonable size value. */
-
- size = hypot(tmat->yx, tmat->yy) / sy;
- if (size < 0.01)
- size = hypot(tmat->xx, tmat->xy) / sx;
- if (size < 0.01)
- size = 1;
-
- return(size);
-}
-
static int
txt_update_text_state(text_list_entry_t *ppts,
const textw_text_enum_t *penum,
@@ -1474,13 +1382,6 @@ txt_update_text_state(text_list_entry_t *ppts,
ppts->size = size;
ppts->matrix = tmat;
- ppts->render_mode = penum->pgs->text_rendering_mode;
- ppts->FontName = (char *)gs_malloc(pdev->memory->stable_memory, 1,
- font->font_name.size + 1, "txtwrite alloc font name");
- if (!ppts->FontName)
- return gs_note_error(gs_error_VMerror);
- memcpy(ppts->FontName, font->font_name.chars, font->font_name.size);
- ppts->FontName[font->font_name.size] = 0x00;
ppts->render_mode = font->WMode;
if (font->PaintType == 2 && penum->pgs->text_rendering_mode == 0)
@@ -1512,227 +1413,6 @@ txt_update_text_state(text_list_entry_t *ppts,
return (code < 0 ? code : mask);
}
-static int
-store_glyph_width(txt_glyph_width_t *pwidth, int wmode, const gs_matrix *scale,
- const gs_glyph_info_t *pinfo)
-{
- double w, v;
-
- gs_distance_transform(pinfo->width[wmode].x, pinfo->width[wmode].y, scale, &pwidth->xy);
- if (wmode)
- w = pwidth->xy.y, v = pwidth->xy.x;
- else
- w = pwidth->xy.x, v = pwidth->xy.y;
- if (v != 0)
- return 1;
- pwidth->w = w;
- gs_distance_transform(pinfo->v.x, pinfo->v.y, scale, &pwidth->v);
- return 0;
-}
-
-static int
-get_missing_width(gs_font *font, int wmode, const gs_matrix *scale_c,
- txt_glyph_widths_t *pwidths)
-{
- gs_font_info_t finfo;
- int code;
-
- code = font->procs.font_info((gs_font *)font, NULL,
- FONT_INFO_MISSING_WIDTH, &finfo);
- if (code < 0)
- return code;
- if (!(finfo.members & FONT_INFO_MISSING_WIDTH))
- return_error(gs_error_undefined);
-
- if (wmode) {
- gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy);
- pwidths->Width.xy.x = 0;
- pwidths->Width.xy.y = pwidths->real_width.xy.y;
- pwidths->Width.w = pwidths->real_width.w =
- pwidths->Width.xy.y;
- pwidths->Width.v.x = - pwidths->Width.xy.y / 2;
- pwidths->Width.v.y = - pwidths->Width.xy.y;
- } else {
- gs_distance_transform(finfo.MissingWidth, 0.0, scale_c, &pwidths->real_width.xy);
- pwidths->Width.xy.x = pwidths->real_width.xy.x;
- pwidths->Width.xy.y = 0;
- pwidths->Width.w = pwidths->real_width.w =
- pwidths->Width.xy.x;
- pwidths->Width.v.x = pwidths->Width.v.y = 0;
- }
- /*
- * Don't mark the width as known, just in case this is an
- * incrementally defined font.
- */
- return 1;
-}
-
-/*
- * Get the widths (unmodified from the copied font,
- * and possibly modified from the original font) of a given glyph.
- * Return 1 if the width was defaulted to MissingWidth.
- * Return TEXT_PROCESS_CDEVPROC if a CDevProc callout is needed.
- * cdevproc_result != NULL if we restart after a CDevProc callout.
- */
-static int
-txt_glyph_widths(gs_font *font, int wmode, gs_glyph glyph,
- gs_font *orig_font, txt_glyph_widths_t *pwidths,
- const double cdevproc_result[10])
-{
- gs_font *ofont = orig_font;
- gs_glyph_info_t info;
- gs_matrix scale_c, scale_o;
- int code, rcode = 0;
- gs_point v;
- int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType
- || orig_font->FontType == ft_CID_encrypted
- ? GLYPH_INFO_CDEVPROC : 0); /* fixme : allow more font types. */
-
- if (ofont->FontType == ft_composite)
- return_error(gs_error_unregistered); /* Must not happen. */
- code = glyph_orig_matrix((const gs_font *)font, glyph, &scale_c);
- if (code < 0)
- return code;
- code = glyph_orig_matrix(ofont, glyph, &scale_o);
- if (code < 0)
- return code;
- gs_matrix_scale(&scale_c, 1000.0, 1000.0, &scale_c);
- gs_matrix_scale(&scale_o, 1000.0, 1000.0, &scale_o);
- pwidths->Width.v.x = pwidths->Width.v.y = 0;
- pwidths->real_width.v.x = pwidths->real_width.v.y = 0;
- pwidths->replaced_v = false;
- if (glyph == GS_NO_GLYPH)
- return get_missing_width(font, wmode, &scale_c, pwidths);
- code = font->procs.glyph_info((gs_font *)font, glyph, NULL,
- GLYPH_INFO_WIDTH0 |
- (GLYPH_INFO_WIDTH0 << wmode) |
- GLYPH_INFO_OUTLINE_WIDTHS |
- (GLYPH_INFO_VVECTOR0 << wmode),
- &info);
- /* For CID fonts the PDF spec requires the x-component of v-vector
- to be equal to half glyph width, and AR5 takes it from W, DW.
- So make a compatibe data here.
- */
- if (font->FontType != ft_PCL_user_defined && font->FontType != ft_GL2_stick_user_defined &&
- font->FontType != ft_GL2_531
- && (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))) {
- code = get_missing_width(font, wmode, &scale_c, pwidths);
- if (code < 0)
- return code;
- else
- v.y = pwidths->Width.v.y;
- if (wmode && (ofont->FontType == ft_CID_encrypted ||
- ofont->FontType == ft_CID_TrueType)) {
- txt_glyph_widths_t widths1;
-
- if (get_missing_width(font, 0, &scale_c, &widths1) < 0)
- v.x = 0;
- else
- v.x = widths1.Width.w / 2;
- } else
- v.x = pwidths->Width.v.x;
- } else if (code < 0)
- return code;
- else {
- code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info);
- if (code < 0)
- return code;
- rcode |= code;
- if (info.members & (GLYPH_INFO_VVECTOR0 << wmode))
- gs_distance_transform(info.v.x, info.v.y, &scale_c, &v);
- else
- v.x = v.y = 0;
- if (wmode && (ofont->FontType == ft_CID_encrypted ||
- ofont->FontType == ft_CID_TrueType)) {
- if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) {
- gs_point xy;
-
- gs_distance_transform(info.width[0].x, info.width[0].y, &scale_c, &xy);
- v.x = xy.x / 2;
- } else {
- txt_glyph_widths_t widths1;
-
- if (get_missing_width(font, 0, &scale_c, &widths1) < 0)
- v.x = 0;
- else
- v.x = widths1.Width.w / 2;
- }
- }
- }
- pwidths->Width.v = v;
- /* Skip only if not paralel to the axis. */
- if (code > 0 && ofont->FontType != ft_CID_encrypted &&
- ofont->FontType != ft_CID_TrueType)
- pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0;
- if (cdevproc_result == NULL) {
- info.members = 0;
- code = ofont->procs.glyph_info(ofont, glyph, NULL,
- (GLYPH_INFO_WIDTH0 << wmode) |
- (GLYPH_INFO_VVECTOR0 << wmode) |
- allow_cdevproc_callout,
- &info);
- /* fixme : Move this call before cfont->procs.glyph_info. */
- if (info.members & GLYPH_INFO_CDEVPROC) {
- if (allow_cdevproc_callout)
- return TEXT_PROCESS_CDEVPROC;
- else
- return_error(gs_error_rangecheck);
- }
- } else {
- info.width[0].x = cdevproc_result[0];
- info.width[0].y = cdevproc_result[1];
- info.width[1].x = cdevproc_result[6];
- info.width[1].y = cdevproc_result[7];
- info.v.x = (wmode ? cdevproc_result[8] : 0);
- info.v.y = (wmode ? cdevproc_result[9] : 0);
- info.members = (GLYPH_INFO_WIDTH0 << wmode) |
- (wmode ? GLYPH_INFO_VVECTOR1 : 0);
- code = 0;
- }
- if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))
- pwidths->real_width = pwidths->Width;
- else if (code < 0)
- return code;
- else {
- if ((info.members & (GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1)) != 0)
- pwidths->replaced_v = true;
- else
- info.v.x = info.v.y = 0;
- code = store_glyph_width(&pwidths->real_width, wmode, &scale_o, &info);
- if (code < 0)
- return code;
- rcode |= code;
- gs_distance_transform(info.v.x, info.v.y, &scale_o, &pwidths->real_width.v);
- }
- return rcode;
-}
-
-static void
-txt_char_widths_to_uts(gs_font *font /* may be NULL for non-Type3 */,
- txt_glyph_widths_t *pwidths)
-{
- if (font && (font->FontType == ft_user_defined ||
- font->FontType == ft_PCL_user_defined ||
- font->FontType == ft_GL2_stick_user_defined ||
- font->FontType == ft_GL2_531)) {
- gs_matrix *pmat = &font->orig_FontMatrix;
-
- pwidths->Width.xy.x *= pmat->xx; /* formula simplified based on wy in glyph space == 0 */
- pwidths->Width.xy.y = 0.0; /* WMode == 0 for PDF Type 3 fonts */
- gs_distance_transform(pwidths->real_width.xy.x, pwidths->real_width.xy.y, pmat, &pwidths->real_width.xy);
- } else {
- /*
- * For other font types:
- * - PDF design->text space is a simple scaling by 0.001.
- * - The Width.xy.x/y that should be zeroed-out per 5.3.3 "Text Space Details" is already 0.
- */
- pwidths->Width.xy.x /= 1000.0;
- pwidths->Width.xy.y /= 1000.0;
- pwidths->real_width.xy.x /= 1000.0;
- pwidths->real_width.xy.y /= 1000.0;
- }
-}
-
/* Simple routine to update the current point by the accumulated width of the
* text.
*/
@@ -1744,142 +1424,6 @@ txt_shift_text_currentpoint(textw_text_enum_t *penum, gs_point *wpt)
fixed2float(penum->origin.y) + wpt->y);
}
-/* Try to convert glyph names/character codes to Unicode. We first try to see
- * if we have any Unicode information either from a ToUnicode CMap or GlyphNames2Unicode
- * table. If that fails we look at the glyph name to see if it starts 'uni'
- * in which case we assume the remainder of the name is the Unicode value. If
- * its not a glyph of that form then we search a bunch of tables whcih map standard
- * glyph names to Unicode code points. If that fails we finally just return the character code.
- */
-static int get_unicode(textw_text_enum_t *penum, gs_font *font, gs_glyph glyph, gs_char ch, unsigned short *Buffer)
-{
- int code;
- gs_const_string gnstr;
- unsigned short fallback = ch;
- ushort *unicode = NULL;
- int length;
-
- length = font->procs.decode_glyph((gs_font *)font, glyph, ch, NULL, 0);
- if (length == 0) {
- if (glyph != GS_NO_GLYPH) {
- code = font->procs.glyph_name(font, glyph, &gnstr);
- if (code >= 0 && gnstr.size == 7) {
- if (!memcmp(gnstr.data, "uni", 3)) {
- static const char *hexdigits = "0123456789ABCDEF";
- char *d0 = strchr(hexdigits, gnstr.data[3]);
- char *d1 = strchr(hexdigits, gnstr.data[4]);
- char *d2 = strchr(hexdigits, gnstr.data[5]);
- char *d3 = strchr(hexdigits, gnstr.data[6]);
-
- if (d0 != NULL && d1 != NULL && d2 != NULL && d3 != NULL) {
- *Buffer++ = ((d0 - hexdigits) << 12) + ((d1 - hexdigits) << 8) + ((d2 - hexdigits) << 4) + (d3 - hexdigits);
- return 1;
- }
- }
- }
- if (length == 0) {
- single_glyph_list_t *sentry = SingleGlyphList;
- double_glyph_list_t *dentry = DoubleGlyphList;
- treble_glyph_list_t *tentry = TrebleGlyphList;
- quad_glyph_list_t *qentry = QuadGlyphList;
-
- /* Search glyph to single Unicode value table */
- while (sentry->Glyph != 0) {
- if (sentry->Glyph[0] < gnstr.data[0]) {
- sentry++;
- continue;
- }
- if (sentry->Glyph[0] > gnstr.data[0]){
- break;
- }
- if (strlen(sentry->Glyph) == gnstr.size) {
- if(memcmp(gnstr.data, sentry->Glyph, gnstr.size) == 0) {
- *Buffer = sentry->Unicode;
- return 1;
- }
- }
- sentry++;
- }
-
- /* Search glyph to double Unicode value table */
- while (dentry->Glyph != 0) {
- if (dentry->Glyph[0] < gnstr.data[0]) {
- dentry++;
- continue;
- }
- if (dentry->Glyph[0] > gnstr.data[0]){
- break;
- }
- if (strlen(dentry->Glyph) == gnstr.size) {
- if(memcmp(gnstr.data, dentry->Glyph, gnstr.size) == 0) {
- memcpy(Buffer, dentry->Unicode, 2);
- return 2;
- }
- }
- dentry++;
- }
-
- /* Search glyph to triple Unicode value table */
- while (tentry->Glyph != 0) {
- if (tentry->Glyph[0] < gnstr.data[0]) {
- tentry++;
- continue;
- }
- if (tentry->Glyph[0] > gnstr.data[0]){
- break;
- }
- if (strlen(tentry->Glyph) == gnstr.size) {
- if(memcmp(gnstr.data, tentry->Glyph, gnstr.size) == 0) {
- memcpy(Buffer, tentry->Unicode, 3);
- return 3;
- }
- }
- tentry++;
- }
-
- /* Search glyph to quadruple Unicode value table */
- while (qentry->Glyph != 0) {
- if (qentry->Glyph[0] < gnstr.data[0]) {
- qentry++;
- continue;
- }
- if (qentry->Glyph[0] > gnstr.data[0]){
- break;
- }
- if (strlen(qentry->Glyph) == gnstr.size) {
- if(memcmp(gnstr.data, qentry->Glyph, gnstr.size) == 0) {
- memcpy(Buffer, qentry->Unicode, 4);
- return 4;
- }
- }
- qentry++;
- }
- }
- }
- *Buffer = fallback;
- return 1;
- } else {
- char *b, *u;
- int l = length - 1;
-
- unicode = (ushort *)gs_alloc_bytes(penum->dev->memory, length, "temporary Unicode array");
- length = font->procs.decode_glyph((gs_font *)font, glyph, ch, unicode, length);
-#if ARCH_IS_BIG_ENDIAN
- memcpy(Buffer, unicode, length);
-#else
- b = (char *)Buffer;
- u = (char *)unicode;
-
- for (l=0;l<length;l+=2, u+=2){
- *b++ = *(u+1);
- *b++ = *u;
- }
-#endif
- gs_free_object(penum->dev->memory, unicode, "free temporary unicode buffer");
- return length / sizeof(short);
- }
-}
-
/* Routines to enumerate each glyph/character code in turn, find its width
* so that we can update the current point and find the end of the text, convert
* to Unicode if at all possible, and store some state such as the font, colour
@@ -1930,7 +1474,7 @@ txtwrite_process_cmap_text(gs_text_enum_t *pte)
code = gs_matrix_multiply(&subfont->FontMatrix, &pte->orig_font->FontMatrix, &m3);
if (code < 0)
return code;
- code = txt_update_text_state(penum->text_state, (textw_text_enum_t *)pte, pte->orig_font, &m3);
+ code = txt_update_text_state(penum->text_state, (textw_text_enum_t *)pte, subfont, &m3);
if (code < 0)
return code;
txt_char_widths_to_uts(pte->orig_font, &widths); /* convert design->text space */
@@ -1940,6 +1484,8 @@ txtwrite_process_cmap_text(gs_text_enum_t *pte)
pte->returned.total_width.x += wanted.x;
pte->returned.total_width.y += wanted.y;
penum->Widths[penum->TextBufferIndex] = wanted.x;
+ penum->GlyphWidths[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size;
+ penum->SpanDeltaX[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size;
if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
gs_point tpt;
@@ -1961,7 +1507,8 @@ txtwrite_process_cmap_text(gs_text_enum_t *pte)
pte->returned.total_width.y += dpt.y;
penum->Widths[penum->TextBufferIndex] += dpt.x;
- penum->TextBufferIndex += get_unicode(penum, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]);
+ penum->GlyphWidths[penum->TextBufferIndex] += dpt.x;
+ penum->TextBufferIndex += txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, chr, &penum->TextBuffer[penum->TextBufferIndex]);
break;
case 2: /* end of string */
return 0;
@@ -2028,6 +1575,8 @@ txtwrite_process_plain_text(gs_text_enum_t *pte)
pte->returned.total_width.y += wanted.y;
penum->Widths[penum->TextBufferIndex] = wanted.x;
penum->Advs[penum->TextBufferIndex] = wanted.x;
+ penum->GlyphWidths[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size;
+ penum->SpanDeltaX[penum->TextBufferIndex] = widths.real_width.xy.x * penum->text_state->size;
if (pte->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
gs_point tpt;
@@ -2049,13 +1598,16 @@ txtwrite_process_plain_text(gs_text_enum_t *pte)
pte->returned.total_width.y += dpt.y;
penum->Widths[penum->TextBufferIndex] += dpt.x;
- code = get_unicode(penum, (gs_font *)pte->orig_font, glyph, ch, &penum->TextBuffer[penum->TextBufferIndex]);
+ penum->SpanDeltaX[penum->TextBufferIndex] += dpt.x;
+ code = txt_get_unicode(penum->dev, (gs_font *)pte->orig_font, glyph, ch, &penum->TextBuffer[penum->TextBufferIndex]);
/* If a single text code returned multiple Unicode values, then we need to set the
* 'extra' code points' widths to 0.
*/
if (code > 1) {
memset(&penum->Widths[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float));
memset(&penum->Advs[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float));
+ memset(&penum->GlyphWidths[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float));
+ memset(&penum->SpanDeltaX[penum->TextBufferIndex + 1], 0x00, (code - 1) * sizeof(float));
}
penum->TextBufferIndex += code;
/* gs_moveto_aux(penum->pgs, gx_current_path(penum->pgs),
@@ -2169,6 +1721,7 @@ txt_add_sorted_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum)
static int
txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum)
{
+ gs_font *font = penum->current_font;
text_list_entry_t *unsorted_entry, *t;
#ifdef TRACE_TXTWRITE
@@ -2216,10 +1769,28 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum)
penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
if (!penum->text_state->Advs)
return gs_note_error(gs_error_VMerror);
+ penum->text_state->GlyphWidths = (float *)gs_malloc(tdev->memory->stable_memory,
+ penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
+ if (!penum->text_state->GlyphWidths)
+ return gs_note_error(gs_error_VMerror);
+ penum->text_state->SpanDeltaX = (float *)gs_malloc(tdev->memory->stable_memory,
+ penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
+ if (!penum->text_state->SpanDeltaX)
+ return gs_note_error(gs_error_VMerror);
memset(penum->text_state->Widths, 0x00, penum->TextBufferIndex * sizeof(float));
memcpy(penum->text_state->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float));
memset(penum->text_state->Advs, 0x00, penum->TextBufferIndex * sizeof(float));
memcpy(penum->text_state->Advs, penum->Advs, penum->TextBufferIndex * sizeof(float));
+ memset(penum->text_state->GlyphWidths, 0x00, penum->TextBufferIndex * sizeof(float));
+ memcpy(penum->text_state->GlyphWidths, penum->GlyphWidths, penum->TextBufferIndex * sizeof(float));
+ memset(penum->text_state->SpanDeltaX, 0x00, penum->TextBufferIndex * sizeof(float));
+ memcpy(penum->text_state->SpanDeltaX, penum->SpanDeltaX, penum->TextBufferIndex * sizeof(float));
+ penum->text_state->FontName = (char *)gs_malloc(tdev->memory->stable_memory, 1,
+ font->font_name.size + 1, "txtwrite alloc font name");
+ if (!penum->text_state->FontName)
+ return gs_note_error(gs_error_VMerror);
+ memcpy(penum->text_state->FontName, font->font_name.chars, font->font_name.size);
+ penum->text_state->FontName[font->font_name.size] = 0x00;
unsorted_entry->Unicode_Text = (unsigned short *)gs_malloc(tdev->memory->stable_memory,
penum->TextBufferIndex, sizeof(unsigned short), "txtwrite alloc sorted text buffer");
@@ -2235,10 +1806,22 @@ txt_add_fragment(gx_device_txtwrite_t *tdev, textw_text_enum_t *penum)
penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
if (!unsorted_entry->Advs)
return gs_note_error(gs_error_VMerror);
+ unsorted_entry->GlyphWidths = (float *)gs_malloc(tdev->memory->stable_memory,
+ penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
+ if (!unsorted_entry->GlyphWidths)
+ return gs_note_error(gs_error_VMerror);
+ unsorted_entry->SpanDeltaX = (float *)gs_malloc(tdev->memory->stable_memory,
+ penum->TextBufferIndex, sizeof(float), "txtwrite alloc widths array");
+ if (!unsorted_entry->SpanDeltaX)
+ return gs_note_error(gs_error_VMerror);
memset(unsorted_entry->Widths, 0x00, penum->TextBufferIndex * sizeof(float));
memcpy(unsorted_entry->Widths, penum->Widths, penum->TextBufferIndex * sizeof(float));
memset(unsorted_entry->Advs, 0x00, penum->TextBufferIndex * sizeof(float));
memcpy(unsorted_entry->Advs, penum->Advs, penum->TextBufferIndex * sizeof(float));
+ memset(unsorted_entry->GlyphWidths, 0x00, penum->TextBufferIndex * sizeof(float));
+ memcpy(unsorted_entry->GlyphWidths, penum->GlyphWidths, penum->TextBufferIndex * sizeof(float));
+ memset(unsorted_entry->SpanDeltaX, 0x00, penum->TextBufferIndex * sizeof(float));
+ memcpy(unsorted_entry->SpanDeltaX, penum->SpanDeltaX, penum->TextBufferIndex * sizeof(float));
unsorted_entry->FontName = (char *)gs_malloc(tdev->memory->stable_memory,
(strlen(penum->text_state->FontName) + 1), sizeof(unsigned char), "txtwrite alloc sorted text buffer");
@@ -2287,7 +1870,7 @@ textw_text_process(gs_text_enum_t *pte)
code = gx_default_text_restore_state(pte_fallback);
if (code < 0)
return code;
- gs_text_release(pte_fallback, "txtwrite_text_process");
+ gs_text_release(NULL, pte_fallback, "txtwrite_text_process");
}
pte_fallback = penum->pte_fallback = NULL;
@@ -2311,6 +1894,14 @@ textw_text_process(gs_text_enum_t *pte)
pte->text.size * 4, sizeof(float), "txtwrite temporary advs array");
if (!penum->Advs)
return gs_note_error(gs_error_VMerror);
+ penum->GlyphWidths = (float *)gs_malloc(tdev->memory->stable_memory,
+ pte->text.size * 4, sizeof(float), "txtwrite temporary glyphwidths array");
+ if (!penum->GlyphWidths)
+ return gs_note_error(gs_error_VMerror);
+ penum->SpanDeltaX = (float *)gs_malloc(tdev->memory->stable_memory,
+ pte->text.size * 4, sizeof(float), "txtwrite temporary spandeltax array");
+ if (!penum->SpanDeltaX)
+ return gs_note_error(gs_error_VMerror);
}
{
switch (font->FontType) {
@@ -2378,7 +1969,7 @@ textw_text_process(gs_text_enum_t *pte)
penum->returned.current_glyph = pte_fallback->returned.current_glyph;
return code;
}
- gs_text_release(pte_fallback, "txtwrite_text_process");
+ gs_text_release(NULL, pte_fallback, "txtwrite_text_process");
penum->pte_fallback = 0;
}
}
@@ -2446,14 +2037,29 @@ textw_text_release(gs_text_enum_t *pte, client_name_t cname)
gs_free(tdev->memory, penum->TextBuffer, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
if (penum->Widths)
gs_free(tdev->memory, penum->Widths, sizeof(float), pte->text.size, "txtwrite free temporary widths array");
+ if (penum->Advs)
+ gs_free(tdev->memory, penum->Advs, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
+ if (penum->GlyphWidths)
+ gs_free(tdev->memory, penum->GlyphWidths, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
+ if (penum->SpanDeltaX)
+ gs_free(tdev->memory, penum->SpanDeltaX, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
/* If this is copied away when we complete the text enumeration succesfully, then
* we set the pointer to NULL, if we get here with it non-NULL , then there was
* an error.
*/
- if (penum->text_state)
+ if (penum->text_state) {
+ if (penum->text_state->Widths)
+ gs_free(tdev->memory, penum->text_state->Widths, sizeof(float), pte->text.size, "txtwrite free temporary widths array");
+ if (penum->text_state->Advs)
+ gs_free(tdev->memory, penum->text_state->Advs, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
+ if (penum->text_state->GlyphWidths)
+ gs_free(tdev->memory, penum->text_state->GlyphWidths, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
+ if (penum->text_state->SpanDeltaX)
+ gs_free(tdev->memory, penum->text_state->SpanDeltaX, 1, penum->TextBufferIndex, "txtwrite free temporary text buffer");
+ if (penum->text_state->FontName)
+ gs_free(tdev->memory, penum->text_state->FontName, 1, penum->TextBufferIndex, "txtwrite free temporary font name copy");
gs_free(tdev->memory, penum->text_state, 1, sizeof(penum->text_state), "txtwrite free text state");
-
- gs_text_release(pte, cname);
+ }
}
/* This is the list of methods for the text enumerator */
diff --git a/devices/vector/gdevxps.c b/devices/vector/gdevxps.c
index 8eb26196..c435cd47 100644
--- a/devices/vector/gdevxps.c
+++ b/devices/vector/gdevxps.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -118,9 +118,10 @@ typedef struct gx_device_xps_f2i_s {
char *filename;
gx_device_xps_zinfo_t *info;
struct gx_device_xps_f2i_s *next;
+ gs_memory_t *memory;
} gx_device_xps_f2i_t;
-/* Used for keeping track of icc profiles that we have written. This way we
+/* Used for keeping track of icc profiles that we have written. This way we
avoid writing the same one multiple times. It would be nice to do this
based upon the gs_id for images, but that id is really created after we
have already drawn the path. Not clear to me how to get a source ID. */
@@ -130,6 +131,16 @@ typedef struct xps_icc_data_s {
struct xps_icc_data_s *next;
} xps_icc_data_t;
+/* Add new page relationships to this linked list, avoiding duplicates.
+ When page is closed write out all the relationships */
+typedef struct xps_relations_s xps_relations_t;
+
+struct xps_relations_s {
+ char* relation;
+ xps_relations_t *next;
+ gs_memory_t *memory;
+};
+
typedef enum {
xps_solidbrush,
xps_imagebrush,
@@ -169,7 +180,8 @@ typedef struct gx_device_xps_s {
/* local state */
int page_count; /* how many output_page calls we've seen */
int image_count; /* number of images so far */
- int relationship_count; /* Pages relationships */
+ xps_relations_t *relations_head;
+ xps_relations_t *relations_tail;
xps_icc_data_t *icc_data;
gx_color_index strokecolor, fillcolor;
xps_brush_t stroketype, filltype;
@@ -373,18 +385,19 @@ zip_new_info_node(gx_device_xps *xps_dev, const char *filename)
int lenstr;
/* NB should use GC */
- gx_device_xps_zinfo_t *info =
+ gx_device_xps_zinfo_t *info =
(gx_device_xps_zinfo_t *)gs_alloc_bytes(mem->non_gc_memory, sizeof(gx_device_xps_zinfo_t), "zinfo");
- gx_device_xps_f2i_t *f2i =
+ gx_device_xps_f2i_t *f2i =
(gx_device_xps_f2i_t *)gs_alloc_bytes(mem->non_gc_memory, sizeof(gx_device_xps_f2i_t), "zinfo node");
if_debug1m('_', dev->memory, "new node %s\n", filename);
-
+
if (info == NULL || f2i == NULL)
- return gs_throw_code(gs_error_Fatal);
+ return gs_throw_code(gs_error_VMerror);
f2i->info = info;
f2i->next = NULL;
+ f2i->memory = mem->non_gc_memory;
if (xps_dev->f2i == 0) { /* no head */
xps_dev->f2i = f2i;
@@ -396,8 +409,10 @@ zip_new_info_node(gx_device_xps *xps_dev, const char *filename)
lenstr = strlen(filename);
f2i->filename = (char*)gs_alloc_bytes(mem->non_gc_memory, lenstr + 1, "zinfo_filename");
+ if (f2i->filename == NULL)
+ return gs_throw_code(gs_error_VMerror);
strcpy(f2i->filename, filename);
-
+
info->data.fp = 0;
info->data.count = 0;
info->saved = false;
@@ -408,7 +423,7 @@ zip_new_info_node(gx_device_xps *xps_dev, const char *filename)
int node = 1;
gx_device_xps_f2i_t *prev_f2i;
#endif
-
+
while (f2i != NULL) {
if_debug2m('_', dev->memory, "node:%d %s\n", node++, f2i->filename);
#ifdef DEBUG
@@ -454,14 +469,14 @@ zip_append_data(gs_memory_t *mem, gx_device_xps_zinfo_t *info, byte *data, uint
archive file, open a temporary file to store the data. */
if (info->data.count == 0) {
char *filename =
- (char *)gs_alloc_bytes(mem->non_gc_memory, gp_file_name_sizeof,
+ (char *)gs_alloc_bytes(mem->non_gc_memory, gp_file_name_sizeof,
"zip_append_data(filename)");
gp_file *fp;
-
+
if (!filename) {
return(gs_throw_code(gs_error_VMerror));
}
-
+
fp = gp_open_scratch_file_rm(mem, "xpsdata-",
filename, "wb+");
gs_free_object(mem->non_gc_memory, filename, "zip_append_data(filename)");
@@ -737,7 +752,7 @@ zip_close_archive_file(gx_device_xps *xps_dev, const char *filename)
}
/* If this is a TIFF file, then update the data count information.
During the writing of the TIFF directory there is seeking and
- relocations that occur, which make data.count incorrect.
+ relocations that occur, which make data.count incorrect.
We could just do this for all the files and avoid the test. */
len = strlen(filename);
if (len > 3 && (strncmp("tif", &(filename[len - 3]), 3) == 0)) {
@@ -908,7 +923,8 @@ xps_open_device(gx_device *dev)
/* xps-specific initialization goes here */
xps->page_count = 0;
- xps->relationship_count = 0;
+ xps->relations_head = NULL;
+ xps->relations_tail = NULL;
xps->strokecolor = gx_no_color_index;
xps->fillcolor = gx_no_color_index;
xps_setstrokebrush(xps, xps_solidbrush);
@@ -934,7 +950,7 @@ xps_open_device(gx_device *dev)
fixed_document_sequence);
if (code < 0)
return gs_rethrow_code(code);
-
+
code = write_str_to_zip_file(xps, (char *)"[Content_Types].xml",
xps_content_types);
if (code < 0)
@@ -969,7 +985,7 @@ write_str_to_current_page(gx_device_xps *xps, const char *str)
int code = gs_sprintf(buf, page_template, xps->page_count+1);
if (code < 0)
return gs_rethrow_code(code);
-
+
return write_str_to_zip_file(xps, buf, str);
}
@@ -977,26 +993,38 @@ write_str_to_current_page(gx_device_xps *xps, const char *str)
static int
add_new_relationship(gx_device_xps *xps, const char *str)
{
- const char *rels_template = "Documents/1/Pages/_rels/%d.fpage.rels";
- char buf[128]; /* easily enough to accommodate the string and a page number */
- char line[300];
- const char *fmt;
+ xps_relations_t *rel;
- int code = gs_sprintf(buf, rels_template, xps->page_count + 1);
- if (code < 0)
- return gs_rethrow_code(code);
+ /* See if we already have this one */
+ for (rel = xps->relations_head; rel; rel = rel->next)
+ if (!strcmp(rel->relation, str))
+ return 0;
- /* Check if this is our first one */
- if (xps->relationship_count == 0)
- write_str_to_zip_file(xps, buf, rels_header);
-
- /* Now add the reference */
- fmt = "<Relationship Target = \"/%s\" Id = \"R%d\" Type = %s/>\n";
- gs_sprintf(line, fmt, str, xps->relationship_count, rels_req_type);
+ rel = (xps_relations_t*)gs_alloc_bytes(xps->memory->non_gc_memory,
+ sizeof(xps_relations_t), "add_new_relationship");
+ if (!rel) {
+ return gs_throw_code(gs_error_VMerror);
+ }
+ rel->memory = xps->memory->non_gc_memory;
+ rel->next = NULL;
+
+ rel->relation = (char*)gs_alloc_bytes(xps->memory->non_gc_memory,
+ strlen(str) + 1, "add_new_relationship");
+ if (!rel->relation) {
+ gs_free_object(rel->memory, rel, "add_new_relationship");
+ return gs_throw_code(gs_error_VMerror);
+ }
+ memcpy(rel->relation, str, strlen(str) + 1);
- xps->relationship_count++;
+ if (!xps->relations_head) {
+ xps->relations_head = rel;
+ xps->relations_tail = rel;
+ } else {
+ xps->relations_tail->next = rel;
+ xps->relations_tail = rel;
+ }
- return write_str_to_zip_file(xps, buf, line);
+ return 0;
}
static int
@@ -1013,6 +1041,51 @@ close_page_relationship(gx_device_xps *xps)
return 0;
}
+static int
+write_page_relationship(gx_device_xps* xps)
+{
+ const char* rels_template = "Documents/1/Pages/_rels/%d.fpage.rels";
+ char buf[128]; /* easily enough to accommodate the string and a page number */
+ char line[300];
+ const char* fmt;
+ int count = 0;
+ xps_relations_t *rel = xps->relations_head;
+
+ int code = gs_sprintf(buf, rels_template, xps->page_count + 1);
+ if (code < 0)
+ return gs_rethrow_code(code);
+
+ write_str_to_zip_file(xps, buf, rels_header);
+ fmt = "<Relationship Target = \"/%s\" Id = \"R%d\" Type = %s/>\n";
+
+ while (rel) {
+ gs_sprintf(line, fmt, rel->relation, count, rels_req_type);
+ write_str_to_zip_file(xps, buf, line);
+ rel = rel->next;
+ count++;
+ }
+
+ return 0;
+}
+
+static void
+release_relationship(gx_device_xps* xps)
+{
+ xps_relations_t *rel = xps->relations_head;
+ xps_relations_t *old;
+
+ while (rel) {
+ old = rel;
+ rel = rel->next;
+ gs_free_object(old->memory, old->relation, "release_relationship");
+ gs_free_object(old->memory, old, "release_relationship");
+ }
+
+ xps->relations_head = NULL;
+ xps->relations_tail = NULL;
+ return;
+}
+
/* Page management */
/* Complete a page */
@@ -1024,14 +1097,22 @@ xps_output_page(gx_device *dev, int num_copies, int flush)
int code;
write_str_to_current_page(xps, "</Canvas></FixedPage>");
- if (xps->relationship_count > 0)
+
+ if (xps->relations_head)
{
+ /* Write all the relations for the page */
+ code = write_page_relationship(xps);
+ if (code < 0)
+ return gs_rethrow_code(code);
+
/* Close the relationship xml */
code = close_page_relationship(xps);
if (code < 0)
return gs_rethrow_code(code);
- xps->relationship_count = 0; /* Reset for next page */
+
+ release_relationship(xps);
}
+
xps->page_count++;
if (gp_ferror(xps->file))
@@ -1070,6 +1151,23 @@ xps_release_icc_info(gx_device *dev)
return;
}
+static void
+xps_release_achive_file_names(gx_device* dev)
+{
+ gx_device_xps* xps = (gx_device_xps*)dev;
+ gx_device_xps_f2i_t *curr;
+ gx_device_xps_f2i_t *f2i = xps->f2i;
+
+ while (f2i) {
+ curr = f2i;
+ f2i = f2i->next;
+ gs_free_object(curr->memory, curr->info, "xps_release_achive_file_names(info)");
+ gs_free_object(curr->memory, curr->filename, "xps_release_achive_file_names(filename)");
+ gs_free_object(curr->memory, curr, "xps_release_achive_file_names(f2i)");
+ }
+ return;
+}
+
/* Close the device */
static int
xps_close_device(gx_device *dev)
@@ -1092,6 +1190,9 @@ xps_close_device(gx_device *dev)
/* Release the icc info */
xps_release_icc_info(dev);
+ /* Release the archive file names */
+ xps_release_achive_file_names(dev);
+
code = gdev_vector_close_file((gx_device_vector*)dev);
if (code < 0)
return gs_rethrow_code(code);
@@ -1232,10 +1333,10 @@ static int
set_state_color(gx_device_vector *vdev, const gx_drawing_color *pdc, gx_color_index *color)
{
gx_device_xps *xps = (gx_device_xps *)vdev;
-
+
/* hack so beginpage is called */
(void)gdev_vector_stream((gx_device_vector*)xps);
-
+
/* Usually this is not an actual error but a signal to the
graphics library to simplify the color */
if (!gx_dc_is_pure(pdc)) {
@@ -1252,7 +1353,7 @@ xps_setfillcolor(gx_device_vector *vdev, const gs_gstate *pgs, const gx_drawing_
gx_device_xps *xps = (gx_device_xps *)vdev;
if_debug1m('_', xps->memory, "xps_setfillcolor:%06X\n", (uint32_t)gx_dc_pure_color(pdc));
-
+
return set_state_color(vdev, pdc, &xps->fillcolor);
}
@@ -1260,9 +1361,9 @@ static int
xps_setstrokecolor(gx_device_vector *vdev, const gs_gstate *pgs, const gx_drawing_color *pdc)
{
gx_device_xps *xps = (gx_device_xps *)vdev;
-
+
if_debug1m('_', xps->memory, "xps_setstrokecolor:%06X\n", (uint32_t)gx_dc_pure_color(pdc));
-
+
return set_state_color(vdev, pdc, &xps->strokecolor);
}
@@ -1473,8 +1574,8 @@ xps_dorect(gx_device_vector *vdev, fixed x0, fixed y0,
fixed2float(x0), fixed2float(y1),
fixed2float(x1), fixed2float(y1),
fixed2float(x1), fixed2float(y0));
-
-
+
+
/* skip non-drawing paths for now */
if (!drawing_path(type, xps->filltype)) {
if_debug1m('_', xps->memory, "xps_dorect: type not supported %x\n", type);
@@ -1552,7 +1653,7 @@ gdev_xps_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
}
return gdev_vector_stroke_path(dev, pgs, ppath, params, pdcolor, pcpath);
}
-
+
static int
xps_beginpath(gx_device_vector *vdev, gx_path_type_t type)
{
@@ -1560,7 +1661,7 @@ xps_beginpath(gx_device_vector *vdev, gx_path_type_t type)
gx_device_xps *xps = (gx_device_xps *)vdev;
uint32_t c;
const char *fmt;
-
+
(void)gdev_vector_stream((gx_device_vector*)xps);
/* skip non-drawing paths for now */
@@ -1588,7 +1689,7 @@ xps_beginpath(gx_device_vector *vdev, gx_path_type_t type)
else {
write_str_to_current_page(xps, "<Path Data=\"");
}
-
+
if_debug1m('_', xps->memory, "xps_beginpath %s\n", line);
return 0;
@@ -1623,7 +1724,7 @@ xps_lineto(gx_device_vector *vdev, double x0, double y0,
char line[200];
if_debug2m('_', xps->memory, "xps_lineto %g %g\n", x, y);
-
+
/* skip non-drawing paths for now */
if (!drawing_path(type, xps->filltype)) {
if_debug1m('_', xps->memory, "xps_lineto: type not supported %x\n", type);
@@ -1642,18 +1743,18 @@ xps_curveto(gx_device_vector *vdev, double x0, double y0,
{
gx_device_xps *xps = (gx_device_xps *)vdev;
char line[200];
-
+
/* skip non-drawing paths for now */
if (!drawing_path(type, xps->filltype)) {
if_debug1m('_', xps->memory, "xps_curveto: type not supported %x\n", type);
return 0;
}
-
+
gs_sprintf(line, " C %g,%g %g,%g %g,%g", x1, y1,
x2,y2,x3,y3);
write_str_to_current_page(xps,line);
if_debug1m('_', xps->memory, "xps_curveto %s\n", line);
-
+
return 0;
}
@@ -1716,9 +1817,10 @@ static const gx_image_enum_procs_t xps_image_enum_procs = {
/* Prototypes */
static TIFF* tiff_from_name(gx_device_xps *dev, const char *name, int big_endian,
bool usebigtiff);
-static int tiff_set_values(xps_image_enum_t *pie, TIFF *tif,
+static int tiff_set_values(xps_image_enum_t *pie, TIFF *tif,
cmm_profile_t *profile, bool force8bit);
static void xps_tiff_set_handlers(void);
+static void tiff_client_release(gx_device_xps* dev, TIFF* t);
/* Check if we have the ICC profile in the package */
static xps_icc_data_t*
@@ -1770,7 +1872,7 @@ xps_add_icc_relationship(xps_image_enum_t *pie)
return 0;
}
-static int
+static int
xps_add_image_relationship(xps_image_enum_t *pie)
{
gx_device_xps *xps = (gx_device_xps*) (pie->dev);
@@ -1796,8 +1898,8 @@ xps_write_profile(const gs_gstate *pgs, char *name, cmm_profile_t *profile, gx_d
}
static int
-xps_begin_image(gx_device *dev, const gs_gstate *pgs,
- const gs_image_t *pim, gs_image_format_t format,
+xps_begin_image(gx_device *dev, const gs_gstate *pgs,
+ const gs_image_t *pim, gs_image_format_t format,
const gs_int_rect *prect, const gx_drawing_color *pdcolor,
const gx_clip_path *pcpath, gs_memory_t *mem,
gx_image_enum_common_t **pinfo)
@@ -1814,7 +1916,7 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
int bits_per_pixel;
int num_components;
int bsize;
- cmm_profile_t *icc_profile = NULL;
+ cmm_profile_t *icc_profile = NULL;
gs_color_space_index csindex;
float index_decode[2];
gsicc_rendering_param_t rendering_params;
@@ -1856,8 +1958,8 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
/* We need this set a bit early for the ICC relationship writing */
pie->dev = (gx_device*) xdev;
- /* If the color space is DeviceN, Sep or indexed these end up getting
- mapped to the color space defined by the device profile. XPS only
+ /* If the color space is DeviceN, Sep or indexed these end up getting
+ mapped to the color space defined by the device profile. XPS only
support RGB indexed images so we just expand if for now. ICC link
creation etc is handled during the remap/concretization of the colors */
if (csindex == gs_color_space_index_Indexed ||
@@ -1927,7 +2029,7 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
xdev->icc_data = icc_data;
}
- /* Get name for mark up and for relationship. Have to wait and do
+ /* Get name for mark up and for relationship. Have to wait and do
this after it is added to the package */
code = xps_create_icc_name(xdev, icc_profile, &(pie->icc_name[0]));
if (code < 0)
@@ -1944,10 +2046,13 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
/* Add ICC relationship */
xps_add_icc_relationship(pie);
} else {
- /* Get name for mark up. We already have it in the relationship and list */
+ /* Get name for mark up. We already have it in the resource list */
code = xps_create_icc_name(xdev, icc_profile, &(pie->icc_name[0]));
if (code < 0)
return gs_rethrow_code(code);
+
+ /* Add ICC relationship. It may not yet be present for this page. */
+ xps_add_icc_relationship(pie);
}
/* Get image name for mark up */
@@ -1965,8 +2070,8 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
pcpath = &cpath;
} else {
/* Force vector device to do new path as the clip path is the image
- path. I had a case where the clip path ids were the same but the
- CTM was changing which resulted in subsequent images coming up
+ path. I had a case where the clip path ids were the same but the
+ CTM was changing which resulted in subsequent images coming up
missing on the page. i.e. only the first one was shown. */
((gx_device_vector*) vdev)->clip_path_id = vdev->no_clip_path_id;
}
@@ -1996,7 +2101,7 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
pie->bytes_comp = (pie->decode_st.bps > 8 ? 2 : 1);
pie->decode_st.spp = num_components;
pie->decode_st.unpack = NULL;
- get_unpack_proc((gx_image_enum_common_t*)pie, &(pie->decode_st), pim->format,
+ get_unpack_proc((gx_image_enum_common_t*)pie, &(pie->decode_st), pim->format,
pim->Decode);
/* The decode mapping for index colors needs an adjustment */
@@ -2011,7 +2116,7 @@ xps_begin_image(gx_device *dev, const gs_gstate *pgs,
}
get_map(&(pie->decode_st), pim->format, index_decode);
} else {
- get_map(&(pie->decode_st), pim->format, pim->Decode);
+ get_map(&(pie->decode_st), pim->format, pim->Decode);
}
/* Allocate our decode buffer. */
@@ -2173,9 +2278,11 @@ const gx_image_plane_t *planes, int height, int *rows_used)
gsicc_init_buffer(&output_buff_desc, 3, bytes_comp,
false, false, false, 0, width * bytes_comp * 3,
1, width);
- (pie->icc_link->procs.map_buffer)(pie->dev, pie->icc_link,
+ code = (pie->icc_link->procs.map_buffer)(pie->dev, pie->icc_link,
&input_buff_desc, &output_buff_desc, (void*)buffer,
(void*)pie->buffer);
+ if (code < 0)
+ return code;
outbuffer = pie->buffer;
}
code = TIFFWriteScanline(pie->tif, outbuffer, pie->y, 0);
@@ -2207,6 +2314,7 @@ xps_image_end_image(gx_image_enum_common_t * info, bool draw_last)
/* N.B. Write the final strip, if any. */
code = TIFFWriteDirectory(pie->tif);
+ tiff_client_release((gx_device_xps*)(pie->dev), pie->tif);
TIFFCleanup(pie->tif);
/* Stuff the image into the zip archive and close the file */
@@ -2232,7 +2340,7 @@ exit:
#define TIFF_PRINT_BUF_LENGTH 1024
static const char tifs_msg_truncated[] = "\n*** Previous line has been truncated.\n";
-static int
+static int
tiff_set_values(xps_image_enum_t *pie, TIFF *tif, cmm_profile_t *profile,
bool force8bit)
{
@@ -2283,7 +2391,7 @@ tiff_set_values(xps_image_enum_t *pie, TIFF *tif, cmm_profile_t *profile,
typedef struct tifs_io_xps_t
{
gx_device_xps *pdev;
- gp_file *fid;
+ gp_file *fid;
} tifs_io_xps;
/* libtiff i/o hooks */
@@ -2384,7 +2492,7 @@ xps_tifsSizeProc(thandle_t fd)
}
static void
-xps_tifsWarningHandlerEx(thandle_t client_data, const char *module,
+xps_tifsWarningHandlerEx(thandle_t client_data, const char *module,
const char *fmt, va_list ap)
{
tifs_io_xps *tiffio = (tifs_io_xps *)client_data;
@@ -2403,7 +2511,7 @@ xps_tifsWarningHandlerEx(thandle_t client_data, const char *module,
}
static void
-xps_tifsErrorHandlerEx(thandle_t client_data, const char *module,
+xps_tifsErrorHandlerEx(thandle_t client_data, const char *module,
const char *fmt, va_list ap)
{
tifs_io_xps *tiffio = (tifs_io_xps *)client_data;
@@ -2484,6 +2592,13 @@ tiff_from_name(gx_device_xps *dev, const char *name, int big_endian, bool usebig
}
static void
+tiff_client_release(gx_device_xps *dev, TIFF *t)
+{
+ gs_free_object(dev->memory->non_gc_memory, TIFFClientdata(t),
+ "tiff_client_release");
+}
+
+static void
xps_image_enum_finalize(const gs_memory_t *cmem, void *vptr)
{
xps_image_enum_t *xpie = (xps_image_enum_t *)vptr;
diff --git a/devices/vector/opdfread.ps b/devices/vector/opdfread.ps
index e0d6f112..36d2049f 100644
--- a/devices/vector/opdfread.ps
+++ b/devices/vector/opdfread.ps
@@ -1,6 +1,6 @@
%!PS-Adobe-2.0
%
-% Copyright (C) 2001-2020 Artifex Software, Inc.
+% Copyright (C) 2001-2021 Artifex Software, Inc.
% All Rights Reserved.
%
% This software is provided AS-IS with no warranty, either express or
@@ -1040,10 +1040,10 @@ currentdict end readonly def
} if % id obj node
1 index exch /Context exch put % id obj
dup /ImmediateExec true put
- dup /IsPage true put
- SetPageSize {dup /Context get //SetupPageView exec} if
% This gets restored at the end of ExecuteStream if IsPage is true.
/pagesave save def
+ dup /IsPage true put
+ SetPageSize {dup /Context get //SetupPageView exec} if
} bind def
/FontFileDaemon % <id> <obj> <font_descriptor> FontFileDaemon <id> <obj>
diff --git a/devices/vector/whitelst.c b/devices/vector/whitelst.c
index af4c14fc..e06941e4 100644
--- a/devices/vector/whitelst.c
+++ b/devices/vector/whitelst.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/devices/vector/whitelst.h b/devices/vector/whitelst.h
index a566da54..8212ff37 100644
--- a/devices/vector/whitelst.h
+++ b/devices/vector/whitelst.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or