#include "libtexpdf.h"
#include "numbers.h"
#include "mem.h"
#include "error.h"
#include "dpxfile.h"
#include "pdfobj.h"
#include "pdffont.h"
#ifndef PDF_NAME_LEN_MAX
# define PDF_NAME_LEN_MAX 255
#endif
#include "sfnt.h"
#include "tt_aux.h"
#include "tt_glyf.h"
#include "tt_cmap.h"
#include "tt_table.h"
#include "tt_gsub.h"
#include "cmap.h"
#include "type0.h"
#include "cid.h"
#include "cid_p.h"
#include "cidtype2.h"
static int verbose = 0;
static int opt_flags = 0;
void
CIDFont_type2_set_verbose (void)
{
verbose++;
}
void
CIDFont_type2_set_flags (long flags)
{
opt_flags = flags;
}
static struct
{
const char *name;
int must_exist;
} required_table[] = {
{"OS/2", 0}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1},
{"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0},
{"prep", 0}, {NULL, 0}
};
static void
validate_name (char *fontname, int len)
{
int i, count;
char *p;
static const char *badstrlist[] = {
"-WIN-RKSJ-H",
"-WINP-RKSJ-H",
"-WING-RKSJ-H",
"-90pv-RKSJ-H",
NULL
};
for (count = 0, i = 0; i < len; i++) {
if (fontname[i] == 0) {
memmove(fontname + i, fontname + i + 1, len - i);
count++;
len--;
}
}
if (count > 0) {
WARN("Removed %d null character(s) from fontname --> %s",
count, fontname);
}
fontname[len] = '\0';
for (i = 0; badstrlist[i] != NULL; i++) {
p = strstr(fontname, badstrlist[i]);
if (p && p > fontname) {
WARN("Removed string \"%s\" from fontname \"%s\".",
badstrlist[i], fontname);
p[0] = '\0';
len = (int) (p - fontname);
break;
}
}
if (len < 1) {
ERROR("No valid character found in fontname string.");
}
}
#define WIN_UCS_INDEX_MAX 1
#define KNOWN_ENCODINGS_MAX 9
static struct
{
unsigned short platform;
unsigned short encoding;
const char *pdfnames[5];
} known_encodings[] = {
{TT_WIN, TT_WIN_UCS4, {"UCSms-UCS4", "UCSms-UCS2", "UCS4", "UCS2", NULL}},
{TT_WIN, TT_WIN_UNICODE, {"UCSms-UCS4", "UCSms-UCS2", "UCS4", "UCS2", NULL}},
{TT_WIN, TT_WIN_SJIS, {"90ms-RKSJ", NULL}},
{TT_WIN, TT_WIN_RPC, {"GBK-EUC", NULL}},
{TT_WIN, TT_WIN_BIG5, {"ETen-B5", NULL}},
{TT_WIN, TT_WIN_WANSUNG, {"KSCms-UHC", NULL}},
{TT_MAC, TT_MAC_JAPANESE, {"90pv-RKSJ", NULL}},
{TT_MAC, TT_MAC_TRADITIONAL_CHINESE, {"B5pc", NULL}},
{TT_MAC, TT_MAC_SIMPLIFIED_CHINESE, {"GBpc-EUC", NULL}},
{TT_MAC, TT_MAC_KOREAN, {"KSCpc-EUC", NULL}},
{0, 0, {NULL}}
};
static CMap *
find_tocode_cmap (const char *reg, const char *ord, int select)
{
int cmap_id = -1, i;
char *cmap_name;
const char *append;
if (!reg || !ord ||
select < 0 || select > KNOWN_ENCODINGS_MAX)
ERROR("Character set unknown.");
if (!strcmp(ord, "UCS") &&
select <= WIN_UCS_INDEX_MAX)
return NULL;
for (i = 0; cmap_id < 0 && i < 5; i++) {
append = known_encodings[select].pdfnames[i];
if (!append)
break;
cmap_name = NEW(strlen(reg) + strlen(ord) + strlen(append) + 3, char);
sprintf(cmap_name, "%s-%s-%s", reg, ord, append);
cmap_id = texpdf_CMap_cache_find(cmap_name);
RELEASE(cmap_name);
}
if (cmap_id < 0) {
WARN("Could not find CID-to-Code mapping for \"%s-%s\".", reg, ord);
WARN("I tried to load (one of) the following file(s):");
for (i = 0; i < 5; i++) {
append = known_encodings[select].pdfnames[i];
if (!append)
break;
MESG(" %s-%s-%s", reg, ord, append);
}
WARN("Please check if this file exists.");
ERROR("Cannot continue...");
}
return texpdf_CMap_cache_get(cmap_id);
}
#define PDFUNIT(v) ((double) (ROUND(1000.0*(v)/(g->emsize), 1)))
static void
add_TTCIDHMetrics (pdf_obj *fontdict, struct tt_glyphs *g,
char *used_chars, unsigned char *cidtogidmap, unsigned short last_cid)
{
long cid, start = 0, prev = 0;
pdf_obj *w_array, *an_array = NULL;
double dw;
int empty = 1;
w_array = texpdf_new_array();
if (g->dw != 0 && g->dw <= g->emsize) {
dw = PDFUNIT(g->dw);
} else {
dw = PDFUNIT(g->gd[0].advw);
}
for (cid = 0; cid <= last_cid; cid++) {
USHORT idx, gid;
double width;
if (!is_used_char2(used_chars, cid))
continue;
gid = (cidtogidmap) ? ((cidtogidmap[2*cid] << 8)|cidtogidmap[2*cid+1]) : cid;
idx = tt_get_index(g, gid);
if (cid != 0 && idx == 0)
continue;
width = PDFUNIT((g->gd)[idx].advw);
if (width == dw) {
if (an_array) {
texpdf_add_array(w_array, texpdf_new_number(start));
texpdf_add_array(w_array, an_array);
an_array = NULL;
empty = 0;
}
} else {
if (cid != prev + 1) {
if (an_array) {
texpdf_add_array(w_array, texpdf_new_number(start));
texpdf_add_array(w_array, an_array);
an_array = NULL;
empty = 0;
}
}
if (an_array == NULL) {
an_array = texpdf_new_array();
start = cid;
}
texpdf_add_array(an_array, texpdf_new_number(width));
prev = cid;
}
}
if (an_array) {
texpdf_add_array(w_array, texpdf_new_number(start));
texpdf_add_array(w_array, an_array);
empty = 0;
}
texpdf_add_dict(fontdict,
texpdf_new_name("DW"),
texpdf_new_number(dw));
if (!empty) {
texpdf_add_dict(fontdict,
texpdf_new_name("W"),
texpdf_ref_obj(w_array));
}
texpdf_release_obj(w_array);
return;
}
static void
add_TTCIDVMetrics (pdf_obj *fontdict, struct tt_glyphs *g,
char *used_chars, unsigned short last_cid)
{
pdf_obj *w2_array, *an_array = NULL;
long cid;
#if 0#endif
double defaultVertOriginY, defaultAdvanceHeight;
int empty = 1;
defaultVertOriginY = PDFUNIT(g->default_advh - g->default_tsb);
defaultAdvanceHeight = PDFUNIT(g->default_advh);
w2_array = texpdf_new_array();
for (cid = 0; cid <= last_cid; cid++) {
USHORT idx;
#if 0#endif
double vertOriginX, vertOriginY, advanceHeight;
if (!is_used_char2(used_chars, cid))
continue;
#if 0#endif
idx = tt_get_index(g, (USHORT)cid);
if (cid != 0 && idx == 0)
continue;
advanceHeight = PDFUNIT(g->gd[idx].advh);
vertOriginX = PDFUNIT(0.5*(g->gd[idx].advw));
vertOriginY = PDFUNIT(g->gd[idx].tsb + g->gd[idx].ury);
#if 0#else
if (vertOriginY != defaultVertOriginY ||
advanceHeight != defaultAdvanceHeight) {
texpdf_add_array(w2_array, texpdf_new_number(cid));
texpdf_add_array(w2_array, texpdf_new_number(cid));
texpdf_add_array(w2_array, texpdf_new_number(-advanceHeight));
texpdf_add_array(w2_array, texpdf_new_number(vertOriginX));
texpdf_add_array(w2_array, texpdf_new_number(vertOriginY));
empty = 0;
}
#endif
}
#if 0#endif
if (defaultVertOriginY != 880 || defaultAdvanceHeight != 1000) {
an_array = texpdf_new_array();
texpdf_add_array(an_array, texpdf_new_number(defaultVertOriginY));
texpdf_add_array(an_array, texpdf_new_number(-defaultAdvanceHeight));
texpdf_add_dict(fontdict, texpdf_new_name ("DW2"), an_array);
}
if (!empty) {
texpdf_add_dict(fontdict,
texpdf_new_name("W2"),
texpdf_ref_obj(w2_array));
}
texpdf_release_obj(w2_array);
return;
}
#define FIX_CJK_UNIOCDE_SYMBOLS 1
static unsigned short
fix_CJK_symbols (unsigned short code)
{
unsigned short alt_code;
static struct
{
unsigned short alt1;
unsigned short alt2;
} CJK_Uni_symbols[] = {
{0x2014, 0x2015},
{0x2016, 0x2225},
{0x203E, 0xFFE3},
{0x2026, 0x22EF},
{0x2212, 0xFF0D},
{0x301C, 0xFF5E},
{0xFFE0, 0x00A2},
{0xFFE1, 0x00A3},
{0xFFE2, 0x00AC},
{0xFFFF, 0xFFFF},
};
#define NUM_CJK_SYMBOLS (sizeof(CJK_Uni_symbols)/sizeof(CJK_Uni_symbols[0]))
int i;
alt_code = code;
for (i = 0; i < NUM_CJK_SYMBOLS; i++) {
if (CJK_Uni_symbols[i].alt1 == code) {
alt_code = CJK_Uni_symbols[i].alt2;
break;
} else if (CJK_Uni_symbols[i].alt2 == code) {
alt_code = CJK_Uni_symbols[i].alt1;
break;
}
}
return alt_code;
}
static long
cid_to_code (CMap *cmap, CID cid)
{
unsigned char inbuf[2], outbuf[32];
long inbytesleft = 2, outbytesleft = 32;
const unsigned char *p;
unsigned char *q;
if (!cmap)
return cid;
inbuf[0] = (cid >> 8) & 0xff;
inbuf[1] = cid & 0xff;
p = inbuf; q = outbuf;
CMap_decode_char(cmap, &p, &inbytesleft, &q, &outbytesleft);
if (inbytesleft != 0)
return 0;
else if (outbytesleft == 31)
return (long) outbuf[0];
else if (outbytesleft == 30)
return (long) (outbuf[0] << 8|outbuf[1]);
else if (outbytesleft == 28) {
CID hi, lo;
hi = outbuf[0] << 8|outbuf[1];
lo = outbuf[2] << 8|outbuf[3];
if (hi >= 0xd800 && hi <= 0xdbff && lo >= 0xdc00 && lo <= 0xdfff)
return (long) ((hi - 0xd800) * 0x400 + 0x10000 + lo - 0xdc00);
else
return (long) (hi << 16|lo);
}
return 0;
}
void
CIDFont_type2_dofont (CIDFont *font)
{
pdf_obj *fontfile;
sfnt *sfont;
char *h_used_chars, *v_used_chars, *used_chars;
struct tt_glyphs *glyphs;
CMap *cmap = NULL;
tt_cmap *ttcmap = NULL;
unsigned long offset = 0;
CID cid, last_cid;
unsigned char *cidtogidmap;
USHORT num_glyphs;
int i, glyph_ordering = 0, unicode_cmap = 0;
FILE *fp = NULL;
if (!font->indirect)
return;
texpdf_add_dict(font->fontdict,
texpdf_new_name("FontDescriptor"), texpdf_ref_obj(font->descriptor));
if (CIDFont_is_BaseFont(font))
return;
{
pdf_obj *tmp;
tmp = texpdf_new_dict ();
texpdf_add_dict(tmp,
texpdf_new_name("Registry"),
texpdf_new_string(font->csi->registry, strlen(font->csi->registry)));
texpdf_add_dict(tmp,
texpdf_new_name("Ordering"),
texpdf_new_string(font->csi->ordering, strlen(font->csi->ordering)));
texpdf_add_dict(tmp,
texpdf_new_name("Supplement"),
texpdf_new_number(font->csi->supplement));
texpdf_add_dict(font->fontdict, texpdf_new_name("CIDSystemInfo"), tmp);
}
if (!CIDFont_get_embedding(font) &&
(opt_flags & CIDFONT_FORCE_FIXEDPITCH)) {
texpdf_add_dict(font->fontdict,
texpdf_new_name("DW"), texpdf_new_number(1000.0));
return;
}
fp = DPXFOPEN(font->ident, DPX_RES_TYPE_TTFONT);
if (!fp) {
fp = DPXFOPEN(font->ident, DPX_RES_TYPE_DFONT);
if (!fp) ERROR("Could not open TTF/dfont file: %s", font->ident);
sfont = dfont_open(fp, font->options->index);
} else {
sfont = sfnt_open(fp);
}
if (!sfont) {
ERROR("Could not open TTF file: %s", font->ident);
}
switch (sfont->type) {
case SFNT_TYPE_TTC:
offset = ttc_read_offset(sfont, font->options->index);
if (offset == 0)
ERROR("Invalid TTC index in %s.", font->ident);
break;
case SFNT_TYPE_TRUETYPE:
if (font->options->index > 0)
ERROR("Found TrueType font file while expecting TTC file (%s).", font->ident);
offset = 0;
break;
case SFNT_TYPE_DFONT:
offset = sfont->offset;
break;
default:
ERROR("Not a TrueType/TTC font (%s)?", font->ident);
break;
}
if (sfnt_read_table_directory(sfont, offset) < 0)
ERROR("Could not read TrueType table directory (%s).", font->ident);
if (!strcmp(font->csi->registry, "Adobe") &&
!strcmp(font->csi->ordering, "Identity")) {
glyph_ordering = 1;
} else {
glyph_ordering = 0;
}
if (glyph_ordering) {
ttcmap = NULL;
cmap = NULL;
} else {
for (i = 0; i <= KNOWN_ENCODINGS_MAX; i++) {
ttcmap = tt_cmap_read(sfont,
known_encodings[i].platform,
known_encodings[i].encoding);
if (ttcmap)
break;
}
if (!ttcmap) {
WARN("No usable TrueType cmap table found for font \"%s\".", font->ident);
WARN("CID character collection for this font is set to \"%s-%s\"",
font->csi->registry, font->csi->ordering);
ERROR("Cannot continue without this...");
} else if (i <= WIN_UCS_INDEX_MAX) {
unicode_cmap = 1;
} else {
unicode_cmap = 0;
}
cmap = find_tocode_cmap(font->csi->registry,
font->csi->ordering, i);
}
glyphs = tt_build_init();
last_cid = 0;
num_glyphs = 1;
used_chars = h_used_chars = v_used_chars = NULL;
{
Type0Font *parent;
int parent_id, c;
if ((parent_id = CIDFont_get_parent_id(font, 0)) >= 0) {
parent = Type0Font_cache_get(parent_id);
h_used_chars = Type0Font_get_usedchars(parent);
}
if ((parent_id = CIDFont_get_parent_id(font, 1)) >= 0) {
parent = Type0Font_cache_get(parent_id);
v_used_chars = Type0Font_get_usedchars(parent);
}
if (!h_used_chars && !v_used_chars)
ERROR("Unexpected error.");
c = 0;
for (i = 8191; i >= 0; i--) {
if (h_used_chars && h_used_chars[i] != 0) {
last_cid = i * 8 + 7;
c = h_used_chars[i];
break;
}
if (v_used_chars && v_used_chars[i] != 0) {
last_cid = i * 8 + 7;
c = v_used_chars[i];
break;
}
}
if (last_cid > 0) {
for (i = 0; i < 8; i++) {
if ((c >> i) & 1)
break;
last_cid--;
}
}
if (last_cid >= 0xFFFFu) {
ERROR("CID count > 65535");
}
}
#ifndef NO_GHOSTSCRIPT_BUG
cidtogidmap = NULL;
#else
cidtogidmap = NEW((last_cid + 1) * 2, unsigned char);
memset(cidtogidmap, 0, (last_cid + 1) * 2);
#endif
if (h_used_chars) {
used_chars = h_used_chars;
for (cid = 1; cid <= last_cid; cid++) {
long code;
unsigned short gid;
if (!is_used_char2(h_used_chars, cid))
continue;
if (glyph_ordering) {
gid = cid;
code = cid;
} else {
code = cid_to_code(cmap, cid);
gid = tt_cmap_lookup(ttcmap, code);
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
if (gid == 0 && unicode_cmap) {
long alt_code;
alt_code = fix_CJK_symbols((unsigned short)code);
if (alt_code != code) {
gid = tt_cmap_lookup(ttcmap, alt_code);
if (gid != 0) {
WARN("Unicode char U+%04x replaced with U+%04x.",
code, alt_code);
}
}
}
#endif
}
if (gid == 0) {
WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
}
#ifndef NO_GHOSTSCRIPT_BUG
gid = tt_add_glyph(glyphs, gid, cid);
#else
gid = tt_add_glyph(glyphs, gid, num_glyphs);
cidtogidmap[2*cid ] = gid >> 8;
cidtogidmap[2*cid+1] = gid & 0xff;
#endif
num_glyphs++;
}
}
if (v_used_chars) {
otl_gsub *gsub_list = NULL;
if (glyph_ordering) {
gsub_list = NULL;
} else {
gsub_list = otl_gsub_new();
if (otl_gsub_add_feat(gsub_list,
"*", "*", "vrt2", sfont) < 0) {
if (otl_gsub_add_feat(gsub_list,
"*", "*", "vert", sfont) < 0) {
WARN("GSUB feature vrt2/vert not found.");
otl_gsub_release(gsub_list);
gsub_list = NULL;
} else {
otl_gsub_select(gsub_list, "*", "*", "vert");
}
} else {
otl_gsub_select(gsub_list, "*", "*", "vrt2");
}
}
for (cid = 1; cid <= last_cid; cid++) {
long code;
unsigned short gid;
if (!is_used_char2(v_used_chars, cid))
continue;
if (h_used_chars && is_used_char2(h_used_chars, cid)) {
continue;
}
if (glyph_ordering) {
gid = cid;
code = cid;
} else {
code = cid_to_code(cmap, cid);
gid = tt_cmap_lookup(ttcmap, code);
#ifdef FIX_CJK_UNIOCDE_SYMBOLS
if (gid == 0 && unicode_cmap) {
long alt_code;
alt_code = fix_CJK_symbols((unsigned short)code);
if (alt_code != code) {
gid = tt_cmap_lookup(ttcmap, alt_code);
if (gid != 0) {
WARN("Unicode char U+%04x replaced with U+%04x.",
code, alt_code);
}
}
}
#endif
}
if (gid == 0) {
WARN("Glyph missing in font. (CID=%u, code=0x%04x)", cid, code);
} else if (gsub_list) {
otl_gsub_apply(gsub_list, &gid);
}
#ifndef NO_GHOSTSCRIPT_BUG
gid = tt_add_glyph(glyphs, gid, cid);
#else
gid = tt_add_glyph(glyphs, gid, num_glyphs);
cidtogidmap[2*cid ] = gid >> 8;
cidtogidmap[2*cid+1] = gid & 0xff;
#endif
if (used_chars)
add_to_used_chars2(used_chars, cid);
num_glyphs++;
}
if (gsub_list)
otl_gsub_release(gsub_list);
if (!used_chars)
used_chars = v_used_chars;
}
if (!used_chars)
ERROR("Unexpected error.");
tt_cmap_release(ttcmap);
if (CIDFont_get_embedding(font)) {
if (tt_build_tables(sfont, glyphs) < 0)
ERROR("Could not created FontFile stream.");
if (verbose > 1)
MESG("[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid);
} else {
if (tt_get_metrics(sfont, glyphs) < 0)
ERROR("Reading glyph metrics failed...");
}
if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
texpdf_add_dict(font->fontdict,
texpdf_new_name("DW"), texpdf_new_number(1000.0));
} else {
add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
if (v_used_chars)
add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, last_cid);
}
tt_build_finish(glyphs);
if (!CIDFont_get_embedding(font)) {
if (cidtogidmap)
RELEASE(cidtogidmap);
sfnt_close(sfont);
if (fp)
DPXFCLOSE(fp);
return;
}
for (i = 0; required_table[i].name; i++) {
if (sfnt_require_table(sfont,
required_table[i].name,
required_table[i].must_exist) < 0) {
ERROR("Some required TrueType table (%s) does not exist.", required_table[i].name);
}
}
fontfile = sfnt_create_FontFile_stream(sfont);
sfnt_close(sfont);
if (fp)
DPXFCLOSE(fp);
if (!fontfile)
ERROR("Could not created FontFile stream for \"%s\".", font->ident);
if (verbose > 1) {
MESG("[%ld bytes]", pdf_stream_length(fontfile));
}
texpdf_add_dict(font->descriptor,
texpdf_new_name("FontFile2"),
texpdf_ref_obj (fontfile));
texpdf_release_obj(fontfile);
{
pdf_obj *cidset;
cidset = texpdf_new_stream(STREAM_COMPRESS);
texpdf_add_stream(cidset, used_chars, last_cid/8 + 1);
texpdf_add_dict(font->descriptor,
texpdf_new_name("CIDSet"),
texpdf_ref_obj(cidset));
texpdf_release_obj(cidset);
}
if (cidtogidmap) {
pdf_obj *c2gmstream;
c2gmstream = texpdf_new_stream(STREAM_COMPRESS);
texpdf_add_stream(c2gmstream, cidtogidmap, (last_cid + 1) * 2);
texpdf_add_dict(font->fontdict,
texpdf_new_name("CIDToGIDMap"),
texpdf_ref_obj (c2gmstream));
texpdf_release_obj(c2gmstream);
RELEASE(cidtogidmap);
}
return;
}
int
CIDFont_type2_open (CIDFont *font, const char *name,
CIDSysInfo *cmap_csi, cid_opt *opt)
{
char *fontname;
sfnt *sfont;
unsigned long offset = 0;
FILE *fp = NULL;
ASSERT(font && opt);
fp = DPXFOPEN(name, DPX_RES_TYPE_TTFONT);
if (!fp) {
fp = DPXFOPEN(name, DPX_RES_TYPE_DFONT);
if (!fp) return -1;
sfont = dfont_open(fp, opt->index);
} else {
sfont = sfnt_open(fp);
}
if (!sfont) {
DPXFCLOSE(fp);
return -1;
}
switch (sfont->type) {
case SFNT_TYPE_TTC:
offset = ttc_read_offset(sfont, opt->index);
break;
case SFNT_TYPE_TRUETYPE:
if (opt->index > 0)
ERROR("Invalid TTC index (not TTC font): %s", name);
offset = 0;
break;
case SFNT_TYPE_DFONT:
offset = sfont->offset;
break;
default:
sfnt_close(sfont);
if (fp)
DPXFCLOSE(fp);
return -1;
}
if (sfnt_read_table_directory(sfont, offset) < 0) {
ERROR("Reading TrueType table directory failed.");
}
if (sfont->type == SFNT_TYPE_TTC && sfnt_find_table_pos(sfont, "CFF ")) {
sfnt_close(sfont);
if (fp)
DPXFCLOSE(fp);
return -1;
}
{
char *shortname;
long namelen;
shortname = NEW(PDF_NAME_LEN_MAX, char);
namelen = tt_get_ps_fontname(sfont, shortname, PDF_NAME_LEN_MAX);
if (namelen == 0) {
memset(shortname, 0, PDF_NAME_LEN_MAX);
strncpy(shortname, name, PDF_NAME_LEN_MAX);
namelen = strlen(shortname);
}
validate_name(shortname, namelen);
fontname = NEW(strlen(shortname)+19, char);
strcpy(fontname, shortname);
RELEASE(shortname);
}
if (opt->embed && opt->style != FONT_STYLE_NONE) {
WARN("Embedding disabled due to style option for %s.", name);
opt->embed = 0;
}
switch (opt->style) {
case FONT_STYLE_BOLD:
strcat(fontname, ",Bold");
break;
case FONT_STYLE_ITALIC:
strcat(fontname, ",Italic");
break;
case FONT_STYLE_BOLDITALIC:
strcat(fontname, ",BoldItalic");
break;
}
font->fontname = fontname;
font->subtype = CIDFONT_TYPE2;
font->csi = NEW(1, CIDSysInfo);
if (opt->csi) {
if (cmap_csi) {
if (strcmp(opt->csi->registry, cmap_csi->registry) ||
strcmp(opt->csi->ordering, cmap_csi->ordering)) {
WARN("CID character collection mismatched:\n");
MESG("\tFont: %s-%s-%d\n",
opt->csi->registry, opt->csi->ordering, opt->csi->supplement);
MESG("\tCMap: %s-%s-%d\n",
cmap_csi->registry, cmap_csi->ordering, cmap_csi->supplement);
ERROR("Incompatible CMap specified for this font.");
}
if (opt->csi->supplement < cmap_csi->supplement) {
WARN("Supplmement value in CIDSystemInfo increased.");
WARN("Some characters may not shown.");
opt->csi->supplement = cmap_csi->supplement;
}
}
font->csi->registry = NEW(strlen(opt->csi->registry)+1, char);
strcpy(font->csi->registry, opt->csi->registry);
font->csi->ordering = NEW(strlen(opt->csi->ordering)+1, char);
strcpy(font->csi->ordering, opt->csi->ordering);
font->csi->supplement = opt->csi->supplement;
} else if (cmap_csi) {
font->csi->registry = NEW(strlen(cmap_csi->registry)+1, char);
strcpy(font->csi->registry, cmap_csi->registry);
font->csi->ordering = NEW(strlen(cmap_csi->ordering)+1, char);
strcpy(font->csi->ordering, cmap_csi->ordering);
font->csi->supplement = cmap_csi->supplement;
} else {
font->csi->registry = NEW(strlen("Adobe")+1, char);
strcpy(font->csi->registry, "Adobe");
font->csi->ordering = NEW(strlen("Identity")+1, char);
strcpy(font->csi->ordering, "Identity");
font->csi->supplement = 0;
}
font->fontdict = texpdf_new_dict();
texpdf_add_dict(font->fontdict,
texpdf_new_name("Type"),
texpdf_new_name("Font"));
texpdf_add_dict(font->fontdict,
texpdf_new_name("Subtype"),
texpdf_new_name("CIDFontType2"));
font->descriptor = tt_get_fontdesc(sfont, &(opt->embed), opt->stemv, 0, name);
if (!font->descriptor) {
ERROR("Could not obtain necessary font info.");
}
if (opt->embed) {
memmove(fontname + 7, fontname, strlen(fontname) + 1);
pdf_font_make_uniqueTag(fontname);
fontname[6] = '+';
}
texpdf_add_dict(font->descriptor,
texpdf_new_name("FontName"),
texpdf_new_name(fontname));
texpdf_add_dict(font->fontdict,
texpdf_new_name("BaseFont"),
texpdf_new_name(fontname));
sfnt_close(sfont);
if (fp)
DPXFCLOSE(fp);
return 0;
}