mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-02-24 05:37:14 +01:00
2276 lines
66 KiB
C
2276 lines
66 KiB
C
|
/*
|
||
|
* << Haru Free PDF Library >> -- hpdf_fontdef_tt.c
|
||
|
*
|
||
|
* URL: http://libharu.org
|
||
|
*
|
||
|
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||
|
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||
|
*
|
||
|
* Permission to use, copy, modify, distribute and sell this software
|
||
|
* and its documentation for any purpose is hereby granted without fee,
|
||
|
* provided that the above copyright notice appear in all copies and
|
||
|
* that both that copyright notice and this permission notice appear
|
||
|
* in supporting documentation.
|
||
|
* It is provided "as is" without express or implied warranty.
|
||
|
*
|
||
|
* 2006.08.24 fixed for composite glyph description.
|
||
|
*/
|
||
|
|
||
|
#include "hpdf_conf.h"
|
||
|
#include "hpdf_utils.h"
|
||
|
#include "hpdf_fontdef.h"
|
||
|
|
||
|
|
||
|
#define HPDF_TTF_MAX_MEM_SIZ 10000
|
||
|
|
||
|
#define HPDF_REQUIRED_TAGS_COUNT 13
|
||
|
|
||
|
static const char * const REQUIRED_TAGS[HPDF_REQUIRED_TAGS_COUNT] = {
|
||
|
"OS/2",
|
||
|
"cmap",
|
||
|
"cvt ",
|
||
|
"fpgm",
|
||
|
"glyf",
|
||
|
"head",
|
||
|
"hhea",
|
||
|
"hmtx",
|
||
|
"loca",
|
||
|
"maxp",
|
||
|
"name",
|
||
|
"post",
|
||
|
"prep"
|
||
|
};
|
||
|
|
||
|
|
||
|
static void
|
||
|
FreeFunc (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadFontData (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_BOOL embedding,
|
||
|
HPDF_UINT offset);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadFontData2 (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_UINT index,
|
||
|
HPDF_BOOL embedding);
|
||
|
|
||
|
|
||
|
static void
|
||
|
InitAttr (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetUINT32 (HPDF_Stream stream,
|
||
|
HPDF_UINT32 *value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetUINT16 (HPDF_Stream stream,
|
||
|
HPDF_UINT16 *value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetINT16 (HPDF_Stream stream,
|
||
|
HPDF_INT16 *value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteUINT32 (HPDF_Stream stream,
|
||
|
HPDF_UINT32 value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteUINT16 (HPDF_Stream stream,
|
||
|
HPDF_UINT16 value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteINT16 (HPDF_Stream stream,
|
||
|
HPDF_INT16 value);
|
||
|
|
||
|
|
||
|
static void
|
||
|
UINT32Swap (HPDF_UINT32 *value);
|
||
|
|
||
|
|
||
|
static void
|
||
|
UINT16Swap (HPDF_UINT16 *value);
|
||
|
|
||
|
|
||
|
static void
|
||
|
INT16Swap (HPDF_INT16 *value);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadTTFTable (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHead (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseMaxp (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHhea (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMap (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMAP_format0 (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT32 offset);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMAP_format4 (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT32 offset);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHmtx (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseLoca (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadUnicodeName (HPDF_Stream stream,
|
||
|
HPDF_UINT offset,
|
||
|
HPDF_UINT len,
|
||
|
char *buf);
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseName (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseOS2 (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_TTFTable*
|
||
|
FindTable (HPDF_FontDef fontdef,
|
||
|
const char *tag);
|
||
|
|
||
|
|
||
|
static void
|
||
|
CleanFunc (HPDF_FontDef fontdef);
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
CheckCompositGryph (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 gid);
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
/*---------------------------------------------------------------------------*/
|
||
|
|
||
|
static void
|
||
|
FreeFunc (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_FreeFunc\n"));
|
||
|
|
||
|
if (attr) {
|
||
|
InitAttr (fontdef);
|
||
|
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
CleanFunc (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_MemSet (attr->glyph_tbl.flgs, 0,
|
||
|
sizeof (HPDF_BYTE) * attr->num_glyphs);
|
||
|
attr->glyph_tbl.flgs[0] = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
InitAttr (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
|
||
|
if (attr) {
|
||
|
if (attr->char_set)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->char_set);
|
||
|
|
||
|
if (attr->h_metric)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->h_metric);
|
||
|
|
||
|
if (attr->name_tbl.name_records)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->name_tbl.name_records);
|
||
|
|
||
|
if (attr->cmap.end_count)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->cmap.end_count);
|
||
|
|
||
|
if (attr->cmap.start_count)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->cmap.start_count);
|
||
|
|
||
|
if (attr->cmap.id_delta)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->cmap.id_delta);
|
||
|
|
||
|
if (attr->cmap.id_range_offset)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->cmap.id_range_offset);
|
||
|
|
||
|
if (attr->cmap.glyph_id_array)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->cmap.glyph_id_array);
|
||
|
|
||
|
if (attr->offset_tbl.table)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->offset_tbl.table);
|
||
|
|
||
|
if (attr->glyph_tbl.flgs)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->glyph_tbl.flgs);
|
||
|
|
||
|
if (attr->glyph_tbl.offsets)
|
||
|
HPDF_FreeMem (fontdef->mmgr, attr->glyph_tbl.offsets);
|
||
|
|
||
|
if (attr->stream)
|
||
|
HPDF_Stream_Free (attr->stream);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_FontDef
|
||
|
HPDF_TTFontDef_New (HPDF_MMgr mmgr)
|
||
|
{
|
||
|
HPDF_FontDef fontdef;
|
||
|
HPDF_TTFontDefAttr fontdef_attr;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_New\n"));
|
||
|
|
||
|
if (!mmgr)
|
||
|
return NULL;
|
||
|
|
||
|
fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
|
||
|
if (!fontdef)
|
||
|
return NULL;
|
||
|
|
||
|
HPDF_MemSet (fontdef, 0, sizeof(HPDF_FontDef_Rec));
|
||
|
fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
|
||
|
fontdef->mmgr = mmgr;
|
||
|
fontdef->error = mmgr->error;
|
||
|
fontdef->type = HPDF_FONTDEF_TYPE_TRUETYPE;
|
||
|
fontdef->clean_fn = CleanFunc;
|
||
|
fontdef->free_fn = FreeFunc;
|
||
|
|
||
|
fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_TTFontDefAttr_Rec));
|
||
|
if (!fontdef_attr) {
|
||
|
HPDF_FreeMem (fontdef->mmgr, fontdef);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
fontdef->attr = fontdef_attr;
|
||
|
HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0, sizeof(HPDF_TTFontDefAttr_Rec));
|
||
|
fontdef->flags = HPDF_FONT_STD_CHARSET;
|
||
|
|
||
|
return fontdef;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_FontDef
|
||
|
HPDF_TTFontDef_Load (HPDF_MMgr mmgr,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_BOOL embedding)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_FontDef fontdef;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_Load\n"));
|
||
|
|
||
|
fontdef = HPDF_TTFontDef_New (mmgr);
|
||
|
|
||
|
if (!fontdef) {
|
||
|
HPDF_Stream_Free (stream);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ret = LoadFontData (fontdef, stream, embedding, 0);
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_FontDef_Free (fontdef);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return fontdef;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_FontDef
|
||
|
HPDF_TTFontDef_Load2 (HPDF_MMgr mmgr,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_UINT index,
|
||
|
HPDF_BOOL embedding)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_FontDef fontdef;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_Load\n"));
|
||
|
|
||
|
fontdef = HPDF_TTFontDef_New (mmgr);
|
||
|
|
||
|
if (!fontdef) {
|
||
|
HPDF_Stream_Free (stream);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
ret = LoadFontData2 (fontdef, stream, index, embedding);
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_FontDef_Free (fontdef);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return fontdef;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef HPDF_TTF_DEBUG
|
||
|
static void
|
||
|
DumpTable (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_Stream stream;
|
||
|
HPDF_UINT i;
|
||
|
|
||
|
for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
|
||
|
char fname[9];
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, REQUIRED_TAGS[i]);
|
||
|
|
||
|
if (!tbl) {
|
||
|
HPDF_PTRACE ((" ERR: cannot seek %s\n", fname));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
HPDF_MemSet (fname, 0, 9);
|
||
|
HPDF_MemCpy (fname, REQUIRED_TAGS[i], 4);
|
||
|
HPDF_MemCpy (fname + 4, ".dat", 4);
|
||
|
HPDF_PTRACE ((" %s open\n", fname));
|
||
|
|
||
|
if (HPDF_MemCmp(fname, "OS/2", 4) == 0)
|
||
|
fname[2] = '_';
|
||
|
|
||
|
stream = HPDF_FileWriter_New (fontdef->mmgr, fname);
|
||
|
|
||
|
if (!stream) {
|
||
|
HPDF_PTRACE ((" ERR: cannot open %s\n", fname));
|
||
|
} else {
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT tbl_len = tbl->length;
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_PTRACE ((" ERR: cannot seek \n"));
|
||
|
HPDF_Stream_Free (stream);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (;;) {
|
||
|
HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
|
||
|
HPDF_UINT len = HPDF_STREAM_BUF_SIZ;
|
||
|
|
||
|
if (len > tbl_len)
|
||
|
len = tbl_len;
|
||
|
|
||
|
HPDF_Stream_Read (attr->stream, buf, &len);
|
||
|
if (len <= 0)
|
||
|
break;
|
||
|
|
||
|
ret = HPDF_Stream_Write (stream, buf, len);
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_PTRACE ((" ERR: cannot write\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
tbl_len -= len;
|
||
|
if (tbl_len == 0)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
HPDF_Stream_Free (stream);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadFontData (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_BOOL embedding,
|
||
|
HPDF_UINT offset)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_TTFTable *tbl;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_LoadFontData\n"));
|
||
|
|
||
|
attr->stream = stream;
|
||
|
attr->embedding = embedding;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (stream, offset, HPDF_SEEK_SET)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = LoadTTFTable (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
#ifdef HPDF_DUMP_FONTDATA
|
||
|
DumpTable (fontdef);
|
||
|
#endif /* HPDF_DUMP_FONTDATA */
|
||
|
|
||
|
if ((ret = ParseHead (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseMaxp (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseHhea (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseCMap (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseHmtx (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseLoca (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseName (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = ParseOS2 (fontdef)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
tbl = FindTable (fontdef, "glyf");
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 4);
|
||
|
|
||
|
attr->glyph_tbl.base_offset = tbl->offset;
|
||
|
fontdef->cap_height =
|
||
|
(HPDF_UINT16)HPDF_TTFontDef_GetCharBBox (fontdef, (HPDF_UINT16)'H').top;
|
||
|
fontdef->x_height =
|
||
|
(HPDF_UINT16)HPDF_TTFontDef_GetCharBBox (fontdef, (HPDF_UINT16)'x').top;
|
||
|
fontdef->missing_width = (HPDF_INT16)((HPDF_UINT32)attr->h_metric[0].advance_width * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
|
||
|
HPDF_PTRACE ((" fontdef->cap_height=%d\n", fontdef->cap_height));
|
||
|
HPDF_PTRACE ((" fontdef->x_height=%d\n", fontdef->x_height));
|
||
|
HPDF_PTRACE ((" fontdef->missing_width=%d\n", fontdef->missing_width));
|
||
|
|
||
|
if (!embedding) {
|
||
|
HPDF_Stream_Free (attr->stream);
|
||
|
attr->stream = NULL;
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadFontData2 (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_UINT index,
|
||
|
HPDF_BOOL embedding)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_BYTE tag[4];
|
||
|
HPDF_UINT32 num_fonts;
|
||
|
HPDF_UINT32 offset;
|
||
|
HPDF_UINT size;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_LoadFontData2\n"));
|
||
|
|
||
|
attr->stream = stream;
|
||
|
attr->embedding = embedding;
|
||
|
|
||
|
ret = HPDF_Stream_Seek (stream, 0, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
size = 4;
|
||
|
if ((ret = HPDF_Stream_Read (stream, tag, &size)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if (HPDF_MemCmp (tag, (HPDF_BYTE *)"ttcf", 4) != 0)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_INVALID_TTC_FILE, 0);
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (stream, 8, HPDF_SEEK_SET)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT32 (stream, &num_fonts)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_LoadFontData2 num_fonts=%u\n",
|
||
|
(HPDF_UINT)num_fonts));
|
||
|
|
||
|
if (index >= num_fonts)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_INVALID_TTC_INDEX, 0);
|
||
|
|
||
|
/* read offset table for target font and set stream positioning to offset
|
||
|
* value.
|
||
|
*/
|
||
|
if ((ret = HPDF_Stream_Seek (stream, 12 + index * 4, HPDF_SEEK_SET)) !=
|
||
|
HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT32 (stream, &offset)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
return LoadFontData (fontdef, stream, embedding, offset);
|
||
|
}
|
||
|
|
||
|
HPDF_Box
|
||
|
HPDF_TTFontDef_GetCharBBox (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 unicode)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid(fontdef, unicode);
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_Box bbox = HPDF_ToBox(0, 0, 0, 0);
|
||
|
HPDF_INT16 i;
|
||
|
HPDF_INT m;
|
||
|
|
||
|
if (gid == 0) {
|
||
|
HPDF_PTRACE ((" GetCharHeight cannot get gid char=0x%04x\n", unicode));
|
||
|
return bbox;
|
||
|
}
|
||
|
|
||
|
if (attr->header.index_to_loc_format == 0)
|
||
|
m = 2;
|
||
|
else
|
||
|
m = 1;
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, attr->glyph_tbl.base_offset +
|
||
|
attr->glyph_tbl.offsets[gid] * m + 2, HPDF_SEEK_SET);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return bbox;
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &i);
|
||
|
bbox.left = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &i);
|
||
|
bbox.bottom = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &i);
|
||
|
bbox.right = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &i);
|
||
|
bbox.top = (HPDF_REAL)((HPDF_INT32)i * 1000 / attr->header.units_per_em);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_ToBox(0, 0, 0, 0);
|
||
|
|
||
|
HPDF_PTRACE((" PdfTTFontDef_GetCharBBox char=0x%04X, "
|
||
|
"box=[%f,%f,%f,%f]\n", unicode, bbox.left, bbox.bottom, bbox.right,
|
||
|
bbox.top));
|
||
|
|
||
|
return bbox;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetUINT32 (HPDF_Stream stream,
|
||
|
HPDF_UINT32 *value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT size = sizeof (HPDF_UINT32);
|
||
|
|
||
|
ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
|
||
|
if (ret != HPDF_OK) {
|
||
|
*value = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
UINT32Swap (value);
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetUINT16 (HPDF_Stream stream,
|
||
|
HPDF_UINT16 *value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT size = sizeof (HPDF_UINT16);
|
||
|
|
||
|
ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
|
||
|
if (ret != HPDF_OK) {
|
||
|
*value = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
UINT16Swap (value);
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
GetINT16 (HPDF_Stream stream,
|
||
|
HPDF_INT16 *value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT size = sizeof (HPDF_INT16);
|
||
|
|
||
|
ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)value, &size);
|
||
|
if (ret != HPDF_OK) {
|
||
|
*value = 0;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
INT16Swap (value);
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteUINT32 (HPDF_Stream stream,
|
||
|
HPDF_UINT32 value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT32 tmp = value;
|
||
|
|
||
|
UINT32Swap (&tmp);
|
||
|
|
||
|
ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteUINT16 (HPDF_Stream stream,
|
||
|
HPDF_UINT16 value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT16 tmp = value;
|
||
|
|
||
|
UINT16Swap (&tmp);
|
||
|
|
||
|
ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteINT16 (HPDF_Stream stream,
|
||
|
HPDF_INT16 value)
|
||
|
{
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_INT16 tmp = value;
|
||
|
|
||
|
INT16Swap (&tmp);
|
||
|
|
||
|
ret = HPDF_Stream_Write (stream, (HPDF_BYTE *)&tmp, sizeof(tmp));
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_STATUS
|
||
|
LoadTTFTable (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret = HPDF_OK;
|
||
|
HPDF_INT i;
|
||
|
HPDF_TTFTable *tbl;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_LoadTTFTable\n"));
|
||
|
|
||
|
ret += GetUINT32 (attr->stream, &attr->offset_tbl.sfnt_version);
|
||
|
ret += GetUINT16 (attr->stream, &attr->offset_tbl.num_tables);
|
||
|
ret += GetUINT16 (attr->stream, &attr->offset_tbl.search_range);
|
||
|
ret += GetUINT16 (attr->stream, &attr->offset_tbl.entry_selector);
|
||
|
ret += GetUINT16 (attr->stream, &attr->offset_tbl.range_shift);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
if (attr->offset_tbl.num_tables * sizeof(HPDF_TTFTable) >
|
||
|
HPDF_TTF_MAX_MEM_SIZ)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
attr->offset_tbl.table = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_TTFTable) * attr->offset_tbl.num_tables);
|
||
|
if (!attr->offset_tbl.table)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
tbl = attr->offset_tbl.table;
|
||
|
for (i = 0; i < attr->offset_tbl.num_tables; i++) {
|
||
|
HPDF_UINT siz = 4;
|
||
|
|
||
|
ret += HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)tbl->tag, &siz);
|
||
|
ret += GetUINT32 (attr->stream, &tbl->check_sum);
|
||
|
ret += GetUINT32 (attr->stream, &tbl->offset);
|
||
|
ret += GetUINT32 (attr->stream, &tbl->length);
|
||
|
|
||
|
HPDF_PTRACE((" [%d] tag=[%c%c%c%c] check_sum=%u offset=%u length=%u\n",
|
||
|
i, tbl->tag[0], tbl->tag[1], tbl->tag[2], tbl->tag[3],
|
||
|
(HPDF_UINT)tbl->check_sum, (HPDF_UINT)tbl->offset,
|
||
|
(HPDF_UINT)tbl->length));
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);;
|
||
|
|
||
|
tbl++;
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHead (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "head");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT siz;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseHead\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 5);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
siz = 4;
|
||
|
ret += HPDF_Stream_Read (attr->stream,
|
||
|
(HPDF_BYTE *)&attr->header.version_number, &siz);
|
||
|
ret += GetUINT32 (attr->stream, &attr->header.font_revision);
|
||
|
ret += GetUINT32 (attr->stream, &attr->header.check_sum_adjustment);
|
||
|
ret += GetUINT32 (attr->stream, &attr->header.magic_number);
|
||
|
ret += GetUINT16 (attr->stream, &attr->header.flags);
|
||
|
ret += GetUINT16 (attr->stream, &attr->header.units_per_em);
|
||
|
|
||
|
siz = 8;
|
||
|
ret += HPDF_Stream_Read (attr->stream, attr->header.created, &siz);
|
||
|
siz = 8;
|
||
|
ret += HPDF_Stream_Read (attr->stream, attr->header.modified, &siz);
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &attr->header.x_min);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.y_min);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.x_max);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.y_max);
|
||
|
ret += GetUINT16 (attr->stream, &attr->header.mac_style);
|
||
|
ret += GetUINT16 (attr->stream, &attr->header.lowest_rec_ppem);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.font_direction_hint);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.index_to_loc_format);
|
||
|
ret += GetINT16 (attr->stream, &attr->header.glyph_data_format);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
fontdef->font_bbox. left = (HPDF_REAL)((HPDF_INT32)attr->header.x_min * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
fontdef->font_bbox. bottom = (HPDF_REAL)((HPDF_INT32)attr->header.y_min * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
fontdef->font_bbox. right = (HPDF_REAL)((HPDF_INT32)attr->header.x_max * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
fontdef->font_bbox. top = (HPDF_REAL)((HPDF_INT32)attr->header.y_max * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseMaxp (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "maxp");
|
||
|
HPDF_STATUS ret;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseMaxp\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 9);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 4, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret = GetUINT16 (attr->stream, &attr->num_glyphs);
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_ParseMaxp num_glyphs=%u\n",
|
||
|
attr->num_glyphs));
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHhea (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "hhea");
|
||
|
HPDF_STATUS ret;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseHhea\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 6);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 4, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret += GetINT16 (attr->stream, &fontdef->ascent);
|
||
|
fontdef->ascent = (HPDF_INT16)((HPDF_INT32)fontdef->ascent * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
ret += GetINT16 (attr->stream, &fontdef->descent);
|
||
|
fontdef->descent = (HPDF_INT16)((HPDF_INT32)fontdef->descent * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 34, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret = GetUINT16 (attr->stream, &attr->num_h_metric);
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_ParseHhea num_h_metric=%u\n",
|
||
|
attr->num_h_metric));
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMap (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "cmap");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT16 version;
|
||
|
HPDF_UINT16 num_cmap;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_UINT32 ms_unicode_encoding_offset = 0;
|
||
|
HPDF_UINT32 byte_encoding_offset = 0;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseCMap\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 1);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &version);
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
if (version != 0)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &num_cmap);
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
for (i = 0; i < num_cmap; i++) {
|
||
|
HPDF_UINT16 platformID;
|
||
|
HPDF_UINT16 encodingID;
|
||
|
HPDF_UINT16 format;
|
||
|
HPDF_UINT32 offset;
|
||
|
HPDF_INT32 save_offset;
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &platformID);
|
||
|
ret += GetUINT16 (attr->stream, &encodingID);
|
||
|
ret += GetUINT32 (attr->stream, &offset);
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
save_offset = HPDF_Stream_Tell (attr->stream);
|
||
|
if (save_offset < 0)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset + offset,
|
||
|
HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret = GetUINT16 (attr->stream, &format);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_ParseCMap tables[%d] platformID=%u "
|
||
|
"encodingID=%u format=%u offset=%u\n", i, platformID,
|
||
|
encodingID, format, (HPDF_UINT)offset));
|
||
|
|
||
|
/* MS-Unicode-CMAP is used for priority */
|
||
|
if (platformID == 3 && encodingID == 1 && format == 4) {
|
||
|
ms_unicode_encoding_offset = offset;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Byte-Encoding-CMAP will be used if MS-Unicode-CMAP is not found */
|
||
|
if (platformID == 1 && encodingID ==0 && format == 1)
|
||
|
byte_encoding_offset = offset;
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, save_offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (ms_unicode_encoding_offset != 0) {
|
||
|
HPDF_PTRACE((" found microsoft unicode cmap.\n"));
|
||
|
ret = ParseCMAP_format4(fontdef, ms_unicode_encoding_offset +
|
||
|
tbl->offset);
|
||
|
} else if (byte_encoding_offset != 0) {
|
||
|
HPDF_PTRACE((" found byte encoding cmap.\n"));
|
||
|
ret = ParseCMAP_format0(fontdef, byte_encoding_offset + tbl->offset);
|
||
|
} else {
|
||
|
HPDF_PTRACE((" cannot found target cmap.\n"));
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMAP_format0 (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT32 offset)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_BYTE array[256];
|
||
|
HPDF_UINT size;
|
||
|
HPDF_UINT16 *parray;
|
||
|
HPDF_UINT i;
|
||
|
|
||
|
HPDF_PTRACE((" ParseCMAP_format0\n"));
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.format);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.length);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.language);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
if (attr->cmap.format != 0)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
size = 256;
|
||
|
ret = HPDF_Stream_Read (attr->stream, array, &size);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
attr->cmap.glyph_id_array_count = 256;
|
||
|
attr->cmap.glyph_id_array = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_UINT16) * 256);
|
||
|
if (!attr->cmap.glyph_id_array)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
parray = attr->cmap.glyph_id_array;
|
||
|
for (i = 0; i < 256; i++) {
|
||
|
*parray = attr->cmap.glyph_id_array[i];
|
||
|
HPDF_PTRACE((" ParseCMAP_format0 glyph_id_array[%d]=%u\n",
|
||
|
i, *parray));
|
||
|
parray++;
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseCMAP_format4 (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT32 offset)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_UINT16 *pend_count;
|
||
|
HPDF_UINT16 *pstart_count;
|
||
|
HPDF_INT16 *pid_delta;
|
||
|
HPDF_UINT16 *pid_range_offset;
|
||
|
HPDF_UINT16 *pglyph_id_array;
|
||
|
HPDF_INT32 num_read;
|
||
|
|
||
|
HPDF_PTRACE((" ParseCMAP_format4\n"));
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET)) !=
|
||
|
HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.format);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.length);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.language);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
if (attr->cmap.format != 4)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.seg_count_x2);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.search_range);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.entry_selector);
|
||
|
ret += GetUINT16 (attr->stream, &attr->cmap.range_shift);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
/* end_count */
|
||
|
attr->cmap.end_count = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
|
||
|
if (!attr->cmap.end_count)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pend_count = attr->cmap.end_count;
|
||
|
for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
|
||
|
if ((ret = GetUINT16 (attr->stream, pend_count++)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT16 (attr->stream, &attr->cmap.reserved_pad)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* start_count */
|
||
|
attr->cmap.start_count = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
|
||
|
if (!attr->cmap.start_count)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pstart_count = attr->cmap.start_count;
|
||
|
for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
|
||
|
if ((ret = GetUINT16 (attr->stream, pstart_count++)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* id_delta */
|
||
|
attr->cmap.id_delta = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
|
||
|
if (!attr->cmap.id_delta)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pid_delta = attr->cmap.id_delta;
|
||
|
for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
|
||
|
if ((ret = GetINT16 (attr->stream, pid_delta++)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* id_range_offset */
|
||
|
attr->cmap.id_range_offset = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_UINT16) * attr->cmap.seg_count_x2 / 2);
|
||
|
if (!attr->cmap.id_range_offset)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pid_range_offset = attr->cmap.id_range_offset;
|
||
|
for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++)
|
||
|
if ((ret = GetUINT16 (attr->stream, pid_range_offset++)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
num_read = HPDF_Stream_Tell (attr->stream) - offset;
|
||
|
if (num_read < 0)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
attr->cmap.glyph_id_array_count = (attr->cmap.length - num_read) / 2;
|
||
|
|
||
|
if (attr->cmap.glyph_id_array_count > 0) {
|
||
|
/* glyph_id_array */
|
||
|
attr->cmap.glyph_id_array = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof(HPDF_UINT16) * attr->cmap.glyph_id_array_count);
|
||
|
if (!attr->cmap.glyph_id_array)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pglyph_id_array = attr->cmap.glyph_id_array;
|
||
|
for (i = 0; i < attr->cmap.glyph_id_array_count; i++)
|
||
|
if ((ret = GetUINT16 (attr->stream, pglyph_id_array++)) != HPDF_OK)
|
||
|
return ret;
|
||
|
} else
|
||
|
attr->cmap.glyph_id_array = NULL;
|
||
|
|
||
|
#ifdef LIBHPDF_DEBUG
|
||
|
/* print all elements of cmap table */
|
||
|
for (i = 0; i < (HPDF_UINT)attr->cmap.seg_count_x2 / 2; i++) {
|
||
|
HPDF_PTRACE((" ParseCMAP_format4[%d] start_count=0x%04X, "
|
||
|
"end_count=0x%04X, id_delta=%d, id_range_offset=%u\n", i,
|
||
|
attr->cmap.start_count[i], attr->cmap.end_count[i],
|
||
|
attr->cmap.id_delta[i], attr->cmap.id_range_offset[i]));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_UINT16
|
||
|
HPDF_TTFontDef_GetGlyphid (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 unicode)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_UINT16 *pend_count = attr->cmap.end_count;
|
||
|
HPDF_UINT seg_count = attr->cmap.seg_count_x2 / 2;
|
||
|
HPDF_UINT i;
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid\n"));
|
||
|
|
||
|
/* format 0 */
|
||
|
if (attr->cmap.format == 0) {
|
||
|
unicode &= 0xFF;
|
||
|
return attr->cmap.glyph_id_array[unicode];
|
||
|
}
|
||
|
|
||
|
/* format 4 */
|
||
|
if (attr->cmap.seg_count_x2 == 0) {
|
||
|
HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_CMAP, 0);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < seg_count; i++) {
|
||
|
if (unicode <= *pend_count)
|
||
|
break;
|
||
|
pend_count++;
|
||
|
}
|
||
|
|
||
|
if (attr->cmap.start_count[i] > unicode) {
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid undefined char(0x%04X)\n",
|
||
|
unicode));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (attr->cmap.id_range_offset[i] == 0) {
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid idx=%u code=%u "
|
||
|
" ret=%u\n", i, unicode,
|
||
|
unicode + attr->cmap.id_delta[i]));
|
||
|
|
||
|
return (HPDF_UINT16)(unicode + attr->cmap.id_delta[i]);
|
||
|
} else {
|
||
|
HPDF_UINT idx = attr->cmap.id_range_offset[i] / 2 +
|
||
|
(unicode - attr->cmap.start_count[i]) - (seg_count - i);
|
||
|
|
||
|
if (idx > attr->cmap.glyph_id_array_count) {
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid[%u] %u > %u\n",
|
||
|
i, idx, (HPDF_UINT)attr->cmap.glyph_id_array_count));
|
||
|
return 0;
|
||
|
} else {
|
||
|
HPDF_UINT16 gid = (HPDF_UINT16)(attr->cmap.glyph_id_array[idx] +
|
||
|
attr->cmap.id_delta[i]);
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGlyphid idx=%u unicode=0x%04X "
|
||
|
"id=%u\n", idx, unicode, gid));
|
||
|
return gid;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_INT16
|
||
|
HPDF_TTFontDef_GetCharWidth (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 unicode)
|
||
|
{
|
||
|
HPDF_UINT16 advance_width;
|
||
|
HPDF_TTF_LongHorMetric hmetrics;
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_UINT16 gid = HPDF_TTFontDef_GetGlyphid (fontdef, unicode);
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetCharWidth\n"));
|
||
|
|
||
|
if (gid >= attr->num_glyphs) {
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetCharWidth WARNING gid > "
|
||
|
"num_glyphs %u > %u\n", gid, attr->num_glyphs));
|
||
|
return fontdef->missing_width;
|
||
|
}
|
||
|
|
||
|
hmetrics = attr->h_metric[gid];
|
||
|
|
||
|
if (!attr->glyph_tbl.flgs[gid]) {
|
||
|
attr->glyph_tbl.flgs[gid] = 1;
|
||
|
|
||
|
if (attr->embedding)
|
||
|
CheckCompositGryph (fontdef, gid);
|
||
|
}
|
||
|
|
||
|
advance_width = (HPDF_UINT16)((HPDF_UINT)hmetrics.advance_width * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
|
||
|
return (HPDF_INT16)advance_width;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
CheckCompositGryph (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 gid)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_UINT offset = attr->glyph_tbl.offsets[gid];
|
||
|
/* HPDF_UINT len = attr->glyph_tbl.offsets[gid + 1] - offset; */
|
||
|
HPDF_STATUS ret;
|
||
|
|
||
|
HPDF_PTRACE ((" CheckCompositGryph\n"));
|
||
|
|
||
|
if (attr->header.index_to_loc_format == 0)
|
||
|
offset *= 2;
|
||
|
|
||
|
offset += attr->glyph_tbl.base_offset;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET))
|
||
|
!= HPDF_OK) {
|
||
|
return ret;
|
||
|
} else {
|
||
|
HPDF_INT16 num_of_contours;
|
||
|
HPDF_INT16 flags;
|
||
|
HPDF_INT16 glyph_index;
|
||
|
const HPDF_UINT16 ARG_1_AND_2_ARE_WORDS = 1;
|
||
|
const HPDF_UINT16 WE_HAVE_A_SCALE = 8;
|
||
|
const HPDF_UINT16 MORE_COMPONENTS = 32;
|
||
|
const HPDF_UINT16 WE_HAVE_AN_X_AND_Y_SCALE = 64;
|
||
|
const HPDF_UINT16 WE_HAVE_A_TWO_BY_TWO = 128;
|
||
|
|
||
|
if ((ret = GetINT16 (attr->stream, &num_of_contours)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if (num_of_contours != -1)
|
||
|
return HPDF_OK;
|
||
|
|
||
|
HPDF_PTRACE ((" CheckCompositGryph composit font gid=%u\n", gid));
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 8, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
do {
|
||
|
if ((ret = GetINT16 (attr->stream, &flags)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetINT16 (attr->stream, &glyph_index)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if (flags & ARG_1_AND_2_ARE_WORDS) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 4, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
} else {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 2, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (flags & WE_HAVE_A_SCALE) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 2, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
} else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 4, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
} else if (flags & WE_HAVE_A_TWO_BY_TWO) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 8, HPDF_SEEK_CUR))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (glyph_index > 0 && glyph_index < attr->num_glyphs)
|
||
|
attr->glyph_tbl.flgs[glyph_index] = 1;
|
||
|
|
||
|
HPDF_PTRACE ((" gid=%d, num_of_contours=%d, flags=%d, "
|
||
|
"glyph_index=%d\n", gid, num_of_contours, flags,
|
||
|
glyph_index));
|
||
|
|
||
|
} while (flags & MORE_COMPONENTS);
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_INT16
|
||
|
HPDF_TTFontDef_GetGidWidth (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT16 gid)
|
||
|
{
|
||
|
HPDF_UINT16 advance_width;
|
||
|
HPDF_TTF_LongHorMetric hmetrics;
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth\n"));
|
||
|
|
||
|
if (gid >= attr->num_glyphs) {
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth WARNING gid > "
|
||
|
"num_glyphs %u > %u\n", gid, attr->num_glyphs));
|
||
|
return fontdef->missing_width;
|
||
|
}
|
||
|
|
||
|
hmetrics = attr->h_metric[gid];
|
||
|
|
||
|
advance_width = (HPDF_UINT16)((HPDF_UINT)hmetrics.advance_width * 1000 /
|
||
|
attr->header.units_per_em);
|
||
|
|
||
|
HPDF_PTRACE((" HPDF_TTFontDef_GetGidWidth gid=%u, width=%u\n",
|
||
|
gid, advance_width));
|
||
|
|
||
|
return (HPDF_INT16)advance_width;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseHmtx (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "hmtx");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_UINT16 save_aw = 0;
|
||
|
HPDF_TTF_LongHorMetric *pmetric;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseHtmx\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 7);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* allocate memory for a table of holizontal matrix.
|
||
|
* the count of metric records is same as the number of glyphs
|
||
|
*/
|
||
|
attr->h_metric = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_TTF_LongHorMetric) * attr->num_glyphs);
|
||
|
|
||
|
if (!attr->h_metric)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
pmetric = attr->h_metric;
|
||
|
for (i = 0; i < attr->num_h_metric; i++) {
|
||
|
if ((ret = GetUINT16 (attr->stream, &pmetric->advance_width)) !=
|
||
|
HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetINT16 (attr->stream, &pmetric->lsb)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
HPDF_PTRACE((" ParseHmtx metric[%u] aw=%u lsb=%d\n", i,
|
||
|
pmetric->advance_width, pmetric->lsb));
|
||
|
|
||
|
save_aw = pmetric->advance_width;
|
||
|
pmetric++;
|
||
|
}
|
||
|
|
||
|
/* pad the advance_width of remaining metrics with the value of last metric */
|
||
|
while (i < attr->num_glyphs) {
|
||
|
pmetric->advance_width = save_aw;
|
||
|
|
||
|
if ((ret = GetINT16 (attr->stream, &pmetric->lsb)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
pmetric++;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseLoca (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "loca");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_UINT32 *poffset;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseLoca\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 8);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* allocate glyph-offset-table. */
|
||
|
attr->glyph_tbl.offsets = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
|
||
|
|
||
|
if (!attr->glyph_tbl.offsets)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
HPDF_MemSet (attr->glyph_tbl.offsets, 0,
|
||
|
sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
|
||
|
|
||
|
/* allocate glyph-flg-table.
|
||
|
* this flgs are used to judge whether glyphs should be embedded.
|
||
|
*/
|
||
|
attr->glyph_tbl.flgs = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_BYTE) * attr->num_glyphs);
|
||
|
|
||
|
if (!attr->glyph_tbl.flgs)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
HPDF_MemSet (attr->glyph_tbl.flgs, 0,
|
||
|
sizeof (HPDF_BYTE) * attr->num_glyphs);
|
||
|
attr->glyph_tbl.flgs[0] = 1;
|
||
|
|
||
|
poffset = attr->glyph_tbl.offsets;
|
||
|
if (attr->header.index_to_loc_format == 0) {
|
||
|
/* short version */
|
||
|
for (i = 0; i <= attr->num_glyphs; i++) {
|
||
|
HPDF_UINT16 tmp = 0;
|
||
|
|
||
|
if ((ret = GetUINT16 (attr->stream, &tmp)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
*poffset = tmp;
|
||
|
poffset++;
|
||
|
}
|
||
|
} else {
|
||
|
/* long version */
|
||
|
for (i = 0; i <= attr->num_glyphs; i++) {
|
||
|
if ((ret = GetUINT32 (attr->stream, poffset)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
poffset++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef LIBHPDF_DEBUG
|
||
|
poffset = attr->glyph_tbl.offsets;
|
||
|
for (i = 0; i <= attr->num_glyphs; i++) {
|
||
|
HPDF_PTRACE((" ParseLOCA offset[%u]=%u\n", i, (HPDF_UINT)*poffset));
|
||
|
poffset++;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
LoadUnicodeName (HPDF_Stream stream,
|
||
|
HPDF_UINT offset,
|
||
|
HPDF_UINT len,
|
||
|
char *buf)
|
||
|
{
|
||
|
HPDF_BYTE tmp[HPDF_LIMIT_MAX_NAME_LEN * 2 + 1];
|
||
|
HPDF_UINT i = 0;
|
||
|
HPDF_UINT j = 0;
|
||
|
HPDF_STATUS ret;
|
||
|
|
||
|
HPDF_MemSet (buf, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (stream, offset, HPDF_SEEK_SET)) !=
|
||
|
HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Read (stream, tmp, &len))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
while (i < len) {
|
||
|
i++;
|
||
|
buf[j] = tmp[i];
|
||
|
j++;
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseName (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "name");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_TTF_NameRecord *name_rec;
|
||
|
HPDF_UINT offset_id1 = 0;
|
||
|
HPDF_UINT offset_id2 = 0;
|
||
|
HPDF_UINT offset_id1u = 0;
|
||
|
HPDF_UINT offset_id2u = 0;
|
||
|
HPDF_UINT len_id1 = 0;
|
||
|
HPDF_UINT len_id2 = 0;
|
||
|
HPDF_UINT len_id1u = 0;
|
||
|
HPDF_UINT len_id2u = 0;
|
||
|
char tmp[HPDF_LIMIT_MAX_NAME_LEN + 1];
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_ParseMaxp\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 10);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
ret += GetUINT16 (attr->stream, &attr->name_tbl.format);
|
||
|
ret += GetUINT16 (attr->stream, &attr->name_tbl.count);
|
||
|
ret += GetUINT16 (attr->stream, &attr->name_tbl.string_offset);
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
HPDF_PTRACE((" ParseName() format=%u, count=%u, string_offset=%u\n",
|
||
|
attr->name_tbl.format, attr->name_tbl.count,
|
||
|
attr->name_tbl.string_offset));
|
||
|
|
||
|
attr->name_tbl.name_records = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_TTF_NameRecord) * attr->name_tbl.count);
|
||
|
|
||
|
if (!attr->name_tbl.name_records)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
name_rec = attr->name_tbl.name_records;
|
||
|
|
||
|
for (i = 0; i < attr->name_tbl.count; i++) {
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->platform_id);
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->encoding_id);
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->language_id);
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->name_id);
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->length);
|
||
|
ret += GetUINT16 (attr->stream, &name_rec->offset);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
HPDF_PTRACE((" ParseName() platformID=%u, encodingID=%d, nameID=%d\n",
|
||
|
name_rec->platform_id, name_rec->encoding_id,
|
||
|
name_rec->name_id));
|
||
|
|
||
|
if (name_rec->platform_id == 1 && name_rec->encoding_id == 0 &&
|
||
|
name_rec->name_id == 6) {
|
||
|
offset_id1 = tbl->offset + name_rec->offset +
|
||
|
attr->name_tbl.string_offset;
|
||
|
len_id1 = name_rec->length;
|
||
|
}
|
||
|
|
||
|
if (name_rec->platform_id == 1 && name_rec->encoding_id == 0 &&
|
||
|
name_rec->name_id == 2) {
|
||
|
offset_id2 = tbl->offset + name_rec->offset +
|
||
|
attr->name_tbl.string_offset;
|
||
|
len_id2 = name_rec->length;
|
||
|
}
|
||
|
|
||
|
if (name_rec->platform_id == 3 && name_rec->encoding_id == 1 &&
|
||
|
name_rec->name_id == 6 && name_rec->language_id == 0x0409) {
|
||
|
offset_id1u = tbl->offset + name_rec->offset +
|
||
|
attr->name_tbl.string_offset;
|
||
|
len_id1u = name_rec->length;
|
||
|
}
|
||
|
|
||
|
if (name_rec->platform_id == 3 && name_rec->encoding_id == 1 &&
|
||
|
name_rec->name_id == 2 && name_rec->language_id == 0x0409) {
|
||
|
offset_id2u = tbl->offset + name_rec->offset +
|
||
|
attr->name_tbl.string_offset;
|
||
|
len_id2u = name_rec->length;
|
||
|
}
|
||
|
|
||
|
name_rec++;
|
||
|
}
|
||
|
|
||
|
if ((!offset_id1 && !offset_id1u) ||
|
||
|
(!offset_id2 && !offset_id2u))
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
if (len_id1 == 0 && len_id1u > 0)
|
||
|
len_id1 = len_id1u / 2 + len_id1u % 2;
|
||
|
|
||
|
if (len_id2 == 0 && len_id2u > 0)
|
||
|
len_id2 = len_id2u / 2 + len_id2u % 2;
|
||
|
|
||
|
if (len_id1 + len_id2 + 8 > 127)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_INVALID_FOMAT, 0);
|
||
|
|
||
|
HPDF_MemSet (attr->base_font, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
|
||
|
if (offset_id1) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, offset_id1,
|
||
|
HPDF_SEEK_SET)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)attr->base_font, &len_id1))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
} else {
|
||
|
if ((ret = LoadUnicodeName (attr->stream, offset_id1u, len_id1u,
|
||
|
attr->base_font)) != HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
HPDF_MemSet (tmp, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
|
||
|
if (offset_id2) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, offset_id2, HPDF_SEEK_SET))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)tmp, &len_id2)) != HPDF_OK)
|
||
|
return ret;
|
||
|
} else {
|
||
|
if ((ret = LoadUnicodeName (attr->stream, offset_id2u, len_id2u,
|
||
|
tmp)) != HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* get "postscript name" of from a "name" table as BaseName.
|
||
|
* if subfamily name is not "Regular", add subfamily name to BaseName.
|
||
|
* if subfamily name includes the blank character, remove it.
|
||
|
* if subfamily name is "Bold" or "Italic" or "BoldItalic", set flags
|
||
|
* attribute.
|
||
|
*/
|
||
|
if (HPDF_MemCmp ((HPDF_BYTE *)tmp, (HPDF_BYTE *)"Regular", 7) != 0) {
|
||
|
char *dst = attr->base_font + len_id1;
|
||
|
char *src = tmp;
|
||
|
HPDF_UINT j;
|
||
|
|
||
|
*dst++ = ',';
|
||
|
|
||
|
for (j = 0; j < len_id2; j++) {
|
||
|
if (*src != ' ')
|
||
|
*dst++ = *src++;
|
||
|
|
||
|
if (dst >= attr->base_font + HPDF_LIMIT_MAX_NAME_LEN)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*dst = 0;
|
||
|
|
||
|
if (HPDF_StrStr (tmp, "Bold", len_id2))
|
||
|
fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
|
||
|
if (HPDF_StrStr (tmp, "Italic", len_id2))
|
||
|
fontdef->flags |= HPDF_FONT_ITALIC;
|
||
|
}
|
||
|
|
||
|
HPDF_MemCpy ((HPDF_BYTE *)fontdef->base_font, (HPDF_BYTE *)attr->base_font, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
|
||
|
HPDF_PTRACE((" ParseName() base_font=%s\n", attr->base_font));
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
ParseOS2 (HPDF_FontDef fontdef)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "OS/2");
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT16 version;
|
||
|
HPDF_UINT len;
|
||
|
|
||
|
HPDF_PTRACE ((" ParseOS2\n"));
|
||
|
|
||
|
if (!tbl)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, 0);
|
||
|
|
||
|
/* get the number version. */
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT16 (attr->stream, &version)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* check whether the font is allowed to be embedded. */
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 8, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT16 (attr->stream, &attr->fs_type)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if (attr->fs_type & (0x0002 | 0x0100 | 0x0200) && attr->embedding)
|
||
|
return HPDF_SetError (fontdef->error, HPDF_TTF_CANNOT_EMBEDDING_FONT,
|
||
|
0);
|
||
|
|
||
|
/* get fields sfamilyclass and panose. */
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, tbl->offset + 30, HPDF_SEEK_SET))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
len = 2;
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, attr->sfamilyclass, &len)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
len = 10;
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, attr->panose, &len)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
HPDF_PTRACE((" ParseOS2 sFamilyClass=%d-%d "
|
||
|
"Panose=%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
|
||
|
attr->sfamilyclass[0], attr->sfamilyclass[1],
|
||
|
attr->panose[0], attr->panose[1], attr->panose[2], attr->panose[3],
|
||
|
attr->panose[4], attr->panose[5], attr->panose[6], attr->panose[7],
|
||
|
attr->panose[8], attr->panose[9]));
|
||
|
|
||
|
/* Class ID = 1 Oldstyle Serifs
|
||
|
Class ID = 2 Transitional Serifs
|
||
|
Class ID = 3 Modern Serifs
|
||
|
Class ID = 4 Clarendon Serifs
|
||
|
Class ID = 5 Slab Serifs
|
||
|
Class ID = 6 (reserved for future use)
|
||
|
Class ID = 7 Freeform Serifs
|
||
|
Class ID = 8 Sans Serif
|
||
|
Class ID = 9 Ornamentals
|
||
|
Class ID = 10 Scripts
|
||
|
Class ID = 11 (reserved for future use)
|
||
|
Class ID = 12 Symbolic */
|
||
|
if ((attr->sfamilyclass[0] > 0 && attr->sfamilyclass[0] < 6)
|
||
|
|| (attr->sfamilyclass[0] == 7))
|
||
|
fontdef->flags = fontdef->flags | HPDF_FONT_SERIF;
|
||
|
|
||
|
if (attr->sfamilyclass[0] == 10)
|
||
|
fontdef->flags = fontdef->flags | HPDF_FONT_SCRIPT;
|
||
|
|
||
|
if (attr->sfamilyclass[0] == 12)
|
||
|
fontdef->flags = fontdef->flags | HPDF_FONT_SYMBOLIC;
|
||
|
|
||
|
/* get fields ulCodePageRange1 and ulCodePageRange2 */
|
||
|
if(version > 0) {
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, 36, HPDF_SEEK_CUR)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT32 (attr->stream, &attr->code_page_range1)) != HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = GetUINT32 (attr->stream, &attr->code_page_range2)) != HPDF_OK)
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
HPDF_PTRACE((" ParseOS2 CodePageRange1=%08X CodePageRange2=%08X\n",
|
||
|
(HPDF_UINT)attr->code_page_range1,
|
||
|
(HPDF_UINT)attr->code_page_range2));
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
RecreateGLYF (HPDF_FontDef fontdef,
|
||
|
HPDF_UINT32 *new_offsets,
|
||
|
HPDF_Stream stream)
|
||
|
{
|
||
|
HPDF_UINT32 save_offset = 0;
|
||
|
HPDF_UINT32 start_offset = stream->size;
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_INT i;
|
||
|
|
||
|
HPDF_PTRACE ((" RecreateGLYF\n"));
|
||
|
|
||
|
for (i = 0; i < attr->num_glyphs; i++) {
|
||
|
HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
|
||
|
|
||
|
if (attr->glyph_tbl.flgs[i] == 1) {
|
||
|
HPDF_UINT offset = attr->glyph_tbl.offsets[i];
|
||
|
HPDF_UINT len = attr->glyph_tbl.offsets[i + 1] - offset;
|
||
|
|
||
|
new_offsets[i] = stream->size - start_offset;
|
||
|
if (attr->header.index_to_loc_format == 0) {
|
||
|
new_offsets[i] /= 2;
|
||
|
len *= 2;
|
||
|
}
|
||
|
|
||
|
HPDF_PTRACE((" RecreateGLYF[%u] move from [%u] to [%u]\n", i,
|
||
|
(HPDF_UINT)attr->glyph_tbl.base_offset + offset,
|
||
|
(HPDF_UINT)new_offsets[i]));
|
||
|
|
||
|
if (attr->header.index_to_loc_format == 0)
|
||
|
offset *= 2;
|
||
|
|
||
|
offset += attr->glyph_tbl.base_offset;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
while (len > 0) {
|
||
|
HPDF_UINT tmp_len =
|
||
|
(len > HPDF_STREAM_BUF_SIZ) ? HPDF_STREAM_BUF_SIZ : len;
|
||
|
|
||
|
HPDF_MemSet (buf, 0, tmp_len);
|
||
|
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, buf, &tmp_len))
|
||
|
!= HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Write (stream, buf, tmp_len)) !=
|
||
|
HPDF_OK)
|
||
|
return ret;
|
||
|
|
||
|
len -= tmp_len;
|
||
|
}
|
||
|
|
||
|
save_offset = stream->size - start_offset;
|
||
|
if (attr->header.index_to_loc_format == 0)
|
||
|
save_offset /= 2;
|
||
|
} else {
|
||
|
new_offsets[i] = save_offset;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
new_offsets[attr->num_glyphs] = save_offset;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
for (i = 0; i <= attr->num_glyphs; i++) {
|
||
|
HPDF_PTRACE((" RecreateGLYF[%u] offset=%u\n", i, new_offsets[i]));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
RecreateName (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, "name");
|
||
|
HPDF_STATUS ret = HPDF_OK;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_TTF_NameRecord *name_rec;
|
||
|
HPDF_Stream tmp_stream = HPDF_MemStream_New (fontdef->mmgr,
|
||
|
HPDF_STREAM_BUF_SIZ);
|
||
|
|
||
|
HPDF_PTRACE ((" RecreateName\n"));
|
||
|
|
||
|
if (!tmp_stream)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
ret += WriteUINT16 (stream, attr->name_tbl.format);
|
||
|
ret += WriteUINT16 (stream, attr->name_tbl.count);
|
||
|
ret += WriteUINT16 (stream, attr->name_tbl.string_offset);
|
||
|
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
}
|
||
|
|
||
|
name_rec = attr->name_tbl.name_records;
|
||
|
for (i = 0; i < attr->name_tbl.count; i++) {
|
||
|
HPDF_UINT name_len = name_rec->length;
|
||
|
HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
|
||
|
HPDF_UINT tmp_len = name_len;
|
||
|
HPDF_UINT offset = tbl->offset + attr->name_tbl.string_offset +
|
||
|
name_rec->offset;
|
||
|
HPDF_UINT rec_offset = tmp_stream->size;
|
||
|
|
||
|
/* add suffix to font-name. */
|
||
|
if (name_rec->name_id == 1 || name_rec->name_id == 4) {
|
||
|
if (name_rec->platform_id == 0 || name_rec->platform_id == 3) {
|
||
|
ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name2,
|
||
|
sizeof(attr->tag_name2));
|
||
|
name_len += sizeof(attr->tag_name2);
|
||
|
} else {
|
||
|
ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)attr->tag_name,
|
||
|
sizeof(attr->tag_name));
|
||
|
name_len += sizeof(attr->tag_name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ret += WriteUINT16 (stream, name_rec->platform_id);
|
||
|
ret += WriteUINT16 (stream, name_rec->encoding_id);
|
||
|
ret += WriteUINT16 (stream, name_rec->language_id);
|
||
|
ret += WriteUINT16 (stream, name_rec->name_id);
|
||
|
ret += WriteUINT16 (stream, (HPDF_UINT16)name_len);
|
||
|
ret += WriteUINT16 (stream, (HPDF_UINT16)rec_offset);
|
||
|
|
||
|
ret += HPDF_Stream_Seek (attr->stream, offset, HPDF_SEEK_SET);
|
||
|
|
||
|
if (ret != HPDF_OK) {
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
}
|
||
|
|
||
|
while (tmp_len > 0) {
|
||
|
HPDF_UINT len = (tmp_len > HPDF_STREAM_BUF_SIZ) ?
|
||
|
HPDF_STREAM_BUF_SIZ : tmp_len;
|
||
|
|
||
|
if ((ret = HPDF_Stream_Read (attr->stream, buf, &len)) != HPDF_OK) {
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if ((ret = HPDF_Stream_Write (tmp_stream, buf, len)) != HPDF_OK) {
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
tmp_len -= len;
|
||
|
}
|
||
|
|
||
|
HPDF_PTRACE((" RecreateNAME name_rec[%u] platform_id=%u "
|
||
|
"encoding_id=%u language_id=%u name_rec->name_id=%u "
|
||
|
"length=%u offset=%u\n", i, name_rec->platform_id,
|
||
|
name_rec->encoding_id, name_rec->language_id,
|
||
|
name_rec->name_id, name_len, rec_offset));
|
||
|
|
||
|
name_rec++;
|
||
|
}
|
||
|
|
||
|
ret = HPDF_Stream_WriteToStream (tmp_stream, stream,
|
||
|
HPDF_STREAM_FILTER_NONE, NULL);
|
||
|
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
static HPDF_STATUS
|
||
|
WriteHeader (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream,
|
||
|
HPDF_UINT32 *check_sum_ptr)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_STATUS ret = HPDF_OK;
|
||
|
|
||
|
HPDF_PTRACE ((" WriteHeader\n"));
|
||
|
|
||
|
ret += HPDF_Stream_Write (stream, attr->header.version_number, 4);
|
||
|
ret += WriteUINT32 (stream, attr->header.font_revision);
|
||
|
|
||
|
/* save the address of checkSumAdjustment.
|
||
|
* the value is rewrite to computed value after new check-sum-value is
|
||
|
* generated.
|
||
|
*/
|
||
|
*check_sum_ptr = stream->size;
|
||
|
|
||
|
ret += WriteUINT32 (stream, 0);
|
||
|
ret += WriteUINT32 (stream, attr->header.magic_number);
|
||
|
ret += WriteUINT16 (stream, attr->header.flags);
|
||
|
ret += WriteUINT16 (stream, attr->header.units_per_em);
|
||
|
ret += HPDF_Stream_Write (stream, attr->header.created, 8);
|
||
|
ret += HPDF_Stream_Write (stream, attr->header.modified, 8);
|
||
|
ret += WriteINT16 (stream, attr->header.x_min);
|
||
|
ret += WriteINT16 (stream, attr->header.y_min);
|
||
|
ret += WriteINT16 (stream, attr->header.x_max);
|
||
|
ret += WriteINT16 (stream, attr->header.y_max);
|
||
|
ret += WriteUINT16 (stream, attr->header.mac_style);
|
||
|
ret += WriteUINT16 (stream, attr->header.lowest_rec_ppem);
|
||
|
ret += WriteINT16 (stream, attr->header.font_direction_hint);
|
||
|
ret += WriteINT16 (stream, attr->header.index_to_loc_format);
|
||
|
ret += WriteINT16 (stream, attr->header.glyph_data_format);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
return HPDF_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HPDF_STATUS
|
||
|
HPDF_TTFontDef_SaveFontData (HPDF_FontDef fontdef,
|
||
|
HPDF_Stream stream)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable tmp_tbl[HPDF_REQUIRED_TAGS_COUNT];
|
||
|
HPDF_Stream tmp_stream;
|
||
|
HPDF_UINT32 *new_offsets;
|
||
|
HPDF_UINT i;
|
||
|
HPDF_UINT32 check_sum_ptr = 0;
|
||
|
HPDF_STATUS ret;
|
||
|
HPDF_UINT32 offset_base;
|
||
|
HPDF_UINT32 tmp_check_sum = 0xB1B0AFBA;
|
||
|
HPDF_TTFTable emptyTable;
|
||
|
emptyTable.length = 0;
|
||
|
emptyTable.offset = 0;
|
||
|
|
||
|
HPDF_PTRACE ((" SaveFontData\n"));
|
||
|
|
||
|
ret = WriteUINT32 (stream, attr->offset_tbl.sfnt_version);
|
||
|
ret += WriteUINT16 (stream, HPDF_REQUIRED_TAGS_COUNT);
|
||
|
ret += WriteUINT16 (stream, attr->offset_tbl.search_range);
|
||
|
ret += WriteUINT16 (stream, attr->offset_tbl.entry_selector);
|
||
|
ret += WriteUINT16 (stream, attr->offset_tbl.range_shift);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
tmp_stream = HPDF_MemStream_New (fontdef->mmgr, HPDF_STREAM_BUF_SIZ);
|
||
|
if (!tmp_stream)
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
|
||
|
offset_base = 12 + 16 * HPDF_REQUIRED_TAGS_COUNT;
|
||
|
|
||
|
new_offsets = HPDF_GetMem (fontdef->mmgr,
|
||
|
sizeof (HPDF_UINT32) * (attr->num_glyphs + 1));
|
||
|
if (!new_offsets) {
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return HPDF_Error_GetCode (fontdef->error);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
|
||
|
HPDF_TTFTable *tbl = FindTable (fontdef, REQUIRED_TAGS[i]);
|
||
|
HPDF_UINT32 length;
|
||
|
HPDF_UINT new_offset;
|
||
|
HPDF_UINT32 *poffset;
|
||
|
HPDF_UINT32 value;
|
||
|
|
||
|
if (!tbl) {
|
||
|
tbl = &emptyTable;
|
||
|
HPDF_MemCpy((HPDF_BYTE *)tbl->tag,
|
||
|
(const HPDF_BYTE *)REQUIRED_TAGS[i], 4);
|
||
|
}
|
||
|
|
||
|
if (!tbl) {
|
||
|
ret = HPDF_SetError (fontdef->error, HPDF_TTF_MISSING_TABLE, i);
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
ret = HPDF_Stream_Seek (attr->stream, tbl->offset, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
|
||
|
length = tbl->length;
|
||
|
new_offset = tmp_stream->size;
|
||
|
|
||
|
if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"head", 4) == 0) {
|
||
|
ret = WriteHeader (fontdef, tmp_stream, &check_sum_ptr);
|
||
|
} else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"glyf", 4) == 0) {
|
||
|
ret = RecreateGLYF (fontdef, new_offsets, tmp_stream);
|
||
|
} else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"loca", 4) == 0) {
|
||
|
HPDF_UINT j;
|
||
|
|
||
|
HPDF_MemSet (&value, 0, 4);
|
||
|
poffset = new_offsets;
|
||
|
|
||
|
if (attr->header.index_to_loc_format == 0) {
|
||
|
for (j = 0; j <= attr->num_glyphs; j++) {
|
||
|
ret += WriteUINT16 (tmp_stream, (HPDF_UINT16)*poffset);
|
||
|
poffset++;
|
||
|
}
|
||
|
} else {
|
||
|
for (j = 0; j <= attr->num_glyphs; j++) {
|
||
|
ret += WriteUINT32 (tmp_stream, *poffset);
|
||
|
poffset++;
|
||
|
}
|
||
|
}
|
||
|
} else if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)"name", 4) == 0) {
|
||
|
ret = RecreateName (fontdef, tmp_stream);
|
||
|
} else {
|
||
|
HPDF_UINT size = 4;
|
||
|
|
||
|
while (length > 4) {
|
||
|
value = 0;
|
||
|
size = 4;
|
||
|
ret = HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
|
||
|
ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
|
||
|
length -= 4;
|
||
|
}
|
||
|
|
||
|
value = 0;
|
||
|
size = length;
|
||
|
ret += HPDF_Stream_Read (attr->stream, (HPDF_BYTE *)&value, &size);
|
||
|
ret += HPDF_Stream_Write (tmp_stream, (HPDF_BYTE *)&value, size);
|
||
|
}
|
||
|
|
||
|
tmp_tbl[i].offset = new_offset;
|
||
|
tmp_tbl[i].length = tmp_stream->size - new_offset;
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
/* recalcurate checksum */
|
||
|
for (i = 0; i < HPDF_REQUIRED_TAGS_COUNT; i++) {
|
||
|
HPDF_TTFTable tbl = tmp_tbl[i];
|
||
|
HPDF_UINT32 buf;
|
||
|
HPDF_UINT length = tbl.length;
|
||
|
|
||
|
HPDF_PTRACE((" SaveFontData() tag[%s] length=%u\n",
|
||
|
REQUIRED_TAGS[i], length));
|
||
|
|
||
|
if ((ret = HPDF_Stream_Seek (tmp_stream, tbl.offset, HPDF_SEEK_SET))
|
||
|
!= HPDF_OK)
|
||
|
break;
|
||
|
|
||
|
tbl.check_sum = 0;
|
||
|
while (length > 0) {
|
||
|
HPDF_UINT rlen = (length > 4) ? 4 : length;
|
||
|
buf = 0;
|
||
|
if ((ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &rlen))
|
||
|
!= HPDF_OK)
|
||
|
break;
|
||
|
|
||
|
UINT32Swap (&buf);
|
||
|
tbl.check_sum += buf;
|
||
|
length -= rlen;
|
||
|
}
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
break;
|
||
|
|
||
|
HPDF_PTRACE((" SaveFontData tag[%s] check-sum=%u offset=%u\n",
|
||
|
REQUIRED_TAGS[i], (HPDF_UINT)tbl.check_sum,
|
||
|
(HPDF_UINT)tbl.offset));
|
||
|
|
||
|
ret += HPDF_Stream_Write (stream, (HPDF_BYTE *)REQUIRED_TAGS[i], 4);
|
||
|
ret += WriteUINT32 (stream, tbl.check_sum);
|
||
|
tbl.offset += offset_base;
|
||
|
ret += WriteUINT32 (stream, tbl.offset);
|
||
|
ret += WriteUINT32 (stream, tbl.length);
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
|
||
|
/* calucurate checkSumAdjustment.*/
|
||
|
ret = HPDF_Stream_Seek (tmp_stream, 0, HPDF_SEEK_SET);
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
|
||
|
for (;;) {
|
||
|
HPDF_UINT32 buf;
|
||
|
HPDF_UINT siz = sizeof(buf);
|
||
|
|
||
|
ret = HPDF_Stream_Read (tmp_stream, (HPDF_BYTE *)&buf, &siz);
|
||
|
if (ret != HPDF_OK || siz <= 0) {
|
||
|
if (ret == HPDF_STREAM_EOF)
|
||
|
ret = HPDF_OK;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
UINT32Swap (&buf);
|
||
|
tmp_check_sum -= buf;
|
||
|
}
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
|
||
|
HPDF_PTRACE((" SaveFontData new checkSumAdjustment=%u\n",
|
||
|
(HPDF_UINT)tmp_check_sum));
|
||
|
|
||
|
UINT32Swap (&tmp_check_sum);
|
||
|
|
||
|
ret = HPDF_Stream_Seek (tmp_stream, check_sum_ptr, HPDF_SEEK_SET);
|
||
|
if (ret == HPDF_OK) {
|
||
|
ret = HPDF_MemStream_Rewrite (tmp_stream, (HPDF_BYTE *)&tmp_check_sum,
|
||
|
4);
|
||
|
}
|
||
|
|
||
|
if (ret != HPDF_OK)
|
||
|
goto Exit;
|
||
|
|
||
|
attr->length1 = tmp_stream->size + offset_base;
|
||
|
ret = HPDF_Stream_WriteToStream (tmp_stream, stream, 0, NULL);
|
||
|
|
||
|
goto Exit;
|
||
|
|
||
|
Exit:
|
||
|
HPDF_FreeMem (fontdef->mmgr, new_offsets);
|
||
|
HPDF_Stream_Free (tmp_stream);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
HPDF_TTFontDef_SetTagName (HPDF_FontDef fontdef,
|
||
|
char *tag)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
char buf[HPDF_LIMIT_MAX_NAME_LEN + 1];
|
||
|
HPDF_UINT i;
|
||
|
|
||
|
HPDF_PTRACE ((" HPDF_TTFontDef_SetTagName\n"));
|
||
|
|
||
|
if (HPDF_StrLen (tag, HPDF_LIMIT_MAX_NAME_LEN) != HPDF_TTF_FONT_TAG_LEN)
|
||
|
return;
|
||
|
|
||
|
HPDF_MemCpy ((HPDF_BYTE *)attr->tag_name, (HPDF_BYTE *)tag, HPDF_TTF_FONT_TAG_LEN);
|
||
|
attr->tag_name[HPDF_TTF_FONT_TAG_LEN] = '+';
|
||
|
|
||
|
for (i = 0; i < HPDF_TTF_FONT_TAG_LEN + 1; i++) {
|
||
|
attr->tag_name2[i * 2] = 0x00;
|
||
|
attr->tag_name2[i * 2 + 1] = attr->tag_name[i];
|
||
|
}
|
||
|
|
||
|
HPDF_MemSet (buf, 0, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
HPDF_MemCpy ((HPDF_BYTE *)buf, (HPDF_BYTE *)attr->tag_name, HPDF_TTF_FONT_TAG_LEN + 1);
|
||
|
HPDF_MemCpy ((HPDF_BYTE *)buf + HPDF_TTF_FONT_TAG_LEN + 1, (HPDF_BYTE *)fontdef->base_font, HPDF_LIMIT_MAX_NAME_LEN - HPDF_TTF_FONT_TAG_LEN - 1);
|
||
|
|
||
|
HPDF_MemCpy ((HPDF_BYTE *)attr->base_font, (HPDF_BYTE *)buf, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
int
|
||
|
PdfTTFontDef::GetNameAttr(unsigned char* buf, HPDF_UINT name_id,
|
||
|
HPDF_UINT platform_id, HPDF_UINT lang_id, HPDF_UINT max_len)
|
||
|
|
||
|
|
||
|
*/
|
||
|
|
||
|
static HPDF_TTFTable*
|
||
|
FindTable (HPDF_FontDef fontdef,
|
||
|
const char *tag)
|
||
|
{
|
||
|
HPDF_TTFontDefAttr attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||
|
HPDF_TTFTable* tbl = attr->offset_tbl.table;
|
||
|
HPDF_UINT i;
|
||
|
|
||
|
for (i = 0; i < attr->offset_tbl.num_tables; i++, tbl++) {
|
||
|
if (HPDF_MemCmp ((HPDF_BYTE *)tbl->tag, (HPDF_BYTE *)tag, 4) == 0) {
|
||
|
HPDF_PTRACE((" FindTable find table[%c%c%c%c]\n",
|
||
|
tbl->tag[0], tbl->tag[1], tbl->tag[2], tbl->tag[3]));
|
||
|
return tbl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
UINT32Swap (HPDF_UINT32 *value)
|
||
|
{
|
||
|
HPDF_BYTE b[4];
|
||
|
|
||
|
HPDF_MemCpy (b, (HPDF_BYTE *)value, 4);
|
||
|
*value = (HPDF_UINT32)((HPDF_UINT32)b[0] << 24 |
|
||
|
(HPDF_UINT32)b[1] << 16 |
|
||
|
(HPDF_UINT32)b[2] << 8 |
|
||
|
(HPDF_UINT32)b[3]);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
UINT16Swap (HPDF_UINT16 *value)
|
||
|
{
|
||
|
HPDF_BYTE b[2];
|
||
|
|
||
|
HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
|
||
|
*value = (HPDF_UINT16)((HPDF_UINT16)b[0] << 8 | (HPDF_UINT16)b[1]);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
INT16Swap (HPDF_INT16 *value)
|
||
|
{
|
||
|
HPDF_BYTE b[2];
|
||
|
|
||
|
HPDF_MemCpy (b, (HPDF_BYTE *)value, 2);
|
||
|
*value = (HPDF_INT16)((HPDF_INT16)b[0] << 8 | (HPDF_INT16)b[1]);
|
||
|
}
|