3
Copyright (c) 2006-2007, BBR Inc. All rights reserved.
5
Permission is hereby granted, free of charge, to any person obtaining
6
a copy of this software and associated documentation files (the
7
"Software"), to deal in the Software without restriction, including
8
without limitation the rights to use, copy, modify, merge, publish,
9
distribute, sublicense, and/or sell copies of the Software, and to
10
permit persons to whom the Software is furnished to do so, subject to
11
the following conditions:
13
The above copyright notice and this permission notice shall be included
14
in all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32
#include <sys/types.h>
35
#ifdef HAVE_CPP_POPPLER_VERSION_H
36
#include "cpp/poppler-version.h"
43
#include "BuiltinFontTables.h"
45
#include "GlobalParams.h"
46
#include "PDFFTrueTypeFont.h"
48
#include "CharCodeToUnicode.h"
49
#include "P2PCharCodeToUnicode.h"
51
/* Size of CID (bytes) */
53
#define CIDTOGID_SIZE (1 << (8*CID_SIZE))
55
int P2PFontFile::nFontFiles = 0;
56
int P2PFontFile::fontFileListSize = 0;
57
P2PFontFile **P2PFontFile::fontFileList = 0;
58
char P2PFontFile::nextTag[7] = "AAAAA@";
60
#define FONT_FILE_LIST_INC 256
63
P2PCIDToGID::P2PCIDToGID(P2PFontFile *fontFileA, GBool wmodeA)
69
P2PCIDToGID::~P2PCIDToGID()
71
/* must not delete fontFile */
74
void P2PCIDToGID::output(P2POutputStream *str, XRef *xref)
76
P2PObj *lenObj = new P2PObj();
82
str->puts("<< /Length ");
83
lenObj->outputRef(str);
84
if (P2PDoc::options.fontCompress && str->canDeflate()) {
85
str->puts(" /Filter /FlateDecode ");
89
cp = str->getPosition(); /* start position */
90
if (P2PDoc::options.fontCompress) str->startDeflate();
91
fontFile->outputCIDToGID(wmode,str,xref);
92
if (P2PDoc::options.fontCompress) str->endDeflate();
93
len = str->getPosition() - cp; /* calculate length */
94
str->puts("\nendstream\n");
98
lenObj->outputBegin(str);
99
str->printf("%d\n",len);
100
lenObj->outputEnd(str);
103
char *P2PFontFile::getNextTag()
107
for (i = 5;i >= 0;i--) {
117
P2PFontFile *P2PFontFile::getFontFile(GooString *fileNameA,
118
GfxFont *fontA, GfxFontType typeA, int faceIndexA)
122
for (i = 0;i < nFontFiles;i++) {
123
if (fontFileList[i] != 0 && strcmp(fileNameA->getCString(),
124
fontFileList[i]->getFileName()->getCString()) == 0
125
&& faceIndexA == fontFileList[i]->faceIndex) {
126
return fontFileList[i];
129
if (nFontFiles >= fontFileListSize) {
130
int size = fontFileListSize + FONT_FILE_LIST_INC;
133
list = new P2PFontFile *[size];
134
for (i = 0;i < nFontFiles;i++) {
135
list[i] = fontFileList[i];
137
for (;i < size;i++) {
142
fontFileListSize = size;
144
fontFileList[nFontFiles] = new P2PFontFile(fileNameA,fontA,typeA,faceIndexA);
145
P2PXRef::put(fontFileList[nFontFiles]);
146
return fontFileList[nFontFiles++];
149
P2PFontFile::P2PFontFile(GooString *fileNameA, GfxFont *fontA,
150
GfxFontType typeA, int faceIndexA)
152
fileName = new GooString(fileNameA);
155
faceIndex = faceIndexA;
160
setSecondPhase(gTrue);
161
if (type == fontCIDType2) {
162
charRefTable = new unsigned char[CIDTOGID_SIZE/8];
163
memset(charRefTable,0,CIDTOGID_SIZE/8);
167
if (type == fontCIDType2 || type == fontTrueType) {
170
tfont.init(fileName->getCString(),faceIndex);
172
fn = tfont.getFontName();
174
if (type == fontCIDType2 && !P2PDoc::options.fontEmbeddingWhole) {
184
tagLen = strlen(tag);
185
fnLen = fn->getLength();
186
len = tagLen+1+fnLen;
187
/* use gmalloc because UGooString uses it */
188
p = static_cast<Unicode *>(gmalloc(len*sizeof(Unicode)));
190
for (i = 0;i < tagLen;i++) {
196
for (j = 0;j < fnLen;j++) {
199
fontName = new UGooString(p,len);
201
fontName = new UGooString(*fn);
207
P2PCIDToGID *P2PFontFile::getCIDToGID(GBool wmode)
217
*p = new P2PCIDToGID(this,wmode);
223
P2PFontFile::~P2PFontFile()
228
if (charRefTable != 0) delete[] charRefTable;
229
if (fontName != 0) delete fontName;
230
/* font is deleted by P2PFontDict, you must not delete it here */
231
/* must not delete CIDToGID */
234
GBool P2PFontFile::isIdentity()
236
/* alway false now */
240
void P2PFontFile::outputCIDToGID(GBool wmode, P2POutputStream *str, XRef *xref)
242
#define N_UCS_CANDIDATES 2
243
/* space characters */
244
static unsigned long spaces[] = {
245
0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
246
0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
249
static const char *adobe_cns1_cmaps[] = {
256
static const char *adobe_gb1_cmaps[] = {
263
static const char *adobe_japan1_cmaps[] = {
270
static const char *adobe_japan2_cmaps[] = {
277
static const char *adobe_korea1_cmaps[] = {
284
static struct CMapListEntry {
285
const char *collection;
286
const char *scriptTag;
287
const char *toUnicodeMap;
329
if (charRefTable == 0 || maxRefCID == 0) {
334
tfont.setupGSUB(0); /* reset GSUB */
336
const char **cmapName;
339
CharCodeToUnicode *octu;
341
GfxCIDFont *cidfont = static_cast<GfxCIDFont *>(font);
342
for (lp = CMapList;lp->collection != 0;lp++) {
343
if (strcmp(lp->collection,cidfont->getCollection()->getCString()) == 0) {
347
tumap = new Unicode[maxRefCID+1];
348
if (lp->collection != 0) {
349
GooString tname(lp->toUnicodeMap);
350
P2PCharCodeToUnicode *ctu;
351
if ((ctu = P2PCharCodeToUnicode::parseCMapFromFile(&tname,16)) != 0) {
353
for (cid = 0;cid <= maxRefCID ;cid++) {
357
len = ctu->mapToUnicode(cid,ucodes,4);
359
tumap[cid] = ucodes[0];
361
/* if not single character, ignore it */
367
vumap = new Unicode[maxRefCID+1];
368
memset(vumap,0,sizeof(Unicode)*(maxRefCID+1));
369
humap = new Unicode[(maxRefCID+1)*N_UCS_CANDIDATES];
370
memset(humap,0,sizeof(Unicode)*(maxRefCID+1)*N_UCS_CANDIDATES);
371
for (cmapName = lp->CMaps;*cmapName != 0;cmapName++) {
372
GooString cname(*cmapName);
374
if ((cMap = P2PCMap::parse(&cmapCache,cidfont->getCollection(),&cname))
376
if (cMap->getWMode()) {
377
cMap->setReverseMap(vumap,maxRefCID+1,1);
379
cMap->setReverseMap(humap,maxRefCID+1,N_UCS_CANDIDATES);
384
tfont.setupGSUB(lp->scriptTag);
386
p2pError(-1,const_cast<char *>("Unknown character collection %s\n"),
387
cidfont->getCollection()->getCString());
388
if ((octu = cidfont->getToUnicode()) != 0) {
390
for (cid = 0;cid <= maxRefCID ;cid++) {
391
#ifdef OLD_MAPTOUNICODE
394
humap[cid*N_UCS_CANDIDATES] = ucode;
396
Unicode *ucode = NULL;
398
humap[cid*N_UCS_CANDIDATES] = *ucode;
400
for (i = 1;i < N_UCS_CANDIDATES;i++) {
401
humap[cid*N_UCS_CANDIDATES+i] = 0;
408
for (i = 0;i <= maxRefCID;i++) {
413
if ((charRefTable[i/8] & (1 << (i & (8-1)))) == 0) {
414
/* not referenced CID */
421
for (j = 0;j < N_UCS_CANDIDATES
422
&& gid == 0 && (unicode = humap[i*N_UCS_CANDIDATES+j]) != 0;j++) {
423
gid = tfont.getGID(unicode,gFalse,
424
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
427
if (gid == 0 && vumap != 0) {
430
gid = tfont.getGID(unicode,gTrue,
431
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
432
if (gid == 0 && tumap != 0) {
433
if ((unicode = tumap[i]) != 0) {
434
gid = tfont.getGID(unicode,gTrue,
435
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
440
if (gid == 0 && tumap != 0) {
441
if ((unicode = tumap[i]) != 0) {
442
gid = tfont.getGID(unicode,gFalse,
443
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
447
/* special handling space characters */
450
if (humap != 0) unicode = humap[i];
452
/* check if code is space character , so map code to 0x0020 */
453
for (p = spaces;*p != 0;p++) {
456
gid = tfont.getGID(unicode,wmode,
457
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
466
should output big endian format.
468
str->putchar((gid >> 8) & 0xff);
469
str->putchar(gid & 0xff);
471
if (humap != 0) delete[] humap;
472
if (vumap != 0) delete[] vumap;
475
void P2PFontFile::output(P2POutputStream *str, XRef *xref)
480
P2PObj *lenObj = new P2PObj();
485
// fprintf(stderr,"INFO:Embedding font file from file %s\n",
486
// fileName->getCString());
488
/* output stream dictionary */
492
str->puts("/SubType /Type1C ");
493
/* should output Length1, Length2, Length3 */
496
str->puts("/SubType /CIDFontType0C ");
497
/* should output Length1, Length2, Length3 */
501
len1Obj = new P2PObj();
502
P2PXRef::put(len1Obj);
503
str->puts("/Length1 ");
504
len1Obj->outputRef(str);
508
/* should output Length1, Length2, Length3 */
513
P2PXRef::put(lenObj);
514
str->puts("/Length ");
515
lenObj->outputRef(str);
516
if (P2PDoc::options.fontCompress && str->canDeflate()) {
517
str->puts(" /Filter /FlateDecode ");
521
/* output stream body */
522
str->puts("stream\n");
523
if (P2PDoc::options.fontCompress) str->startDeflate();
524
cp = str->getPosition();
528
len1 = tfont.getLength();
536
if ((fd = open(fileName->getCString(),O_RDONLY)) < 0) {
537
p2pError(-1,const_cast<char *>("Cannot open FontFile:%s\n"),fileName->getCString());
540
while ((n = read(fd,buf,BUFSIZ)) > 0) {
555
if (P2PDoc::options.fontCompress) str->endDeflate();
556
len = str->getPosition()-cp; /* calculate length */
557
str->puts("\nendstream\n");
562
lenObj->outputBegin(str);
563
str->printf("%d\n",len);
564
lenObj->outputEnd(str);
568
len1Obj->outputBegin(str);
569
str->printf("%d\n",len1);
570
len1Obj->outputEnd(str);
574
P2PFontDescriptor::P2PFontDescriptor(Object *descriptorA,
575
GfxFont *fontA, GooString *fileName, GfxFontType typeA,
576
int faceIndexA, XRef *xref, int num, int gen) : P2PObject(num,gen)
578
descriptorA->copy(&descriptor);
579
fontFile = P2PFontFile::getFontFile(fileName,fontA,typeA,faceIndexA);
583
P2PFontDescriptor::~P2PFontDescriptor()
585
/* fontFile is pointed by multiple FontDescriptor,
586
so, don't delete it here. it is deleted by P2PXRef::clean() */
591
void P2PFontDescriptor::output(P2POutputStream *str, XRef *xref)
598
/* only indirect referenced */
607
keys[objsIndex] = "FontFile";
611
keys[objsIndex] = "FontFile2";
615
keys[objsIndex] = "FontFile3";
618
objs[objsIndex++] = fontFile;
619
fn = fontFile->getFontName();
623
p = fn->getCString();
624
fnobj.getObj()->initName(p);
625
keys[objsIndex] = "FontName";
626
objs[objsIndex++] = &fnobj;
630
P2POutput::outputDict(descriptor.getDict(),keys,objs,objsIndex,str,xref);
635
P2PCIDFontDict::P2PCIDFontDict(Object *fontDictA, GfxFont *fontA,
636
GfxFontType typeA, GfxFontType embeddedTypeA,
637
P2PFontDescriptor *fontDescriptorA, int num, int gen) : P2PObject(num,gen)
640
embeddedType = embeddedTypeA;
641
fontDictA->copy(&fontDict);
642
fontDescriptor = fontDescriptorA;
646
P2PCIDFontDict::~P2PCIDFontDict()
649
/* must not delete font, it is deleted by P2PFontDict::~P2PFonrDict(). */
652
void P2PCIDFontDict::output(P2POutputStream *str, XRef *xref)
657
P2PObj *subtypeObjp = 0;
660
if (embeddedType != type) {
663
subtypeObjp = new P2PObj();
664
switch (embeddedType) {
666
subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType0"));
669
subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType2"));
672
case fontUnknownType:
678
p2pError(-1,const_cast<char *>("P2PCIDFontDict: Illegal embedded font type"));
682
keys[objsIndex] = "Subtype";
683
objs[objsIndex++] = subtypeObjp;
685
if (embeddedType == fontCIDType2) {
686
/* Add CIDToGIDMap */
688
P2PFontFile *fontFile;
690
fontFile = fontDescriptor->getFontFile();
694
if (!(fontFile->isIdentity())) {
695
keys[objsIndex] = "CIDToGIDMap";
696
objp = fontFile->getCIDToGID(font->getWMode());
697
objs[objsIndex++] = objp;
699
fn = fontFile->getFontName();
701
char *p = fn->getCString();
702
fnobj.getObj()->initName(p);
703
keys[objsIndex] = "BaseFont";
704
objs[objsIndex++] = &fnobj;
711
P2POutput::outputDict(fontDict.getDict(),keys,objs,objsIndex,str,xref);
715
if (subtypeObjp != 0) {
720
P2PDescendantFontsWrapper::P2PDescendantFontsWrapper(P2PObject *elementA)
725
P2PDescendantFontsWrapper::~P2PDescendantFontsWrapper()
730
void P2PDescendantFontsWrapper::output(P2POutputStream *str, XRef *xref)
733
element->outputRef(str);
737
void P2PFontDict::doReadFontDescriptor(Object *dictObj,
738
GfxFontType type, const char *name, XRef *xref)
740
Dict *dict = dictObj->getDict();
746
if (dict->lookupNF(const_cast<char *>("FontDescriptor"),&obj) == 0
748
/* no FontDescriptor */
749
p2pError(-1,const_cast<char *>("Font:%s has no FontDescriptor entry.\n"),name);
753
/* not indirect reference is error */
754
p2pError(-1,const_cast<char *>("FontDescriptor entry of Font:%s is not indirect.\n"),name);
757
num = obj.getRefNum();
758
gen = obj.getRefGen();
759
if ((p = P2PObject::find(num,gen)) != 0) {
761
fontDescriptor = static_cast<P2PFontDescriptor *>(p);
762
embeddedType = fontDescriptor->getType();
766
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
770
fileName = globalParams->findSystemFontFile(font,&sftype,
773
p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
779
p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
790
embeddedType = fontCIDType2;
794
embeddedType = fontTrueType;
797
p2pError(-1, const_cast<char *>("Illegal type font\n"));
802
p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
807
GooString *fileName = font->getExtFontFile();
810
DisplayFontParam *dfp = 0;
811
/* look for substitute font */
813
if (font->getName()) {
814
dfp = globalParams->getDisplayFont(font);
815
/* a caller must not delete dfp */
818
p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
823
p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
833
embeddedType = fontCIDType2;
837
embeddedType = fontTrueType;
840
p2pError(-1, const_cast<char *>("Illegal type font\n"));
843
fileName = dfp->tt.fileName;
844
faceIndex = dfp->tt.faceIndex;
847
p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
856
xref->fetch(num,gen,&obj);
858
p2pError(-1, const_cast<char *>("Font Descriptor of Font:%s is not Dictionary. Not embedded\n"),name);
861
//fprintf(stderr, "DEBUG: Embedding Font fileName=%s for %s\n",fileName->getCString(),name);
862
fontDescriptor = new P2PFontDescriptor(&obj,font,fileName,
863
embeddedType, faceIndex, xref,num,gen);
864
P2PXRef::put(fontDescriptor);
865
fp = fontDescriptor->getFontFile();
868
ugs = fp->getFontName();
870
char *cs = ugs->getCString();
872
fprintf(stderr, "INFO: Embedded Font=%s, from fileName=%s for %s\n",
873
cs,fileName->getCString(),name);
878
fprintf(stderr, "INFO: Embedded Font from fileName=%s for %s\n",
879
fileName->getCString(),name);
886
void P2PFontDict::read8bitFontDescriptor(GfxFontType type, const char *name,
889
doReadFontDescriptor(&fontDict,type,name,xref);
892
void P2PFontDict::readCIDFontDescriptor(GfxFontType type, const char *name,
897
Dict *dict = fontDict.getDict();
898
int num = -1, gen = -1;
900
if (dict->lookup(const_cast<char *>("DescendantFonts"),&obj) == 0
902
/* no DescendantFonts */
903
p2pError(-1,const_cast<char *>("Font:%s has no DescendantFonts entry.\n"),name);
906
if (!obj.isArray() || obj.arrayGetNF(0,&descendant) == 0) {
907
/* illegal DescendantFonts */
908
p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
911
if (descendant.isRef()) {
912
num = descendant.getRefNum();
913
gen = descendant.getRefGen();
915
cidFontDict = static_cast<P2PCIDFontDict *>(
916
P2PObject::find(num,gen));
917
if (cidFontDict == 0) {
920
xref->fetch(num,gen,&descendant);
923
if (cidFontDict == 0) {
924
if (!descendant.isDict()) {
925
p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
928
doReadFontDescriptor(&descendant,type,name,xref);
929
cidFontDict = new P2PCIDFontDict(&descendant,font,type,
930
embeddedType,fontDescriptor,num,gen);
931
if (num > 0) P2PXRef::put(cidFontDict);
939
UGooString *P2PFontDict::getEmbeddingFontName()
941
P2PFontDescriptor *desc = fontDescriptor;
943
if (cidFontDict != 0) {
944
desc = cidFontDict->getFontDescriptor();
947
P2PFontFile *file = desc->getFontFile();
948
if (file != 0) return file->getFontName();
953
void P2PFontDict::output(P2POutputStream *str, XRef *xref)
962
fn = getEmbeddingFontName();
964
keys[nobjs] = "BaseFont";
965
char *p = fn->getCString();
966
fnobj.getObj()->initName(p);
967
objs[nobjs] = &fnobj;
971
/* output indirect referenced dictionary only */
973
if (cidFontDict != 0) {
974
cidFontDict->getNum(&num,&gen);
976
/* not indirect referenced, change it indirect referenced */
977
P2PDescendantFontsWrapper *wrap
978
= new P2PDescendantFontsWrapper(cidFontDict);
979
keys[nobjs] = "DescendantFonts";
983
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
985
P2PXRef::put(cidFontDict);
987
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
990
if (embeddedType != font->getType()) {
993
keys[nobjs] = "Subtype";
997
switch (embeddedType) {
999
obj.getObj()->initName(const_cast<char *>("TrueType"));
1000
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1003
obj.getObj()->initName(const_cast<char *>("Type1"));
1004
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1009
/* change is not needed */
1010
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1013
case fontUnknownType:
1016
p2pError(-1,const_cast<char *>("P2PFontDict: Illegal embedded font type"));
1021
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1028
P2PFontDict::P2PFontDict(Object *fontDictA, XRef *xref, int num, int gen)
1029
: P2PObject(num,gen)
1040
if (fontDictA == 0 || !fontDictA->isDict()) return;
1041
fontDictA->copy(&fontDict);
1043
dict = fontDict.getDict();
1044
dict->lookup(const_cast<char *>("BaseFont"),&name);
1045
if (!name.isName()) {
1046
p2pError(-1,const_cast<char *>("FontDictionary has not name type BaseFont entry\n"));
1049
/* font id and tag are not used */
1050
if ((font = GfxFont::makeFont(xref,const_cast<char *>(""),
1051
id,fontDict.getDict())) == 0) {
1052
p2pError(-1,const_cast<char *>("Can't get font %s. Not embedded\n"),
1056
embeddedType = type = font->getType();
1057
if (!font->getEmbeddedFontID(&embID)) {
1060
const char *namep = name.getName();
1062
//fprintf(stderr,"DEBUG:%s is not embedded\n",name.getName());
1064
/* check builtin fonts */
1065
for (i = 0;i < nBuiltinFonts;i++) {
1066
if (strcmp(namep, builtinFonts[i].name) == 0) {
1068
/* don't embed built in font */
1069
fprintf(stderr,"INFO:%s is builtin font. not embedded.\n",namep);
1074
if (!P2PDoc::options.fontEmbeddingPreLoad) {
1075
/* check pre-loaded fonts */
1076
for (i = 0;i < P2PDoc::options.numPreFonts;i++) {
1077
if (strcmp(namep, P2PDoc::options.preFonts[i]) == 0) {
1078
/* pre-loaded font */
1079
/* don't embed pre-loaded font */
1080
fprintf(stderr,"INFO:%s is pre-loaded font. not embedded.\n",namep);
1088
/* Type3 font is always embedded */
1092
case fontUnknownType:
1096
case fontTrueTypeOT:
1098
read8bitFontDescriptor(type,name.getName(),xref);
1103
case fontCIDType0COT:
1104
case fontCIDType2OT:
1106
readCIDFontDescriptor(type,name.getName(),xref);
1116
P2PFontDict::~P2PFontDict()
1121
/* fontDescriptor is pointed by multiple FontDict,
1122
so, don't delete it here. it is deleted by P2PXRef::clean() */
1123
/* cidFontDict is pointed by multiple FontDict,
1124
so, don't delete it here. it is deleted by P2PXRef::clean() */
1129
void P2PFontDict::showText(GooString *s)
1134
#ifdef OLD_MAPTOUNICODE
1141
double dx,dy,originX,originY;
1142
P2PFontFile *fontFile;
1144
if (font == 0 || fontDescriptor == 0) return;
1145
if ((fontFile = fontDescriptor->getFontFile()) == 0) return;
1146
p = s->getCString();
1147
len = s->getLength();
1149
#ifdef OLD_MAPTOUNICODE
1150
n = font->getNextChar(p,len,&code,u,(sizeof(u)/sizeof(Unicode)),&uLen,
1151
&dx,&dy,&originX,&originY);
1153
n = font->getNextChar(p,len,&code,&u,&uLen,
1154
&dx,&dy,&originX,&originY);
1156
code &= (CIDTOGID_SIZE-1); /* mask */
1157
fontFile->refChar(code);
1163
P2PFontResource::P2PFontResource()
1173
P2PFontResource::~P2PFontResource()
1178
for (i = 0;i < nDicts;i++) {
1183
if (fontDicts != 0) {
1184
for (i = 0;i < nDicts;i++) {
1185
if (fontDicts[i] != 0) {
1188
fontDicts[i]->getNum(&num,&gen);
1190
/* Not indirect referenced FontDict */
1191
/* output it as normal dictionary */
1192
/* so, not needed any more */
1193
delete fontDicts[i];
1195
/* indirect referenced FontDict is registered in P2PXRef */
1196
/* So, should not delete it. */
1201
if (extGStateKeys != 0) {
1202
for (i = 0;i < nExtGState;i++) {
1203
delete extGStateKeys[i];
1205
delete[] extGStateKeys;
1207
if (extGStateFonts != 0) {
1208
/* indirect referenced FontDict is registered in P2PXRef */
1209
/* So, should not delete it. */
1210
delete[] extGStateFonts;
1214
void P2PFontResource::setup(P2PResources *resources, XRef *xref)
1216
doSetup(resources->getFontResource(),xref);
1217
doSetupExtGState(resources->getExtGState(),xref);
1220
void P2PFontResource::setup(Dict *resources, XRef *xref)
1224
if (resources == 0) return;
1225
resources->lookup(const_cast<char *>("Font"),&obj);
1227
doSetup(obj.getDict(),xref);
1230
resources->lookup(const_cast<char *>("ExtGState"),&obj);
1232
doSetupExtGState(obj.getDict(),xref);
1237
void P2PFontResource::doSetup(Dict *fontResource, XRef *xref)
1242
if (fontResource == 0) return;
1243
nDicts = fontResource->getLength();
1244
keys = new UGooString *[nDicts];
1245
fontDicts = new P2PFontDict *[nDicts];
1246
for (i = 0;i < nDicts;i++) {
1248
#ifdef HAVE_UGOOSTRING_H
1249
UGooString *key = fontResource->getKey(i);
1251
UGooString *key = new UGooString(fontResource->getKey(i));
1254
fontResource->getValNF(i,&obj);
1256
int num = obj.getRefNum();
1257
int gen = obj.getRefGen();
1258
if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen))) == 0) {
1261
xref->fetch(num,gen,&fobj);
1262
if (fobj.isDict()) {
1263
p = new P2PFontDict(&fobj,xref,num,gen);
1264
/* register this in P2PXRef to output later */
1271
keys[i] = new UGooString(*key);
1273
} else if (obj.isDict()) {
1274
keys[i] = new UGooString(*key);
1275
fontDicts[i] = new P2PFontDict(&obj,xref);
1276
P2PXRef::put(fontDicts[i]);
1285
void P2PFontResource::doSetupExtGState(Dict *extGState, XRef *xref)
1290
if (extGState == 0) return;
1291
nExtGState = extGState->getLength();
1292
extGStateKeys = new UGooString *[nExtGState];
1293
extGStateFonts = new P2PFontDict *[nExtGState];
1294
for (i = 0;i < nExtGState;i++) {
1296
#ifdef HAVE_UGOOSTRING_H
1297
UGooString *key = extGState->getKey(i);
1299
char *key = extGState->getKey(i);
1302
extGStateKeys[i] = 0;
1303
extGStateFonts[i] = 0;
1304
extGState->getVal(i,&gstateObj);
1305
if (gstateObj.isDict()) {
1306
Object fontArrayObj;
1307
Dict *gstate = gstateObj.getDict();
1309
if (gstate->lookup(const_cast<char *>("Font"),&fontArrayObj) != 0) {
1310
if (fontArrayObj.isArray() && fontArrayObj.arrayGetLength() > 0) {
1313
if (fontArrayObj.arrayGetNF(0,&fontRefObj) && fontRefObj.isRef()) {
1314
int num = fontRefObj.getRefNum();
1315
int gen = fontRefObj.getRefGen();
1317
if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen)))
1320
xref->fetch(num,gen,&fontObj);
1321
if (fontObj.isDict()) {
1322
p = new P2PFontDict(&fontObj,xref,num,gen);
1323
/* register this in P2PXRef to output later */
1331
#ifdef HAVE_UGOOSTRING_H
1332
extGStateKeys[i] = new UGooString(*key);
1334
extGStateKeys[i] = new UGooString(key);
1336
extGStateFonts[i] = p;
1338
fontArrayObj.free();
1344
void P2PFontResource::output(P2POutputStream *str, XRef *xref)
1349
for (i = 0;i < nDicts;i++) {
1350
P2POutput::outputName(keys[i]->getCString(),str);
1352
fontDicts[i]->outputRef(str);
1358
P2PFontDict *P2PFontResource::lookup(const UGooString &key)
1362
for (i = 0;i < nDicts;i++) {
1363
if (key.cmp(keys[i]) == 0) {
1364
return fontDicts[i];
1370
P2PFontDict *P2PFontResource::lookupExtGState(const UGooString &key)
1374
for (i = 0;i < nExtGState;i++) {
1375
if (extGStateKeys != 0 && key.cmp(extGStateKeys[i]) == 0) {
1376
return extGStateFonts[i];