summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/type0.c
diff options
context:
space:
mode:
authorPeter Breitenlohner <peb@mppmu.mpg.de>2013-07-05 13:19:04 +0000
committerPeter Breitenlohner <peb@mppmu.mpg.de>2013-07-05 13:19:04 +0000
commite54eda8832ef70dfae37d4200bd56bd2dee6118e (patch)
treea039e3a605db6104dc47ead65f07061df23a847c /Build/source/texk/dvipdfm-x/type0.c
parentcf1fc7b4d3f71633ca71e17dd7044722d19ceda4 (diff)
dvipdfm-x: Continue merging dvipdfmx and xdvipdfmx
git-svn-id: svn://tug.org/texlive/trunk@31095 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/type0.c')
-rw-r--r--Build/source/texk/dvipdfm-x/type0.c691
1 files changed, 691 insertions, 0 deletions
diff --git a/Build/source/texk/dvipdfm-x/type0.c b/Build/source/texk/dvipdfm-x/type0.c
new file mode 100644
index 00000000000..a9069e77ef3
--- /dev/null
+++ b/Build/source/texk/dvipdfm-x/type0.c
@@ -0,0 +1,691 @@
+/*
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * Type0 font support:
+ *
+ * TODO:
+ *
+ * Composite font (multiple descendants) - not supported in PDF
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "system.h"
+#include "mem.h"
+#include "error.h"
+#include "dpxfile.h"
+
+#include "pdfobj.h"
+#include "fontmap.h"
+
+#include "cmap.h"
+#include "cid.h"
+
+#include "type0.h"
+
+
+#define TYPE0FONT_DEBUG_STR "Type0"
+#define TYPE0FONT_DEBUG 3
+
+static int __verbose = 0;
+
+static pdf_obj *pdf_read_ToUnicode_file (const char *cmap_name);
+
+void
+Type0Font_set_verbose(void)
+{
+ __verbose++;
+}
+
+/*
+ * used_chars:
+ *
+ * Single bit is used for each CIDs since used_chars can be reused as a
+ * stream content of CIDSet by doing so. See, cid.h for add_to_used() and
+ * is_used().
+ */
+
+static char *
+new_used_chars2(void)
+{
+ char *used_chars;
+
+ used_chars = NEW(8192, char);
+ memset(used_chars, 0, 8192);
+
+ return used_chars;
+}
+
+#define FLAG_NONE 0
+#define FLAG_USED_CHARS_SHARED (1 << 0)
+
+struct Type0Font {
+ char *fontname; /* BaseFont */
+ char *encoding; /* "Identity-H" or "Identity-V" (not ID) */
+ char *used_chars; /* Used chars (CIDs) */
+
+ /*
+ * Type0 only
+ */
+ CIDFont *descendant; /* Only single descendant is allowed. */
+ int flags;
+ int wmode;
+
+ /*
+ * PDF Font Resource
+ */
+ pdf_obj *indirect;
+ pdf_obj *fontdict;
+ pdf_obj *descriptor; /* MUST BE NULL */
+};
+
+static void
+Type0Font_init_font_struct (Type0Font *font)
+{
+ ASSERT(font);
+
+ font->fontname = NULL;
+ font->fontdict = NULL;
+ font->indirect = NULL;
+ font->descriptor = NULL;
+ font->encoding = NULL;
+ font->used_chars = NULL;
+ font->descendant = NULL;
+ font->wmode = -1;
+ font->flags = FLAG_NONE;
+
+ return;
+}
+
+static void
+Type0Font_clean (Type0Font *font)
+{
+ if (font) {
+ if (font->fontdict)
+ ERROR("%s: Object not flushed.", TYPE0FONT_DEBUG_STR);
+ if (font->indirect)
+ ERROR("%s: Object not flushed.", TYPE0FONT_DEBUG_STR);
+ if (font->descriptor)
+ ERROR("%s: FontDescriptor unexpected for Type0 font.", TYPE0FONT_DEBUG_STR);
+ if (!(font->flags & FLAG_USED_CHARS_SHARED) && font->used_chars)
+ RELEASE(font->used_chars);
+ if (font->encoding)
+ RELEASE(font->encoding);
+ if (font->fontname)
+ RELEASE(font->fontname);
+ font->fontdict = NULL;
+ font->indirect = NULL;
+ font->descriptor = NULL;
+ font->used_chars = NULL;
+ font->encoding = NULL;
+ font->fontname = NULL;
+ }
+}
+
+/* PLEASE FIX THIS */
+#include "tt_cmap.h"
+
+static void
+add_ToUnicode (Type0Font *font)
+{
+ pdf_obj *tounicode;
+ CIDFont *cidfont;
+ CIDSysInfo *csi;
+ char *cmap_name, *fontname;
+
+ /*
+ * ToUnicode CMap:
+ *
+ * ToUnicode CMaps are usually not required for standard character
+ * collections such as Adobe-Japan1. Identity-H is used for UCS
+ * ordering CID-keyed fonts. External resource must be loaded for
+ * others.
+ */
+
+ cidfont = font->descendant;
+ if (!cidfont) {
+ ERROR("%s: No descendant CID-keyed font.", TYPE0FONT_DEBUG_STR);
+ return;
+ }
+
+ if (CIDFont_is_ACCFont(cidfont)) {
+ /* No need to embed ToUnicode */
+ return;
+ } else if (CIDFont_is_UCSFont(cidfont)) {
+ /*
+ * Old version of dvipdfmx mistakenly used Adobe-Identity as Unicode.
+ */
+ tounicode = pdf_read_ToUnicode_file("Adobe-Identity-UCS2");
+ if (!tounicode) { /* This should work */
+ tounicode = pdf_new_name("Identity-H");
+ }
+ pdf_add_dict(font->fontdict, pdf_new_name("ToUnicode"), tounicode);
+ return;
+ }
+
+ tounicode = NULL;
+ csi = CIDFont_get_CIDSysInfo(cidfont);
+ fontname = CIDFont_get_fontname(cidfont);
+ if (CIDFont_get_embedding(cidfont)) {
+ fontname += 7; /* FIXME */
+ }
+
+ if (!strcmp(csi->registry, "Adobe") &&
+ !strcmp(csi->ordering, "Identity")) {
+ switch (CIDFont_get_subtype(cidfont)) {
+ case CIDFONT_TYPE2:
+ /* PLEASE FIX THIS */
+ tounicode = otf_create_ToUnicode_stream(CIDFont_get_ident(cidfont),
+ CIDFont_get_opt_index(cidfont),
+#ifdef XETEX
+ CIDFont_get_ft_face(cidfont),
+#endif
+ Type0Font_get_usedchars(font));
+ break;
+ default:
+ if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1C)) { /* FIXME */
+ tounicode = otf_create_ToUnicode_stream(CIDFont_get_ident(cidfont),
+ CIDFont_get_opt_index(cidfont),
+#ifdef XETEX
+ CIDFont_get_ft_face(cidfont),
+#endif
+ Type0Font_get_usedchars(font));
+ } else if (CIDFont_get_flag(cidfont, CIDFONT_FLAG_TYPE1)) { /* FIXME */
+ /* Font loader will create ToUnicode and set. */
+ return;
+ } else {
+ cmap_name = NEW(strlen(fontname) + 7, char);
+ sprintf(cmap_name, "%s-UTF16", fontname);
+ tounicode = pdf_read_ToUnicode_file(cmap_name);
+ if (!tounicode) {
+ sprintf(cmap_name, "%s-UCS2", fontname);
+ tounicode = pdf_read_ToUnicode_file(cmap_name);
+ }
+ RELEASE(cmap_name);
+ }
+ break;
+ }
+ } else {
+ cmap_name = NEW(strlen(csi->registry)+strlen(csi->ordering)+8, char);
+ sprintf(cmap_name, "%s-%s-UTF16", csi->registry, csi->ordering);
+ tounicode = pdf_read_ToUnicode_file(cmap_name);
+ if (!tounicode) {
+ sprintf(cmap_name, "%s-%s-UCS2", csi->registry, csi->ordering);
+ tounicode = pdf_read_ToUnicode_file(cmap_name);
+ }
+ RELEASE(cmap_name);
+ }
+
+ if (tounicode) {
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("ToUnicode"), tounicode);
+ } else {
+ WARN("Failed to load ToUnicode CMap for font \"%s\"", fontname);
+ }
+
+ return;
+}
+
+void
+Type0Font_set_ToUnicode (Type0Font *font, pdf_obj *cmap_ref)
+{
+ ASSERT(font);
+
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("ToUnicode"), cmap_ref);
+}
+
+static void
+Type0Font_dofont (Type0Font *font)
+{
+ if (!font || !font->indirect)
+ return;
+
+ if (!pdf_lookup_dict(font->fontdict, "ToUnicode")) { /* FIXME */
+ add_ToUnicode(font);
+ }
+}
+
+static void
+Type0Font_flush (Type0Font *font)
+{
+ if (font) {
+ if (font->fontdict)
+ pdf_release_obj(font->fontdict);
+ font->fontdict = NULL;
+ if (font->indirect)
+ pdf_release_obj(font->indirect);
+ font->indirect = NULL;
+ if (font->descriptor)
+ ERROR("%s: FontDescriptor unexpected for Type0 font.", TYPE0FONT_DEBUG_STR);
+ font->descriptor = NULL;
+ }
+}
+
+int
+Type0Font_get_wmode (Type0Font *font)
+{
+ ASSERT(font);
+
+ return font->wmode;
+}
+
+#if 0
+char *
+Type0Font_get_encoding (Type0Font *font)
+{
+ ASSERT(font);
+
+ return font->encoding;
+}
+#endif
+
+char *
+Type0Font_get_usedchars (Type0Font *font)
+{
+ ASSERT(font);
+
+ return font->used_chars;
+}
+
+pdf_obj *
+Type0Font_get_resource (Type0Font *font)
+{
+ ASSERT(font);
+
+ /*
+ * This looks somewhat strange.
+ */
+ if (!font->indirect) {
+ pdf_obj *array;
+
+ array = pdf_new_array();
+ pdf_add_array(array, CIDFont_get_resource(font->descendant));
+ pdf_add_dict(font->fontdict, pdf_new_name("DescendantFonts"), array);
+ font->indirect = pdf_ref_obj(font->fontdict);
+ }
+
+ return pdf_link_obj(font->indirect);
+}
+
+/******************************** CACHE ********************************/
+
+#define CHECK_ID(n) do {\
+ if ((n) < 0 || (n) >= __cache.count)\
+ ERROR("%s: Invalid ID %d", TYPE0FONT_DEBUG_STR, (n));\
+} while (0)
+
+#define CACHE_ALLOC_SIZE 16u
+
+static struct font_cache {
+ int count;
+ int capacity;
+ Type0Font *fonts;
+} __cache = {
+ 0, 0, NULL
+};
+
+void
+Type0Font_cache_init (void)
+{
+ if (__cache.fonts)
+ ERROR("%s: Already initialized.", TYPE0FONT_DEBUG_STR);
+ __cache.count = 0;
+ __cache.capacity = 0;
+ __cache.fonts = NULL;
+}
+
+Type0Font *
+Type0Font_cache_get (int id)
+{
+ CHECK_ID(id);
+
+ return &__cache.fonts[id];
+}
+
+#ifdef XETEX
+unsigned short*
+Type0Font_get_ft_to_gid(int id)
+{
+ return CIDFont_get_ft_to_gid(Type0Font_cache_get(id)->descendant);
+}
+#endif
+
+int
+Type0Font_cache_find (const char *map_name, int cmap_id, fontmap_opt *fmap_opt)
+{
+ int font_id = -1;
+ Type0Font *font;
+ CIDFont *cidfont;
+ CMap *cmap;
+ CIDSysInfo *csi;
+ char *fontname = NULL;
+ int cid_id = -1, parent_id = -1, wmode = 0;
+ int pdf_ver;
+
+ pdf_ver = pdf_get_version();
+ if (!map_name || cmap_id < 0 || pdf_ver < 2)
+ return -1;
+
+ /*
+ * Encoding is Identity-H or Identity-V according as thier WMode value.
+ *
+ * We do not use match against the map_name since fonts (TrueType) covers
+ * characters across multiple character collection (eg, Adobe-Japan1 and
+ * Adobe-Japan2) must be splited into multiple CID-keyed fonts.
+ */
+
+ cmap = CMap_cache_get(cmap_id);
+ csi = (CMap_is_Identity(cmap)) ? NULL : CMap_get_CIDSysInfo(cmap) ;
+
+ cid_id = CIDFont_cache_find(map_name, csi, fmap_opt);
+
+ if (cid_id < 0)
+ return -1;
+
+ /*
+ * The descendant CID-keyed font has already been registerd.
+ * If CID-keyed font with ID = cid_id is new font, then create new parent
+ * Type 0 font. Otherwise, there already exists parent Type 0 font and
+ * then we find him and return his ID. We must check against their WMode.
+ */
+
+ cidfont = CIDFont_cache_get(cid_id);
+ wmode = CMap_get_wmode(cmap);
+
+ /* Does CID-keyed font already have parent ? */
+ parent_id = CIDFont_get_parent_id(cidfont, wmode);
+ if (parent_id >= 0)
+ return parent_id; /* If so, we don't need new one. */
+
+ /*
+ * CIDFont does not have parent or his parent's WMode does not matched with
+ * wmode. Create new Type0 font.
+ */
+
+ if (__cache.count >= __cache.capacity) {
+ __cache.capacity += CACHE_ALLOC_SIZE;
+ __cache.fonts = RENEW(__cache.fonts, __cache.capacity, struct Type0Font);
+ }
+ font_id = __cache.count;
+ font = &__cache.fonts[font_id];
+
+ Type0Font_init_font_struct(font);
+
+ /*
+ * All CJK double-byte characters are mapped so that resulting
+ * character codes coincide with CIDs of given character collection.
+ * So, the Encoding is always Identity-H for horizontal fonts or
+ * Identity-V for vertical fonts.
+ */
+ if (wmode) {
+ font->encoding = NEW(strlen("Identity-V")+1, char);
+ strcpy(font->encoding, "Identity-V");
+ } else {
+ font->encoding = NEW(strlen("Identity-H")+1, char);
+ strcpy(font->encoding, "Identity-H");
+ }
+ font->wmode = wmode;
+
+ /*
+ * Now we start font dictionary.
+ */
+ font->fontdict = pdf_new_dict();
+ pdf_add_dict(font->fontdict, pdf_new_name ("Type"), pdf_new_name ("Font"));
+ pdf_add_dict(font->fontdict, pdf_new_name ("Subtype"), pdf_new_name ("Type0"));
+
+ /*
+ * Type0 font does not have FontDescriptor because it is not a simple font.
+ * Instead, DescendantFonts appears here.
+ *
+ * Up to PDF version 1.5, Type0 font must have single descendant font which
+ * is a CID-keyed font. Future PDF spec. will allow multiple desecendant
+ * fonts.
+ */
+ font->descendant = cidfont;
+ CIDFont_attach_parent(cidfont, font_id, wmode);
+
+ /*
+ * PostScript Font name:
+ *
+ * Type0 font's fontname is usually descendant CID-keyed font's font name
+ * appended by -ENCODING.
+ */
+ fontname = CIDFont_get_fontname(cidfont);
+
+ if (__verbose) {
+ if (CIDFont_get_embedding(cidfont) && strlen(fontname) > 7)
+ MESG("(CID:%s)", fontname+7); /* skip XXXXXX+ */
+ else
+ MESG("(CID:%s)", fontname);
+ }
+
+ /*
+ * The difference between CID-keyed font and TrueType font appears here.
+ *
+ * Glyph substitution for vertical writing is done in CMap mapping process
+ * for CID-keyed fonts. But we must rely on OpenType layout table in the
+ * case of TrueType fonts. So, we must use different used_chars for each
+ * horizontal and vertical fonts in that case.
+ *
+ * In most PDF file, encoding name is not appended to fontname for Type0
+ * fonts having CIDFontType 2 font as their descendant.
+ */
+
+ font->used_chars = NULL;
+ font->flags = FLAG_NONE;
+
+ switch (CIDFont_get_subtype(cidfont)) {
+ case CIDFONT_TYPE0:
+ font->fontname = NEW(strlen(fontname)+strlen(font->encoding)+2, char);
+ sprintf(font->fontname, "%s-%s", fontname, font->encoding);
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("BaseFont"), pdf_new_name(font->fontname));
+ /*
+ * Need used_chars to write W, W2.
+ */
+ if ((parent_id = CIDFont_get_parent_id(cidfont, wmode ? 0 : 1)) < 0)
+ font->used_chars = new_used_chars2();
+ else {
+ /* Don't allocate new one. */
+ font->used_chars = Type0Font_get_usedchars(Type0Font_cache_get(parent_id));
+ font->flags |= FLAG_USED_CHARS_SHARED;
+ }
+ break;
+ case CIDFONT_TYPE2:
+ /*
+ * TrueType:
+ *
+ * Use different used_chars for H and V.
+ */
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("BaseFont"), pdf_new_name(fontname));
+ font->used_chars = new_used_chars2();
+ break;
+ default:
+ ERROR("Unrecognized CIDFont Type");
+ break;
+ }
+
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("Encoding"), pdf_new_name(font->encoding));
+
+ __cache.count++;
+
+ return font_id;
+}
+
+void
+Type0Font_cache_close (void)
+{
+ int font_id;
+
+ /*
+ * This need to be fixed.
+ *
+ * CIDFont_cache_close() before Type0Font_release because of used_chars.
+ * ToUnicode support want descendant CIDFont's CSI and fontname.
+ */
+ if (__cache.fonts) {
+ for (font_id = 0; font_id < __cache.count; font_id++)
+ Type0Font_dofont(&__cache.fonts[font_id]);
+ }
+ CIDFont_cache_close();
+ if (__cache.fonts) {
+ for (font_id = 0; font_id < __cache.count; font_id++) {
+ Type0Font_flush(&__cache.fonts[font_id]);
+ Type0Font_clean(&__cache.fonts[font_id]);
+ }
+ RELEASE(__cache.fonts);
+ }
+ __cache.fonts = NULL;
+ __cache.count = 0;
+ __cache.capacity = 0;
+}
+
+
+/************************************************************************/
+
+int
+pdf_font_findfont0 (const char *font_name, int cmap_id, fontmap_opt *fmap_opt)
+{
+ return Type0Font_cache_find(font_name, cmap_id, fmap_opt);
+}
+
+/******************************** COMPAT ********************************/
+
+#ifndef WITHOUT_COMPAT
+
+#include "cmap_read.h"
+#include "cmap_write.h"
+#include "pdfresource.h"
+#include "pdfencoding.h"
+
+static pdf_obj *
+create_dummy_CMap (void)
+{
+ pdf_obj *stream;
+ char buf[32];
+ int i, n;
+
+#define CMAP_PART0 "\
+%!PS-Adobe-3.0 Resource-CMap\n\
+%%DocumentNeededResources: ProcSet (CIDInit)\n\
+%%IncludeResource: ProcSet (CIDInit)\n\
+%%BeginResource: CMap (Adobe-Identity-UCS2)\n\
+%%Title: (Adobe-Identity-UCS2 Adobe UCS2 0)\n\
+%%Version: 1.0\n\
+%%Copyright:\n\
+%% ---\n\
+%%EndComments\n\n\
+"
+#define CMAP_PART1 "\
+/CIDInit /ProcSet findresource begin\n\
+\n\
+12 dict begin\n\nbegincmap\n\n\
+/CIDSystemInfo 3 dict dup begin\n\
+ /Registry (Adobe) def\n\
+ /Ordering (UCS2) def\n\
+ /Supplement 0 def\n\
+end def\n\n\
+/CMapName /Adobe-Identity-UCS2 def\n\
+/CMapVersion 1.0 def\n\
+/CMapType 2 def\n\n\
+2 begincodespacerange\n\
+<0000> <FFFF>\n\
+endcodespacerange\n\
+"
+#define CMAP_PART3 "\
+endcmap\n\n\
+CMapName currentdict /CMap defineresource pop\n\n\
+end\nend\n\n\
+%%EndResource\n\
+%%EOF\n\
+"
+
+ stream = pdf_new_stream(STREAM_COMPRESS);
+ pdf_add_stream(stream, CMAP_PART0, strlen(CMAP_PART0));
+ pdf_add_stream(stream, CMAP_PART1, strlen(CMAP_PART1));
+ pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
+ for (i = 0; i < 0x64; i++) {
+ n = sprintf(buf,
+ "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
+ pdf_add_stream(stream, buf, n);
+ }
+ pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
+
+ pdf_add_stream(stream, "\n100 beginbfrange\n", strlen("\n100 beginbfrange\n"));
+ for (i = 0x64; i < 0xc8; i++) {
+ n = sprintf(buf,
+ "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
+ pdf_add_stream(stream, buf, n);
+ }
+ pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
+
+ pdf_add_stream(stream, "\n48 beginbfrange\n", strlen("\n48 beginbfrange\n"));
+ for (i = 0xc8; i <= 0xd7; i++) {
+ n = sprintf(buf,
+ "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
+ pdf_add_stream(stream, buf, n);
+ }
+ for (i = 0xe0; i <= 0xff; i++) {
+ n = sprintf(buf,
+ "<%02X00> <%02XFF> <%02X00>\n", i, i, i);
+ pdf_add_stream(stream, buf, n);
+ }
+ pdf_add_stream(stream, "endbfrange\n\n", strlen("endbfrange\n\n"));
+
+ pdf_add_stream(stream, CMAP_PART3, strlen(CMAP_PART3));
+
+ return stream;
+}
+
+static pdf_obj *
+pdf_read_ToUnicode_file (const char *cmap_name)
+{
+ pdf_obj *stream;
+ long res_id = -1;
+
+ ASSERT(cmap_name);
+
+ res_id = pdf_findresource("CMap", cmap_name);
+ if (res_id < 0) {
+ if (!strcmp(cmap_name, "Adobe-Identity-UCS2"))
+ stream = create_dummy_CMap();
+ else {
+ stream = pdf_load_ToUnicode_stream(cmap_name);
+ }
+ if (stream) {
+ res_id = pdf_defineresource("CMap",
+ cmap_name,
+ stream, PDF_RES_FLUSH_IMMEDIATE);
+ }
+ }
+
+ return (res_id < 0 ? NULL : pdf_get_resource_reference(res_id));
+}
+#endif /* !WITHOUT_COMPAT */