summaryrefslogtreecommitdiff
path: root/gs/src/gdevpdfw.c
diff options
context:
space:
mode:
authorL Peter Deutsch <lpd@ghostscript.com>2000-04-10 07:48:37 +0000
committerL Peter Deutsch <lpd@ghostscript.com>2000-04-10 07:48:37 +0000
commit538aef624719f9320257ff31ab59807ce08a6d74 (patch)
tree5a95edc52db15aa91ef64201c8abd0a209153b68 /gs/src/gdevpdfw.c
parentfb8b9a366c50978ee044baadc403809a29e742ba (diff)
Overhauls font embedding in the PDF writer: splits off the code into a new
file (gdevpdfe.c), writes embedded Type 1 fonts as Type 1C (CFF Type 2), and adds a little bit of code for future support of Type 0 and CID-keyed fonts. git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@287 a1074d23-0009-0410-80fe-cf8c14f379e6
Diffstat (limited to 'gs/src/gdevpdfw.c')
-rw-r--r--gs/src/gdevpdfw.c355
1 files changed, 104 insertions, 251 deletions
diff --git a/gs/src/gdevpdfw.c b/gs/src/gdevpdfw.c
index b1ca247f1..8c6ef46c0 100644
--- a/gs/src/gdevpdfw.c
+++ b/gs/src/gdevpdfw.c
@@ -21,11 +21,14 @@
#include "memory_.h"
#include "string_.h"
#include "gx.h"
+#include "gsbittab.h"
#include "gserrors.h"
#include "gsmalloc.h" /* for patching font memory */
#include "gsmatrix.h"
#include "gsutil.h" /* for bytes_compare */
+#include "gxfcid.h"
#include "gxfont.h"
+#include "gxfont0.h"
#include "gdevpdfx.h"
#include "gdevpdff.h"
#include "gdevpsf.h"
@@ -48,137 +51,22 @@ pdf_char_proc_id(const pdf_char_proc_t *pcp)
return pdf_resource_id((const pdf_resource_t *)pcp);
}
-/* Begin writing FontFile* data. */
-private int
-pdf_begin_fontfile(gx_device_pdf *pdev, long *plength_id)
-{
- stream *s;
-
- *plength_id = pdf_obj_ref(pdev);
- s = pdev->strm;
- pputs(s, "<<");
- if (!pdev->binary_ok)
- pputs(s, "/Filter/ASCII85Decode");
- pprintld1(s, "/Length %ld 0 R", *plength_id);
- return 0;
-}
-
-/* Finish writing FontFile* data. */
-private int
-pdf_end_fontfile(gx_device_pdf *pdev, long start, long length_id)
+/* Write CIDSystemInfo for a CIDFont or CMap. */
+private void
+pdf_write_CIDSystemInfo(gx_device_pdf *pdev,
+ const gs_cid_system_info_t *pcidsi)
{
stream *s = pdev->strm;
- long length;
- pputs(s, "\n");
- length = pdf_stell(pdev) - start;
- pputs(s, "endstream\n");
- pdf_end_separate(pdev);
- pdf_open_separate(pdev, length_id);
- pprintld1(pdev->strm, "%ld\n", length);
- pdf_end_separate(pdev);
- return 0;
+ pputs(s, "/CISystemInfo<<\n/Registry");
+ s_write_ps_string(s, pcidsi->Registry.data, pcidsi->Registry.size,
+ PRINT_HEX_NOT_OK);
+ pputs(s, "\n/Ordering");
+ s_write_ps_string(s, pcidsi->Ordering.data, pcidsi->Ordering.size,
+ PRINT_HEX_NOT_OK);
+ pprintd1(s, "\n/Supplement %d\n>>\n", pcidsi->Supplement);
}
-/* Write the FontFile data for an embedded Type 1 font. */
-private int
-pdf_embed_font_type1(gx_device_pdf *pdev, gs_font_type1 *font,
- long FontFile_id, gs_glyph subset_glyphs[256],
- uint subset_size, const gs_const_string *pfname)
-{
- stream poss;
- int lengths[3];
- int code;
- long length_id;
- long start;
- psdf_binary_writer writer;
-
- swrite_position_only(&poss);
- /*
- * We omit the 512 zeros and the cleartomark, and set Length3 to 0.
- * Note that the interpreter adds them implicitly (per documentation),
- * so we must set MARK so that the encrypted portion pushes a mark on
- * the stack.
- */
-#define TYPE1_OPTIONS (WRITE_TYPE1_EEXEC | WRITE_TYPE1_EEXEC_MARK)
- code = psf_write_type1_font(&poss, font, TYPE1_OPTIONS,
- subset_glyphs, subset_size, pfname, lengths);
- if (code < 0)
- return code;
- pdf_open_separate(pdev, FontFile_id);
- pdf_begin_fontfile(pdev, &length_id);
- pprintd2(pdev->strm, "/Length1 %d/Length2 %d/Length3 0>>stream\n",
- lengths[0], lengths[1]);
- start = pdf_stell(pdev);
- code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
- if (code < 0)
- return code;
-#ifdef DEBUG
- {
- int check_lengths[3];
-
- psf_write_type1_font(writer.strm, font, TYPE1_OPTIONS,
- subset_glyphs, subset_size, pfname,
- check_lengths);
- if (writer.strm == pdev->strm &&
- (check_lengths[0] != lengths[0] ||
- check_lengths[1] != lengths[1] ||
- check_lengths[2] != lengths[2])
- ) {
- lprintf7("Type 1 font id %ld, lengths mismatch: (%d,%d,%d) != (%d,%d,%d)\n",
- ((gs_font *)font)->id, lengths[0], lengths[1], lengths[2],
- check_lengths[0], check_lengths[1], check_lengths[2]);
- }
- }
-#else
- psf_write_type1_font(writer.strm, font, TYPE1_OPTIONS,
- subset_glyphs, subset_size, pfname,
- lengths /*ignored*/);
-#endif
-#undef TYPE1_OPTIONS
- psdf_end_binary(&writer);
- pdf_end_fontfile(pdev, start, length_id);
- return 0;
-}
-
-/* Write the FontFile2 data for an embedded TrueType font. */
-private int
-pdf_embed_font_type42(gx_device_pdf *pdev, gs_font_type42 *font,
- long FontFile_id, gs_glyph subset_glyphs[256],
- uint subset_size, const gs_const_string *pfname)
-{
- stream poss;
- int length;
- int code;
- long length_id;
- long start;
- psdf_binary_writer writer;
- /* Acrobat Reader 3 doesn't handle cmap format 6 correctly. */
- const int options = WRITE_TRUETYPE_CMAP | WRITE_TRUETYPE_NAME |
- (pdev->CompatibilityLevel <= 1.2 ?
- WRITE_TRUETYPE_NO_TRIMMED_TABLE : 0);
-
- swrite_position_only(&poss);
- code = psf_write_truetype_font(&poss, font, options,
- subset_glyphs, subset_size, pfname);
- if (code < 0)
- return code;
- length = stell(&poss);
- pdf_open_separate(pdev, FontFile_id);
- pdf_begin_fontfile(pdev, &length_id);
- pprintd1(pdev->strm, "/Length1 %d>>stream\n", length);
- start = pdf_stell(pdev);
- code = psdf_begin_binary((gx_device_psdf *)pdev, &writer);
- if (code < 0)
- return code;
- psf_write_truetype_font(writer.strm, font, options,
- subset_glyphs, subset_size, pfname);
- psdf_end_binary(&writer);
- pdf_end_fontfile(pdev, start, length_id);
- return 0;
-}
-
-
/* Write the Widths for a font. */
private int
pdf_write_Widths(gx_device_pdf *pdev, int first, int last,
@@ -257,27 +145,47 @@ pdf_write_synthesized_type3(gx_device_pdf *pdev, const pdf_font_t *pef)
}
/* Write a font descriptor. */
-private int
-pdf_write_FontDescriptor(gx_device_pdf *pdev,
- const pdf_font_descriptor_t *pfd)
+int
+pdf_write_FontDescriptor(gx_device_pdf *pdev, const pdf_font_descriptor_t *pfd)
{
+ gs_font *font = pfd->base_font;
+ bool is_subset =
+ pdf_has_subset_prefix(pfd->FontName.chars, pfd->FontName.size);
+ long cidset_id = 0; /* pro forma initialization */
stream *s;
int code = 0;
+ /* If this is a CIDFont subset, write the CIDSet now. */
+ if (font && is_subset) {
+ switch (pfd->values.FontType) {
+ case ft_CID_encrypted:
+ case ft_CID_TrueType: {
+ int i;
+
+ cidset_id = pdf_begin_separate(pdev);
+ s = pdev->strm;
+ /****** ADD COMPRESSION + ASCII85 ******/
+ pprintd1(s, "<</Length %d>>stream\n", (int)pfd->chars_used.size);
+ for (i = 0; i < pfd->chars_used.size; ++i)
+ pputc(s, byte_reverse_bits[pfd->chars_used.data[i]]);
+ pputs(s, "endstream\n");
+ pdf_end_separate(pdev);
+ }
+ default:
+ break;
+ }
+ }
pdf_open_separate(pdev, pdf_font_descriptor_id(pfd));
s = pdev->strm;
pputs(s, "<</Type/FontDescriptor/FontName");
pdf_put_name(pdev, pfd->FontName.chars, pfd->FontName.size);
- if (pfd->base_font) { /* not a built-in font */
+ if (font) { /* not a built-in font */
param_printer_params_t params;
- static const param_printer_params_t ppp_defaults = {
- param_printer_params_default_values
- };
printer_param_list_t rlist;
gs_param_list *const plist = (gs_param_list *)&rlist;
pdf_write_font_bbox(pdev, &pfd->values.FontBBox);
- params = ppp_defaults;
+ params = param_printer_params_default;
code = s_init_param_printer(&rlist, &params, s);
if (code >= 0) {
#define DESC_INT(str, memb)\
@@ -316,33 +224,39 @@ pdf_write_FontDescriptor(gx_device_pdf *pdev,
gs_param_write_items(plist, pfd, &defaults, optional_items);
s_release_param_printer(&rlist);
}
- if (pdf_has_subset_prefix(pfd->FontName.chars, pfd->FontName.size)) {
- gs_font *font = pfd->base_font;
- gs_glyph subset_glyphs[256];
- uint subset_size = psf_subset_glyphs(subset_glyphs, font,
- pfd->chars_used);
- int i;
-
- pputs(s, "/CharSet(");
- for (i = 0; i < subset_size; ++i) {
- uint len;
- const char *str = font->procs.callbacks.glyph_name
- (subset_glyphs[i], &len);
-
- /* Don't include .notdef. */
- if (bytes_compare((const byte *)str, len,
- (const byte *)".notdef", 7))
- pdf_put_name(pdev, (const byte *)str, len);
+ if (is_subset) {
+ switch (pfd->values.FontType) {
+ case ft_CID_encrypted:
+ case ft_CID_TrueType:
+ pprintld1(s, "/CIDSet %ld 0 R\n", cidset_id);
+ break;
+ case ft_composite:
+ return_error(gs_error_rangecheck);
+ default: {
+ gs_glyph subset_glyphs[256];
+ uint subset_size = psf_subset_glyphs(subset_glyphs, font,
+ pfd->chars_used.data);
+ int i;
+
+ pputs(s, "/CharSet(");
+ for (i = 0; i < subset_size; ++i) {
+ uint len;
+ const char *str = font->procs.callbacks.glyph_name
+ (subset_glyphs[i], &len);
+
+ /* Don't include .notdef. */
+ if (bytes_compare((const byte *)str, len,
+ (const byte *)".notdef", 7))
+ pdf_put_name(pdev, (const byte *)str, len);
+ }
+ pputs(s, ")\n");
+ }
}
- pputs(s, ")\n");
}
if (pfd->FontFile_id) {
const char *FontFile_key;
switch (pfd->values.FontType) {
- case ft_encrypted:
- FontFile_key = "/FontFile";
- break;
case ft_TrueType:
case ft_CID_TrueType:
FontFile_key = "/FontFile2";
@@ -350,6 +264,12 @@ pdf_write_FontDescriptor(gx_device_pdf *pdev,
default:
code = gs_note_error(gs_error_rangecheck);
/* falls through */
+ case ft_encrypted:
+ if (pdev->CompatibilityLevel < 1.2) {
+ FontFile_key = "/FontFile";
+ break;
+ }
+ /* For PDF 1.2 and later, write Type 1 fonts as Type1C. */
case ft_encrypted2:
case ft_CID_encrypted:
FontFile_key = "/FontFile3";
@@ -365,8 +285,8 @@ pdf_write_FontDescriptor(gx_device_pdf *pdev,
}
/*
- * Write a Type 1 or TrueType font resource, including Widths and/or
- * Encoding if relevant, but not the FontDescriptor. Note that the
+ * Write a font resource, including Widths and/or Encoding if relevant,
+ * but not the FontDescriptor or embedded font data. Note that the
* font itself may not be available.
*/
private int
@@ -383,23 +303,42 @@ pdf_write_font_resource(gx_device_pdf *pdev, const pdf_font_t *pef,
pdf_open_separate(pdev, pdf_font_id(pef));
s = pdev->strm;
switch (pef->FontType) {
- case ft_encrypted: {
+ case ft_composite:
+ pputs(s, "<</Subtype/Type0");
+ goto bfname;
+ case ft_encrypted:
+ case ft_encrypted2: {
/*
* If the font is a Multiple Master instance, it needs to be
* identified as such.
*/
if (pef->is_MM_instance) {
- pputs(s, "<</Subtype/MMType1/BaseFont");
+ pputs(s, "<</Subtype/MMType1");
/****** NAME IS WRONG ******/
- pdf_put_name(pdev, pbfname->data, pbfname->size);
} else {
- pputs(s, "<</Subtype/Type1/BaseFont");
- pdf_put_name(pdev, pbfname->data, pbfname->size);
+ pputs(s, "<</Subtype/Type1");
}
}
+ bfname:
+ pputs(s, "/BaseFont");
+ pdf_put_name(pdev, pbfname->data, pbfname->size);
break;
+ case ft_CID_encrypted:
+ pputs(s, "<</Subtype/CIDFontType0");
+ /****** REQUIRES FONT TO EXIST ******/
+ pdf_write_CIDSystemInfo(pdev, &((const gs_font_cid0 *)pfd->base_font)->
+ cidata.common.CIDSystemInfo);
+ goto bfname;
+ case ft_CID_TrueType:
+ pputs(s, "<</Subtype/CIDFontType2");
+ /****** REQUIRES FONT TO EXIST ******/
+ pdf_write_CIDSystemInfo(pdev, &((const gs_font_cid2 *)pfd->base_font)->
+ cidata.common.CIDSystemInfo);
+ goto ttname;
case ft_TrueType:
- pputs(s, "<</Subtype/TrueType/BaseFont");
+ pputs(s, "<</Subtype/TrueType");
+ ttname:
+ pputs(s, "/BaseFont");
/****** WHAT ABOUT STYLE INFO? ******/
pdf_put_name(pdev, pbfname->data, pbfname->size);
break;
@@ -411,6 +350,7 @@ pdf_write_font_resource(gx_device_pdf *pdev, const pdf_font_t *pef,
pprintld1(s, "/FontDescriptor %ld 0 R", pdf_font_descriptor_id(pfd));
if (pef->write_Widths)
pdf_write_Widths(pdev, pef->FirstChar, pef->LastChar, pef->Widths);
+ /****** WRITE CIDFont [D]W[2] ******/
if (pef->Differences) {
long diff_id = pdf_obj_ref(pdev);
int prev = 256;
@@ -440,89 +380,6 @@ pdf_write_font_resource(gx_device_pdf *pdev, const pdf_font_t *pef,
return pdf_end_separate(pdev);
}
-/*
- * Write the FontDescriptor and FontFile* data for an embedded font.
- * Return a rangecheck error if the font can't be embedded.
- */
-private int
-pdf_write_embedded_font(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd)
-{
- gs_font *font = pfd->base_font;
- gs_const_string font_name;
- byte *fnchars = pfd->FontName.chars;
- uint fnsize = pfd->FontName.size;
- bool do_subset = pfd->subset_ok && pdev->params.SubsetFonts &&
- pdev->params.MaxSubsetPct > 0;
- long FontFile_id = pfd->FontFile_id;
- gs_glyph subset_glyphs[256];
- gs_glyph *glyph_subset = 0;
- uint subset_size = 0;
- gs_matrix save_mat;
- int code;
-
- /* Determine whether to subset the font. */
- if (do_subset) {
- int used, i, total, index;
- gs_glyph ignore_glyph;
-
- for (i = 0, used = 0; i < 256/8; ++i)
- used += byte_count_bits[pfd->chars_used[i]];
- for (index = 0, total = 0;
- (font->procs.enumerate_glyph(font, &index, GLYPH_SPACE_INDEX,
- &ignore_glyph), index != 0);
- )
- ++total;
- if ((double)used / total > pdev->params.MaxSubsetPct / 100.0)
- do_subset = false;
- else {
- subset_size = psf_subset_glyphs(subset_glyphs, font,
- pfd->chars_used);
- glyph_subset = subset_glyphs;
- }
- }
-
- /* Generate an appropriate font name. */
- if (pdf_has_subset_prefix(fnchars, fnsize)) {
- /* Strip off any existing subset prefix. */
- fnsize -= SUBSET_PREFIX_SIZE;
- memmove(fnchars, fnchars + SUBSET_PREFIX_SIZE, fnsize);
- }
- if (do_subset) {
- memmove(fnchars + SUBSET_PREFIX_SIZE, fnchars, fnsize);
- pdf_make_subset_prefix(fnchars, FontFile_id);
- fnsize += SUBSET_PREFIX_SIZE;
- }
- font_name.data = fnchars;
- font_name.size = pfd->FontName.size = fnsize;
- code = pdf_write_FontDescriptor(pdev, pfd);
- if (code >= 0) {
- pfd->written = true;
-
- /*
- * Finally, write the font (or subset), using the original
- * (unscaled) FontMatrix.
- */
- save_mat = font->FontMatrix;
- font->FontMatrix = pfd->orig_matrix;
- switch (font->FontType) {
- case ft_encrypted:
- code = pdf_embed_font_type1(pdev, (gs_font_type1 *)font,
- FontFile_id, glyph_subset,
- subset_size, &font_name);
- break;
- case ft_TrueType:
- code = pdf_embed_font_type42(pdev, (gs_font_type42 *)font,
- FontFile_id, glyph_subset,
- subset_size, &font_name);
- break;
- default:
- code = gs_note_error(gs_error_rangecheck);
- }
- font->FontMatrix = save_mat;
- }
- return code;
-}
-
/* Register a font for eventual writing (embedded or not). */
private GS_NOTIFY_PROC(pdf_font_notify_proc);
typedef struct pdf_font_notify_s {
@@ -665,6 +522,7 @@ pdf_font_unreg_proc(void *vpfn /*proc_data*/)
gs_free_object(pfn->memory, vpfn, "pdf_font_unreg_proc");
}
+/* Write out the font resources when wrapping up the output. */
int
pdf_write_font_resources(gx_device_pdf *pdev)
{
@@ -712,10 +570,5 @@ pdf_write_font_resources(gx_device_pdf *pdev)
}
}
}
-
- /* Unregister the standard fonts. */
-
- pdf_unregister_fonts(pdev);
-
return 0;
}