From 80096425836c7c322a5ffb3dd7e96e2247d062d0 Mon Sep 17 00:00:00 2001 From: Akira Kakuto Date: Tue, 22 Sep 2020 01:13:44 +0000 Subject: Simplify font related code. Fix a bug in determinant calculation. (S. Hirata) git-svn-id: svn://tug.org/texlive/trunk@56400 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/dvipdfm-x/pdffont.c | 1132 +++++++++++++++++++-------------- 1 file changed, 637 insertions(+), 495 deletions(-) (limited to 'Build/source/texk/dvipdfm-x/pdffont.c') diff --git a/Build/source/texk/dvipdfm-x/pdffont.c b/Build/source/texk/dvipdfm-x/pdffont.c index 5e38733d3c8..cc05c2e1ac9 100644 --- a/Build/source/texk/dvipdfm-x/pdffont.c +++ b/Build/source/texk/dvipdfm-x/pdffont.c @@ -47,9 +47,9 @@ #include "pkfont.h" +#include "cidtype0.h" #include "type0.h" #include "tt_cmap.h" -#include "cidtype0.h" #include "pdffont.h" @@ -66,16 +66,6 @@ pdf_font_make_uniqueTag (char *tag) { int i; char ch; - static char first = 1; - - if (first) { - time_t current_time; - current_time = dpx_util_get_unique_time_if_given(); - if (current_time == INVALID_EPOCH_VALUE) - current_time = time(NULL); - srand(current_time); - first = 0; - } for (i = 0; i < 6; i++) { ch = rand() % 26; @@ -84,58 +74,25 @@ pdf_font_make_uniqueTag (char *tag) tag[6] = '\0'; } - -struct pdf_font -{ - char *ident; - int subtype; - - char *map_name; - - int encoding_id; /* encoding or CMap */ - - /* - * If subtype is Type0, it simply points font_id - * of Type0 font. Type0 and simple font is not - * unified yet. - */ - int font_id; - - /* For simple font */ - uint32_t index; - char *fontname; - char uniqueID[7]; - - /* - * PDF font resource objects - */ - pdf_obj *reference; - pdf_obj *resource; - pdf_obj *descriptor; - - /* - * Font format specific data - */ - char *usedchars; - int flags; - - /* PK font */ - double point_size; - double design_size; -}; +static void +init_CIDSysInfo (CIDSysInfo *csi) { + csi->registry = NULL; + csi->ordering = NULL; + csi->supplement = 0; +} static void pdf_init_font_struct (pdf_font *font) { ASSERT(font); - font->ident = NULL; - font->map_name = NULL; - font->subtype = -1; - font->font_id = -1; /* Type0 ID */ - font->fontname = NULL; + font->ident = NULL; + font->filename = NULL; + font->subtype = -1; + font->font_id = -1; + font->fontname = NULL; memset(font->uniqueID, 0, 7); - font->index = 0; + font->index = 0; font->encoding_id = -1; @@ -149,6 +106,16 @@ pdf_init_font_struct (pdf_font *font) font->usedchars = NULL; font->flags = 0; + font->type0.descendant = -1; + font->type0.wmode = 0; + + init_CIDSysInfo(&font->cid.csi); + font->cid.usedchars_v = NULL; + font->cid.options.embed = 0; + font->cid.options.style = FONT_STYLE_NONE; + font->cid.options.stemv = 0; + init_CIDSysInfo(&font->cid.options.csi); + return; } @@ -157,37 +124,39 @@ pdf_flush_font (pdf_font *font) { char *fontname, *uniqueTag; - if (!font) { + if (!font) + return; + if ((font->flags & PDF_FONT_FLAG_IS_ALIAS) || (font->flags & PDF_FONT_FLAG_IS_REENCODE)) { return; } if (font->resource && font->reference) { - if (font->subtype != PDF_FONT_FONTTYPE_TYPE3) { - if (pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { - pdf_add_dict(font->resource, - pdf_new_name("BaseFont"), pdf_new_name(font->fontname)); - if (font->descriptor) { - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), pdf_new_name(font->fontname)); - } + switch (font->subtype) { + case PDF_FONT_FONTTYPE_TYPE3: + case PDF_FONT_FONTTYPE_TYPE0: + break; + case PDF_FONT_FONTTYPE_CIDTYPE0: + case PDF_FONT_FONTTYPE_CIDTYPE2: + break; + default: + if (font->flags & PDF_FONT_FLAG_NOEMBED) { + pdf_add_dict(font->resource, pdf_new_name("BaseFont"), pdf_new_name(font->fontname)); + if (font->descriptor) { + pdf_add_dict(font->descriptor, pdf_new_name("FontName"), pdf_new_name(font->fontname)); + } } else { - if (!font->fontname) { - ERROR("Undefined in fontname... (%s)", font->ident); - } - fontname = NEW(7+strlen(font->fontname)+1, char); - uniqueTag = pdf_font_get_uniqueTag(font); - sprintf(fontname, "%6s+%s", uniqueTag, font->fontname); - pdf_add_dict(font->resource, - pdf_new_name("BaseFont"), pdf_new_name(fontname)); - if (font->descriptor) { - pdf_add_dict(font->descriptor, - pdf_new_name("FontName"), pdf_new_name(fontname)); - } - RELEASE(fontname); + ASSERT(font->fontname); + fontname = NEW(7+strlen(font->fontname)+1, char); + uniqueTag = pdf_font_get_uniqueTag(font); + sprintf(fontname, "%6s+%s", uniqueTag, font->fontname); + pdf_add_dict(font->resource, pdf_new_name("BaseFont"), pdf_new_name(fontname)); + if (font->descriptor) { + pdf_add_dict(font->descriptor, pdf_new_name("FontName"), pdf_new_name(fontname)); + } + RELEASE(fontname); } if (font->descriptor) { - pdf_add_dict(font->resource, - pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor)); + pdf_add_dict(font->resource, pdf_new_name("FontDescriptor"), pdf_ref_obj(font->descriptor)); } } } @@ -209,28 +178,42 @@ pdf_flush_font (pdf_font *font) static void pdf_clean_font_struct (pdf_font *font) { - if (font) { - if (font->ident) - RELEASE(font->ident); - if (font->map_name) - RELEASE(font->map_name); - if (font->fontname) - RELEASE(font->fontname); - if (font->usedchars) - RELEASE(font->usedchars); - - if (font->reference) - ERROR("pdf_font>> Object not flushed."); - if (font->resource) - ERROR("pdf_font> Object not flushed."); - if (font->descriptor) - ERROR("pdf_font>> Object not flushed."); - - font->ident = NULL; - font->map_name = NULL; - font->fontname = NULL; - font->usedchars = NULL; + if (!font) + return; + + if (font->resource) + WARN("font \"%s\" not properly released?", font->ident); + + if (font->ident) + RELEASE(font->ident); + if (font->filename) + RELEASE(font->filename); + if (font->fontname) + RELEASE(font->fontname); + if (font->usedchars) { + if (!(font->flags & PDF_FONT_FLAG_USEDCHAR_SHARED)) + RELEASE(font->usedchars); } + if (font->cid.csi.registry) + RELEASE(font->cid.csi.registry); + if (font->cid.csi.ordering) + RELEASE(font->cid.csi.ordering); + if (font->cid.options.csi.registry) + RELEASE(font->cid.options.csi.registry); + if (font->cid.options.csi.ordering) + RELEASE(font->cid.options.csi.ordering); + if (font->cid.usedchars_v) + RELEASE(font->cid.usedchars_v); + + font->ident = NULL; + font->filename = NULL; + font->fontname = NULL; + font->usedchars = NULL; + font->cid.csi.registry = NULL; + font->cid.csi.ordering = NULL; + font->cid.options.csi.registry = NULL; + font->cid.options.csi.ordering = NULL; + font->cid.usedchars_v = NULL; return; } @@ -255,11 +238,18 @@ pdf_init_fonts (void) CMap_cache_init(); pdf_init_encodings(); - Type0Font_cache_init(); - font_cache.count = 0; font_cache.capacity = CACHE_ALLOC_SIZE; font_cache.fonts = NEW(font_cache.capacity, pdf_font); + + { + time_t current_time; + + current_time = dpx_util_get_unique_time_if_given(); + if (current_time == INVALID_EPOCH_VALUE) + current_time = time(NULL); + srand(current_time); + } } #define CHECK_ID(n) do {\ @@ -267,8 +257,41 @@ pdf_init_fonts (void) ERROR("Invalid font ID: %d", (n));\ }\ } while (0) -#define GET_FONT(n) (&(font_cache.fonts[(n)])) +static pdf_font * +GET_FONT (int font_id) +{ + pdf_font *font = NULL; + + if (font_id >= 0 && font_id < font_cache.count) { + font = &font_cache.fonts[font_id]; + if (font->flags & PDF_FONT_FLAG_IS_ALIAS) { + font = &font_cache.fonts[font->font_id]; + } + } + + return font; +} + +pdf_font * +pdf_get_font_data (int font_id) +{ + CHECK_ID(font_id); + + return &font_cache.fonts[font_id]; +} + +char * +pdf_get_font_ident (int font_id) +{ + pdf_font *font; + + CHECK_ID(font_id); + + font = &font_cache.fonts[font_id]; + + return font->ident; +} pdf_obj * pdf_get_font_reference (int font_id) @@ -278,20 +301,42 @@ pdf_get_font_reference (int font_id) CHECK_ID(font_id); font = GET_FONT(font_id); + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font = GET_FONT(font->font_id); + } + if (!font->reference) { + font->reference = pdf_ref_obj(pdf_font_get_resource(font)); + } if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) { - Type0Font *t0font; + if (!pdf_lookup_dict(font->resource, "DescendantFonts")) { + pdf_obj *array; - t0font = Type0Font_cache_get(font->font_id); - return Type0Font_get_resource(t0font); - } else { - if (!font->reference) { - font->reference = pdf_ref_obj(pdf_font_get_resource(font)); + array = pdf_new_array(); + pdf_add_array(array, pdf_get_font_reference(font->type0.descendant)); + pdf_add_dict(font->resource, pdf_new_name("DescendantFonts"), array); } } return pdf_link_obj(font->reference); } +pdf_obj * +pdf_get_font_resource (int font_id) +{ + pdf_font *font; + + CHECK_ID(font_id); + + font = GET_FONT(font_id); + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font = GET_FONT(font->font_id); + } + if (!font->resource) + font->resource = pdf_new_dict(); + + return font->resource; /* FIXME */ +} + char * pdf_get_font_usedchars (int font_id) { @@ -300,18 +345,17 @@ pdf_get_font_usedchars (int font_id) CHECK_ID(font_id); font = GET_FONT(font_id); - if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) { - Type0Font *t0font; - - t0font = Type0Font_cache_get(font->font_id); - return Type0Font_get_usedchars(t0font); - } else { + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font = GET_FONT(font->font_id); + } + if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) { if (!font->usedchars) { font->usedchars = NEW(256, char); memset(font->usedchars, 0, 256 * sizeof(char)); } - return font->usedchars; } + + return font->usedchars; } int @@ -322,11 +366,11 @@ pdf_get_font_wmode (int font_id) CHECK_ID(font_id); font = GET_FONT(font_id); + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font = GET_FONT(font->font_id); + } if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) { - Type0Font *t0font; - - t0font = Type0Font_cache_get(font->font_id); - return Type0Font_get_wmode(t0font); + return font->type0.wmode; } else { return 0; } @@ -340,13 +384,15 @@ pdf_get_font_subtype (int font_id) CHECK_ID(font_id); font = GET_FONT(font_id); + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font = GET_FONT(font->font_id); + } return font->subtype; } -#if 0 -char * -pdf_get_font_fontname (int font_id) +int +pdf_get_font_encoding (int font_id) { pdf_font *font; @@ -354,20 +400,28 @@ pdf_get_font_fontname (int font_id) font = GET_FONT(font_id); - return font->fontname; + return font->encoding_id; } -#endif /* 0 */ int -pdf_get_font_encoding (int font_id) +pdf_font_resource_name (int font_id, char *buff) { + int len; pdf_font *font; CHECK_ID(font_id); + font = &font_cache.fonts[font_id]; + if (font->flags & PDF_FONT_FLAG_IS_ALIAS) { + font_id = font->font_id; + } font = GET_FONT(font_id); + if (font->flags & PDF_FONT_FLAG_IS_REENCODE) { + font_id = font->font_id; + } + len = sprintf(buff, "F%d", font_id); - return font->encoding_id; + return len; } /* The rule for ToUnicode creation is: @@ -381,10 +435,9 @@ pdf_get_font_encoding (int font_id) static int try_load_ToUnicode_CMap (pdf_font *font) { - pdf_obj *fontdict; pdf_obj *tounicode; const char *cmap_name = NULL; - fontmap_rec *mrec; /* Be sure fontmap is still alive here */ + fontmap_rec *mrec = NULL; /* Be sure fontmap is still alive here */ ASSERT(font); @@ -394,29 +447,32 @@ try_load_ToUnicode_CMap (pdf_font *font) if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) return 0; - ASSERT(font->map_name); + ASSERT(font->ident); - mrec = pdf_lookup_fontmap_record(font->map_name); - if (MREC_HAS_TOUNICODE(mrec)) + mrec = pdf_lookup_fontmap_record(font->ident); + if (MREC_HAS_TOUNICODE(mrec)) { cmap_name = mrec->opt.tounicode; - else { - cmap_name = font->map_name; + } else { + cmap_name = font->ident; } - - fontdict = pdf_font_get_resource(font); tounicode = pdf_load_ToUnicode_stream(cmap_name); - if (!tounicode && MREC_HAS_TOUNICODE(mrec)) - WARN("Failed to read ToUnicode mapping \"%s\"...", mrec->opt.tounicode); - else if (tounicode) { - if (pdf_obj_typeof(tounicode) != PDF_STREAM) + + if (!tounicode) { + if (MREC_HAS_TOUNICODE(mrec)) { + WARN("Failed to read ToUnicode mapping \"%s\"...", mrec->opt.tounicode); + } + } else { + if (pdf_obj_typeof(tounicode) != PDF_STREAM) { ERROR("Object returned by pdf_load_ToUnicode_stream() not stream object! (This must be bug)"); - else if (pdf_stream_length(tounicode) > 0) { + } else if (pdf_stream_length(tounicode) > 0) { + pdf_obj *fontdict = pdf_font_get_resource(font); + pdf_add_dict(fontdict, pdf_new_name("ToUnicode"), pdf_ref_obj (tounicode)); /* _FIXME_ */ if (dpx_conf.verbose_level > 0) MESG("pdf_font>> ToUnicode CMap \"%s\" attached to font id=\"%s\".\n", - cmap_name, font->map_name); + cmap_name, font->ident); } pdf_release_obj(tounicode); } @@ -429,91 +485,133 @@ pdf_close_fonts (void) { int font_id; - for (font_id = 0; - font_id < font_cache.count; font_id++) { + for (font_id = 0; font_id < font_cache.count; font_id++) { pdf_font *font; - font = GET_FONT(font_id); + font = &font_cache.fonts[font_id]; + if ((font->flags & PDF_FONT_FLAG_IS_ALIAS) || + (font->flags & PDF_FONT_FLAG_IS_REENCODE)) { + continue; + } + if (font->subtype == PDF_FONT_FONTTYPE_CIDTYPE0 || + font->subtype == PDF_FONT_FONTTYPE_CIDTYPE2) + continue; if (dpx_conf.verbose_level > 0) { if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) { - MESG("(%s", pdf_font_get_ident(font)); - if (dpx_conf.verbose_level > 2 && - !pdf_font_get_flag(font, PDF_FONT_FLAG_NOEMBED)) { - MESG("[%s+%s]", - pdf_font_get_uniqueTag(font), - pdf_font_get_fontname(font)); - } else if (dpx_conf.verbose_level > 1) { - MESG("[%s]", pdf_font_get_fontname(font)); - } - if (dpx_conf.verbose_level > 1) { - if (pdf_font_get_encoding(font) >= 0) { - MESG("[%s]", pdf_encoding_get_name(pdf_font_get_encoding(font))); - } else { - MESG("[built-in]"); - } - } + MESG("(%s", font->filename); + if (dpx_conf.verbose_level > 2 && + !(font->flags & PDF_FONT_FLAG_NOEMBED)) { + MESG("[%s+%s]", pdf_font_get_uniqueTag(font), font->fontname); + } else if (dpx_conf.verbose_level > 1) { + MESG("[%s]", font->fontname); + } + if (dpx_conf.verbose_level > 1) { + if (font->encoding_id >= 0) { + MESG("[%s]", pdf_encoding_get_name(font->encoding_id)); + } else { + MESG("[built-in]"); + } + } } } /* Must come before load_xxx */ try_load_ToUnicode_CMap(font); - /* Type 0 is handled separately... */ switch (font->subtype) { case PDF_FONT_FONTTYPE_TYPE1: if (dpx_conf.verbose_level > 0) - MESG("[Type1]"); - if (!pdf_font_get_flag(font, PDF_FONT_FLAG_BASEFONT)) - pdf_font_load_type1(font); + MESG("[Type1]"); + if (!(font->flags & PDF_FONT_FLAG_BASEFONT)) + pdf_font_load_type1(font); break; case PDF_FONT_FONTTYPE_TYPE1C: if (dpx_conf.verbose_level > 0) - MESG("[Type1C]"); + MESG("[Type1C]"); pdf_font_load_type1c(font); break; case PDF_FONT_FONTTYPE_TRUETYPE: if (dpx_conf.verbose_level > 0) - MESG("[TrueType]"); + MESG("[TrueType]"); pdf_font_load_truetype(font); break; case PDF_FONT_FONTTYPE_TYPE3: if (dpx_conf.verbose_level > 0) - MESG("[Type3/PK]"); + MESG("[Type3/PK]"); pdf_font_load_pkfont (font); break; case PDF_FONT_FONTTYPE_TYPE0: - break; - default: - ERROR("Unknown font type: %d", font->subtype); + if (dpx_conf.verbose_level > 0) + MESG("[Type0]"); + pdf_font_load_type0(font); break; } - if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0) - pdf_encoding_add_usedchars(font->encoding_id, font->usedchars); + if (font->encoding_id >= 0) { + if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) { + pdf_encoding_add_usedchars(font->encoding_id, font->usedchars); + } + } if (dpx_conf.verbose_level > 0) { - if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) - MESG(")"); + if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) { + MESG(")"); + } } } pdf_encoding_complete(); + /* Order is important... */ + for (font_id = 0; font_id < font_cache.count; font_id++) { + pdf_font *font = &font_cache.fonts[font_id]; + + if ((font->flags & PDF_FONT_FLAG_IS_ALIAS) || + (font->flags & PDF_FONT_FLAG_IS_REENCODE)) { + continue; + } + + switch (font->subtype) { + case PDF_FONT_FONTTYPE_CIDTYPE0: + case PDF_FONT_FONTTYPE_CIDTYPE2: + pdf_font_load_cidfont(font); + break; + } + } for (font_id = 0; font_id < font_cache.count; font_id++) { - pdf_font *font = GET_FONT(font_id); + pdf_font *font; + + font = &font_cache.fonts[font_id]; - if (font->encoding_id >= 0 && font->subtype != PDF_FONT_FONTTYPE_TYPE0) { + if ((font->flags & PDF_FONT_FLAG_IS_ALIAS) || + (font->flags & PDF_FONT_FLAG_IS_REENCODE)) { + pdf_clean_font_struct(font); + continue; + } + + if (font->encoding_id >= 0 && + font->subtype != PDF_FONT_FONTTYPE_TYPE0 && + font->subtype != PDF_FONT_FONTTYPE_CIDTYPE0 && + font->subtype != PDF_FONT_FONTTYPE_CIDTYPE2) { pdf_obj *enc_obj = pdf_get_encoding_obj(font->encoding_id); pdf_obj *tounicode; /* Predefined encodings (and those simplified to them) are embedded - * as direct objects, but this is purely a matter of taste. + * as direct objects, but this is purely a matter of taste. */ - if (enc_obj) - pdf_add_dict(font->resource, - pdf_new_name("Encoding"), - PDF_OBJ_NAMETYPE(enc_obj) ? pdf_link_obj(enc_obj) : pdf_ref_obj(enc_obj)); + if (enc_obj) { + if (font->subtype == PDF_FONT_FONTTYPE_TRUETYPE) { + if (pdf_encoding_is_predefined(font->encoding_id) && PDF_OBJ_NAMETYPE(enc_obj)) { + pdf_add_dict(font->resource, + pdf_new_name("Encoding"), pdf_link_obj(enc_obj)); + } + } else { + pdf_add_dict(font->resource, + pdf_new_name("Encoding"), + PDF_OBJ_NAMETYPE(enc_obj) ? pdf_link_obj(enc_obj) : pdf_ref_obj(enc_obj)); + } + } /* For built-in encoding, each font loader create ToUnicode CMap. */ if (!pdf_lookup_dict(font->resource, "ToUnicode")) { tounicode = pdf_encoding_get_tounicode(font->encoding_id); @@ -529,17 +627,15 @@ pdf_close_fonts (void) pdf_new_name("Encoding"), pdf_new_name("MacRomanEncoding")); } - pdf_flush_font(font); pdf_clean_font_struct(font); } + RELEASE(font_cache.fonts); font_cache.fonts = NULL; font_cache.count = 0; font_cache.capacity = 0; - Type0Font_cache_close(); - CMap_cache_close(); pdf_close_encodings(); @@ -549,19 +645,148 @@ pdf_close_fonts (void) } int -pdf_font_findresource (const char *tex_name, - double font_scale, fontmap_rec *mrec) +pdf_font_findresource (const char *ident, double scale) +{ + int font_id, found = 0; + + for (font_id = 0; font_id < font_cache.count; font_id++) { + pdf_font *font; + + font = &font_cache.fonts[font_id]; + switch (font->subtype) { + case PDF_FONT_FONTTYPE_TYPE1: + case PDF_FONT_FONTTYPE_TYPE1C: + case PDF_FONT_FONTTYPE_TRUETYPE: + case PDF_FONT_FONTTYPE_TYPE0: + if (!strcmp(ident, font->ident)) { + found = 1; + } + break; + case PDF_FONT_FONTTYPE_TYPE3: + /* There shouldn't be any encoding specified for PK font. + * It must be always font's build-in encoding. + * + * TODO: a PK font with two encodings makes no sense. Change? + */ + if (!strcmp(ident, font->ident) && scale == font->point_size) { + found = 1; + } + break; + } + + if (found) { + if (dpx_conf.verbose_level > 0) { + MESG("\npdf_font>> Font \"%s\" (enc_id=%d) found at id=%d.\n", font->ident, font->encoding_id, font_id); + } + break; + } + } + + return found ? font_id : -1; +} + +#if 1 +static void +compat_set_mapchar (int cmap_id, fontmap_rec *mrec) +{ + CMap *cmap; + int cmap_type, minbytes; + + cmap = CMap_cache_get(cmap_id); + cmap_type = CMap_get_type(cmap); + minbytes = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN); + + if (cmap_type != CMAP_TYPE_IDENTITY && + cmap_type != CMAP_TYPE_CODE_TO_CID && + cmap_type != CMAP_TYPE_TO_UNICODE) { + WARN("Only 16-bit encoding supported for output encoding."); + } + /* Turn on map option. */ + if (minbytes == 2 && mrec->opt.mapc < 0) { + if (dpx_conf.verbose_level > 0) { + MESG("\n"); + MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n", CMap_get_name(cmap)); + MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name); + } + /* FIXME: The following code modifies mrec. */ + mrec->opt.mapc = 0; + } + + return; +} +#endif + +static int +create_font_alias (const char *ident, int font_id) +{ + int this_id; + pdf_font *font, *src; + + if (font_id < 0 || font_id >= font_cache.count) + return -1; + + src = &font_cache.fonts[font_id]; + + this_id = font_cache.count; + if (font_cache.count >= font_cache.capacity) { + font_cache.capacity += CACHE_ALLOC_SIZE; + font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); + } + font = &font_cache.fonts[this_id]; + pdf_init_font_struct(font); + + font->ident = NEW(strlen(ident) + 1, char); + strcpy(font->ident, ident); + font->font_id = font_id; + font->subtype = src->subtype; + font->encoding_id = src->encoding_id; + + font->flags |= PDF_FONT_FLAG_IS_ALIAS; + + font_cache.count++; + + return this_id; +} + +static int +create_font_reencoded (const char *ident, int font_id, int cmap_id) +{ + int this_id; + pdf_font *font; + + if (font_cache.count + 1 >= font_cache.capacity) { + font_cache.capacity += CACHE_ALLOC_SIZE; + font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); + } + + this_id = font_cache.count; + font = &font_cache.fonts[this_id]; + pdf_init_font_struct(font); + font->ident = NEW(strlen(ident) + 1, char); + strcpy(font->ident, ident); + font->font_id = font_id; + font->subtype = PDF_FONT_FONTTYPE_TYPE0; + font->encoding_id = cmap_id; + font->flags |= PDF_FONT_FLAG_IS_REENCODE; + font->flags |= PDF_FONT_FLAG_USEDCHAR_SHARED; + font_cache.count++; + + return this_id; +} + +int +pdf_font_load_font (const char *ident, double font_scale, fontmap_rec *mrec) { - int font_id = -1; - pdf_font *font; - int encoding_id = -1, cmap_id = -1; - const char *fontname; + int font_id = -1; + pdf_font *font; + int encoding_id = -1, cmap_id = -1; + const char *fontname; /* * Get appropriate info from map file. (PK fonts at two different * point sizes would be looked up twice unecessarily.) */ - fontname = mrec ? mrec->font_name : tex_name; + fontname = mrec ? mrec->font_name : ident; /* XeTeX specific... * First try loading GID-to-CID mapping from CFF CID-keyed OpenType font. * There was a serious bug in xdv support... It was implemented with the wrong @@ -580,253 +805,218 @@ pdf_font_findresource (const char *tex_name, else { WARN("Unexpected encoding specified for xdv: %s", mrec->enc_name); } - /* cmap_id < 0 is returned if ... - * Font is not a CFF font - * GID to CID mapping is identity mapping - * - * TODO: fontmap record still has Identity CMap assigned but actually different CMap - * can be attached to the font here. Should we fix mrec->enc_name here? - */ + /* cmap_id < 0 is returned if ... + * Font is not a CFF font + * GID to CID mapping is identity mapping + * + * TODO: fontmap record still has Identity CMap assigned but actually different CMap + * can be attached to the font here. Should we fix mrec->enc_name here? + */ cmap_id = otf_try_load_GID_to_CID_map(mrec->font_name, mrec->opt.index, wmode); } } + if (cmap_id < 0 && mrec && mrec->enc_name) { -#define MAYBE_CMAP(s) (!strstr((s), ".enc") || strstr((s), ".cmap")) - if (MAYBE_CMAP(mrec->enc_name)) { + if (!strcmp(mrec->enc_name, "unicode")) { + cmap_id = otf_load_Unicode_CMap(mrec->font_name, + mrec->opt.index, mrec->opt.otl_tags, + ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0)); + if (cmap_id < 0) { + cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags, + ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0)); + } + } else if (!strstr(mrec->enc_name, ".enc") || strstr(mrec->enc_name, ".cmap")) { cmap_id = CMap_cache_find(mrec->enc_name); +#if 1 if (cmap_id >= 0) { - CMap *cmap; - int cmap_type, minbytes; - - cmap = CMap_cache_get(cmap_id); - cmap_type = CMap_get_type (cmap); - minbytes = CMap_get_profile(cmap, CMAP_PROF_TYPE_INBYTES_MIN); - /* - * Check for output encoding. - */ - if (cmap_type != CMAP_TYPE_IDENTITY && - cmap_type != CMAP_TYPE_CODE_TO_CID && - cmap_type != CMAP_TYPE_TO_UNICODE) { - WARN("Only 16-bit encoding supported for output encoding."); - } - /* - * Turn on map option. - */ - if (minbytes == 2 && mrec->opt.mapc < 0) { - if (dpx_conf.verbose_level > 0) { - MESG("\n"); - MESG("pdf_font>> Input encoding \"%s\" requires at least 2 bytes.\n", - CMap_get_name(cmap)); - MESG("pdf_font>> The -m <00> option will be assumed for \"%s\".\n", mrec->font_name); - } - /* FIXME: The following code modifies mrec. */ - mrec->opt.mapc = 0; - } - } else if (!strcmp(mrec->enc_name, "unicode")) { - cmap_id = otf_load_Unicode_CMap(mrec->font_name, - mrec->opt.index, mrec->opt.otl_tags, - ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0)); - if (cmap_id < 0) { - cmap_id = t1_load_UnicodeCMap(mrec->font_name, mrec->opt.otl_tags, - ((mrec->opt.flags & FONTMAP_OPT_VERT) ? 1 : 0)); - } - if (cmap_id < 0) - ERROR("Failed to read UCS2/UCS4 TrueType cmap..."); + compat_set_mapchar(cmap_id, mrec); } +#endif } if (cmap_id < 0) { encoding_id = pdf_encoding_findresource(mrec->enc_name); - if (encoding_id < 0) - ERROR("Could not find encoding file \"%s\".", mrec->enc_name); } } - if (mrec && cmap_id >= 0) { - /* - * Composite Font - */ - int type0_id, found = 0; - type0_id = Type0Font_cache_find(mrec->font_name, cmap_id, &mrec->opt); - if (type0_id < 0) { + if (mrec && mrec->enc_name) { + if (cmap_id < 0 && encoding_id < 0) { + WARN("Could not read encoding file: %s", mrec->enc_name); return -1; } + } - for (font_id = 0; - font_id < font_cache.count; font_id++) { - font = GET_FONT(font_id); - if (font->subtype == PDF_FONT_FONTTYPE_TYPE0 && - font->font_id == type0_id && - font->encoding_id == cmap_id) { - found = 1; - if (dpx_conf.verbose_level > 0) { - MESG("\npdf_font>> Type0 font \"%s\" (cmap_id=%d) found at font_id=%d.\n", - mrec->font_name, cmap_id, font_id); - } - break; + if (mrec && cmap_id >= 0) { + /* Composite font */ + CMap *cmap; + CIDSysInfo *csi; + int wmode, cid_id; + + cmap = CMap_cache_get(cmap_id); + csi = CMap_is_Identity(cmap) ? NULL : CMap_get_CIDSysInfo(cmap); + wmode = CMap_get_wmode(cmap); + + cid_id = pdf_font_cidfont_lookup_cache(font_cache.fonts, font_cache.count, mrec->font_name, csi, &mrec->opt); + if (cid_id >= 0) { + for (font_id = 0; font_id < font_cache.count; font_id++) { + font = &font_cache.fonts[font_id]; + if (font->subtype != PDF_FONT_FONTTYPE_TYPE0) + continue; + if (font->type0.wmode == wmode && font->type0.descendant == cid_id) { + break; + } } - } - - if (!found) { - font_id = font_cache.count; - if (font_cache.count >= font_cache.capacity) { - font_cache.capacity += CACHE_ALLOC_SIZE; - font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); + if (font_id >= 0 && font_id < font_cache.count) { + font = &font_cache.fonts[font_id]; + if (font->encoding_id == cmap_id) { + if (dpx_conf.verbose_level > 0) { + MESG("\npdf_font>> Type0 font \"%s\" cmap_id=<%s,%d> found at font_id=<%s,%d>.\n", + mrec->font_name, mrec->enc_name, cmap_id, pdf_get_font_ident(font_id), font_id); + } + if (!strcmp(ident, font->ident)) { + return font_id; + } else { + return create_font_alias(ident, font_id); + } + } else { + if (dpx_conf.verbose_level > 0) { + MESG("\npdf_font>> Type0 font \"%s\" cmap_id=<%s,%d> found at font_id=<%s,%d>. (re-encoded)\n", + mrec->font_name, mrec->enc_name, cmap_id, pdf_get_font_ident(font_id), font_id); + } + return create_font_reencoded(ident, font_id, cmap_id); + } } - font = GET_FONT(font_id); - pdf_init_font_struct(font); + } - font->font_id = type0_id; - font->subtype = PDF_FONT_FONTTYPE_TYPE0; - font->encoding_id = cmap_id; + /* plus one for CIDFont */ + if (font_cache.count + 1 >= font_cache.capacity) { + font_cache.capacity += CACHE_ALLOC_SIZE; + font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); + } - font_cache.count++; + if (cid_id < 0) { + pdf_font *cidfont; - if (dpx_conf.verbose_level > 0) { - MESG("\npdf_font>> Type0 font \"%s\"", fontname); - MESG(" cmap_id=<%s,%d>", mrec->enc_name, font->encoding_id); - MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id); + cid_id = font_cache.count; + cidfont = &font_cache.fonts[cid_id]; + pdf_init_font_struct(cidfont); + if (pdf_font_open_cidfont(cidfont, fontname, csi, &mrec->opt) < 0) { + pdf_clean_font_struct(cidfont); + return -1; } + font_cache.count++; + } + font_id = font_cache.count; + font = &font_cache.fonts[font_id]; + pdf_init_font_struct(font); + if (pdf_font_open_type0(font, cid_id, wmode) < 0) { + pdf_clean_font_struct(font); + return -1; + } + font->ident = NEW(strlen(ident) + 1, char); + strcpy(font->ident, ident); + font->subtype = PDF_FONT_FONTTYPE_TYPE0; + font->encoding_id = cmap_id; + + font_cache.count++; + if (dpx_conf.verbose_level > 0) { + MESG("\n"); + MESG("pdf_font>> Type0 font \"%s\" ", fontname); + MESG("cmap_id=<%s,%d> ", mrec->enc_name, font->encoding_id); + MESG("font_id=<%s,%d>.", ident, font_id); + MESG("\n"); } } else { - /* - * Simple Font - always embed. - */ - int found = 0; - - for (font_id = 0; - font_id < font_cache.count; font_id++) { - font = GET_FONT(font_id); + /* Simple Font - always embed. */ + for (font_id = 0; font_id < font_cache.count; font_id++) { + font = &font_cache.fonts[font_id]; + if (font->flags & PDF_FONT_FLAG_IS_ALIAS) + continue; switch (font->subtype) { case PDF_FONT_FONTTYPE_TYPE1: case PDF_FONT_FONTTYPE_TYPE1C: case PDF_FONT_FONTTYPE_TRUETYPE: - /* fontname here is font file name. - * We must compare both font file name and encoding - * - * TODO: Embed a font only once if it is used - * with two different encodings - */ - if (!strcmp(fontname, font->ident) && - encoding_id == font->encoding_id) { - if (mrec && mrec->opt.index == font->index) - found = 1; - } - break; + /* fontname here is font file name. + * We must compare both font file name and encoding + * + * TODO: Embed a font only once if it is used + * with two different encodings + */ + if (!strcmp(fontname, font->filename) && encoding_id == font->encoding_id && + (!mrec || mrec->opt.index == font->index)) { + if (dpx_conf.verbose_level > 0) { + MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n", fontname, encoding_id, font_id); + } + if (!strcmp(ident, font->ident)) { + return font_id; + } else { + return create_font_alias(ident, font_id); + } + } + break; case PDF_FONT_FONTTYPE_TYPE3: - /* There shouldn't be any encoding specified for PK font. - * It must be always font's build-in encoding. - * - * TODO: a PK font with two encodings makes no sense. Change? - */ - if (!strcmp(fontname, font->ident) && - font_scale == font->point_size) { - found = 1; - } - break; - case PDF_FONT_FONTTYPE_TYPE0: - break; - default: - ERROR("Unknown font type: %d", font->subtype); - break; - } - - if (found) { - if (dpx_conf.verbose_level > 0) { - MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n", - fontname, encoding_id, font_id); - } - break; + /* There shouldn't be any encoding specified for PK font. + * It must be always font's build-in encoding. + * + * TODO: a PK font with two encodings makes no sense. Change? + */ + if (!strcmp(fontname, font->filename) && font_scale == font->point_size) { + if (dpx_conf.verbose_level > 0) { + MESG("\npdf_font>> Simple font \"%s\" (enc_id=%d) found at id=%d.\n", fontname, encoding_id, font_id); + } + if (!strcmp(ident, font->ident)) { + return font_id; + } else { + return create_font_alias(ident, font_id); + } + } + break; } } + font_id = font_cache.count; + if (font_cache.count >= font_cache.capacity) { + font_cache.capacity += CACHE_ALLOC_SIZE; + font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); + } - if (!found) { - font_id = font_cache.count; - if (font_cache.count >= font_cache.capacity) { - font_cache.capacity += CACHE_ALLOC_SIZE; - font_cache.fonts = RENEW(font_cache.fonts, font_cache.capacity, pdf_font); - } - - font = GET_FONT(font_id); - - pdf_init_font_struct(font); - - font->point_size = font_scale; - font->encoding_id = encoding_id; - font->ident = NEW(strlen(fontname) + 1, char); - strcpy(font->ident, fontname); - font->map_name = NEW(strlen(tex_name) + 1, char); - strcpy(font->map_name, tex_name); - font->index = (mrec && mrec->opt.index) ? mrec->opt.index : 0; - - if (pdf_font_open_type1(font) >= 0) { - font->subtype = PDF_FONT_FONTTYPE_TYPE1; - } else if (pdf_font_open_type1c(font) >= 0) { - font->subtype = PDF_FONT_FONTTYPE_TYPE1C; - } else if (pdf_font_open_truetype(font) >= 0) { - font->subtype = PDF_FONT_FONTTYPE_TRUETYPE; - } else if (pdf_font_open_pkfont(font) >= 0) { - font->subtype = PDF_FONT_FONTTYPE_TYPE3; - } else { - pdf_clean_font_struct(font); - return -1; - } + font = &font_cache.fonts[font_id]; + pdf_init_font_struct(font); + + font->ident = NEW(strlen(ident) + 1, char); + strcpy(font->ident, ident); + font->encoding_id = encoding_id; + font->filename = NEW(strlen(fontname) + 1, char); + strcpy(font->filename, fontname); + font->index = (mrec && mrec->opt.index) ? mrec->opt.index : 0; + font->flags |= (mrec && (mrec->opt.flags & FONTMAP_OPT_NOEMBED)) ? PDF_FONT_FLAG_NOEMBED : 0; + if (pdf_font_open_type1(font, font->filename, font->index, font->encoding_id, (font->flags & PDF_FONT_FLAG_NOEMBED) ? 0 : 1) >= 0) { + font->subtype = PDF_FONT_FONTTYPE_TYPE1; + } else if (pdf_font_open_type1c(font, font->filename, font->index, font->encoding_id, (font->flags & PDF_FONT_FLAG_NOEMBED) ? 0 : 1) >= 0) { + font->subtype = PDF_FONT_FONTTYPE_TYPE1C; + } else if (pdf_font_open_truetype(font, font->filename, font->index, font->encoding_id, (font->flags & PDF_FONT_FLAG_NOEMBED) ? 0 : 1) >= 0) { + font->subtype = PDF_FONT_FONTTYPE_TRUETYPE; + } else if (pdf_font_open_pkfont(font,font->filename, font->index, font->encoding_id, (font->flags & PDF_FONT_FLAG_NOEMBED) ? 0 : 1, font->point_size) >= 0) { + font->subtype = PDF_FONT_FONTTYPE_TYPE3; + } else { + pdf_clean_font_struct(font); + return -1; + } - font_cache.count++; + font_cache.count++; - if (dpx_conf.verbose_level > 0) { - MESG("\npdf_font>> Simple font \"%s\"", fontname); - MESG(" enc_id=<%s,%d>", - (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id); - MESG(" opened at font_id=<%s,%d>.\n", tex_name, font_id); - } + if (dpx_conf.verbose_level > 0) { + MESG("\n"); + MESG("pdf_font>> Simple font \"%s\" ", fontname); + MESG("enc_id=<%s,%d> ", (mrec && mrec->enc_name) ? mrec->enc_name : "builtin", font->encoding_id); + MESG("font_id=<%s,%d>.", ident, font_id); + MESG("\n"); } } return font_id; } -int -pdf_font_is_in_use (pdf_font *font) -{ - ASSERT(font); - - return ((font->reference) ? 1 : 0); -} - -uint32_t -pdf_font_get_index (pdf_font *font) -{ - ASSERT(font); - - return font->index; -} - -char * -pdf_font_get_ident (pdf_font *font) -{ - ASSERT(font); - - return font->ident; -} - -char * -pdf_font_get_mapname (pdf_font *font) -{ - ASSERT(font); - - return font->map_name; -} - -char * -pdf_font_get_fontname (pdf_font *font) -{ - ASSERT(font); - - return font->fontname; -} - pdf_obj * pdf_font_get_resource (pdf_font *font) { @@ -834,21 +1024,17 @@ pdf_font_get_resource (pdf_font *font) if (!font->resource) { font->resource = pdf_new_dict(); - pdf_add_dict(font->resource, - pdf_new_name("Type"), pdf_new_name("Font")); + pdf_add_dict(font->resource, pdf_new_name("Type"), pdf_new_name("Font")); switch (font->subtype) { case PDF_FONT_FONTTYPE_TYPE1: case PDF_FONT_FONTTYPE_TYPE1C: - pdf_add_dict(font->resource, - pdf_new_name("Subtype"), pdf_new_name("Type1")); + pdf_add_dict(font->resource, pdf_new_name("Subtype"), pdf_new_name("Type1")); break; case PDF_FONT_FONTTYPE_TYPE3: - pdf_add_dict(font->resource, - pdf_new_name("Subtype"), pdf_new_name("Type3")); + pdf_add_dict(font->resource, pdf_new_name("Subtype"), pdf_new_name("Type3")); break; case PDF_FONT_FONTTYPE_TRUETYPE: - pdf_add_dict(font->resource, - pdf_new_name("Subtype"), pdf_new_name("TrueType")); + pdf_add_dict(font->resource, pdf_new_name("Subtype"), pdf_new_name("TrueType")); break; default: break; @@ -863,70 +1049,16 @@ pdf_font_get_descriptor (pdf_font *font) { ASSERT(font); - if (!font->descriptor) { + if (font->subtype == PDF_FONT_FONTTYPE_TYPE0) { + return NULL; + } else if (!font->descriptor) { font->descriptor = pdf_new_dict(); - pdf_add_dict(font->descriptor, - pdf_new_name("Type"), pdf_new_name("FontDescriptor")); + pdf_add_dict(font->descriptor, pdf_new_name("Type"), pdf_new_name("FontDescriptor")); } return font->descriptor; } -char * -pdf_font_get_usedchars (pdf_font *font) -{ - ASSERT(font); - - return font->usedchars; -} - -int -pdf_font_get_encoding (pdf_font *font) -{ - ASSERT(font); - - return font->encoding_id; -} - -int -pdf_font_get_flag (pdf_font *font, int mask) -{ - ASSERT(font); - - return ((font->flags & mask) ? 1 : 0); -} - -#if 0 -int -pdf_font_get_flags (pdf_font *font) -{ - ASSERT(font); - - return font->flags; -} -#endif /* 0 */ - -double -pdf_font_get_param (pdf_font *font, int param_type) -{ - double param = 0.0; - - ASSERT(font); - - switch (param_type) { - case PDF_FONT_PARAM_DESIGN_SIZE: - param = font->design_size; - break; - case PDF_FONT_PARAM_POINT_SIZE: - param = font->point_size; - break; - default: - break; - } - - return param; -} - char * pdf_font_get_uniqueTag (pdf_font *font) { @@ -939,41 +1071,51 @@ pdf_font_get_uniqueTag (pdf_font *font) return font->uniqueID; } -int -pdf_font_set_fontname (pdf_font *font, const char *fontname) -{ - ASSERT(font && fontname); - - if (strlen(fontname) > PDF_NAME_LEN_MAX) { - ERROR("Unexpected error..."); - return -1; - } - if (font->fontname) { - RELEASE(font->fontname); - } - font->fontname = NEW(strlen(fontname)+1, char); - strcpy(font->fontname, fontname); - - return 0; -} - -int -pdf_font_set_subtype (pdf_font *font, int subtype) -{ - ASSERT(font); - - font->subtype = subtype; +/* + * Please don’t use TFM widths for the /Widths + * entry of the font dictionary. + * + * PDF 32000-1:2008 (p.255) + * + * These widths shall be consistent with the + * actual widths given in the font program. + */ - return 0; -} +#include "tfm.h" int -pdf_font_set_flags (pdf_font *font, int flags) +pdf_check_tfm_widths (const char *ident, double *widths, int firstchar, int lastchar, const char *usedchars) { - ASSERT(font); + int error = 0; + int tfm_id, code, count = 0; + double sum = 0.0; + double tolerance = 1.0; + int override = 0; /* Don't set to 1! */ + + tfm_id = tfm_open(ident, 0); + if (tfm_id < 0) + return 0; + for (code = firstchar; code <= lastchar; code++) { + if (usedchars[code]) { + double width, diff; + + width = 1000. * tfm_get_width(tfm_id, code); + diff = widths[code] - width; + diff = diff < 0 ? -diff : diff; + if (override) { + widths[code] = width; + } else if (diff > tolerance) { + if (dpx_conf.verbose_level > 0) { + WARN("Intolerable difference in glyph width: font=%s, char=%d", ident, code); + WARN("font: %g vs. tfm: %g", widths[code], width); + } + sum += diff; + } + count++; + } + } - font->flags |= flags; + error = sum > 0.5 * count * tolerance ? -1 : 0; - return 0; + return override ? 0 : error; } - -- cgit v1.2.3