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>
40
#include "BuiltinFontTables.h"
42
#include "GlobalParams.h"
43
#include "PDFFTrueTypeFont.h"
45
#include "CharCodeToUnicode.h"
46
#include "P2PCharCodeToUnicode.h"
48
/* Size of CID (bytes) */
50
#define CIDTOGID_SIZE (1 << (8*CID_SIZE))
52
int P2PFontFile::nFontFiles = 0;
53
int P2PFontFile::fontFileListSize = 0;
54
P2PFontFile **P2PFontFile::fontFileList = 0;
55
char P2PFontFile::nextTag[7] = "AAAAA@";
57
#define FONT_FILE_LIST_INC 256
60
P2PCIDToGID::P2PCIDToGID(P2PFontFile *fontFileA, GBool wmodeA)
66
P2PCIDToGID::~P2PCIDToGID()
68
/* must not delete fontFile */
71
void P2PCIDToGID::output(P2POutputStream *str, XRef *xref)
73
P2PObj *lenObj = new P2PObj();
79
str->puts("<< /Length ");
80
lenObj->outputRef(str);
81
if (P2PDoc::options.fontCompress && str->canDeflate()) {
82
str->puts(" /Filter /FlateDecode ");
86
cp = str->getPosition(); /* start position */
87
if (P2PDoc::options.fontCompress) str->startDeflate();
88
fontFile->outputCIDToGID(wmode,str,xref);
89
if (P2PDoc::options.fontCompress) str->endDeflate();
90
len = str->getPosition() - cp; /* calculate length */
91
str->puts("\nendstream\n");
95
lenObj->outputBegin(str);
96
str->printf("%d\n",len);
97
lenObj->outputEnd(str);
100
char *P2PFontFile::getNextTag()
104
for (i = 5;i >= 0;i--) {
114
P2PFontFile *P2PFontFile::getFontFile(GooString *fileNameA,
115
GfxFont *fontA, GfxFontType typeA, int faceIndexA)
119
for (i = 0;i < nFontFiles;i++) {
120
if (fontFileList[i] != 0 && strcmp(fileNameA->getCString(),
121
fontFileList[i]->getFileName()->getCString()) == 0
122
&& faceIndexA == fontFileList[i]->faceIndex) {
123
return fontFileList[i];
126
if (nFontFiles >= fontFileListSize) {
127
int size = fontFileListSize + FONT_FILE_LIST_INC;
130
list = new P2PFontFile *[size];
131
for (i = 0;i < nFontFiles;i++) {
132
list[i] = fontFileList[i];
134
for (;i < size;i++) {
139
fontFileListSize = size;
141
fontFileList[nFontFiles] = new P2PFontFile(fileNameA,fontA,typeA,faceIndexA);
142
P2PXRef::put(fontFileList[nFontFiles]);
143
return fontFileList[nFontFiles++];
146
P2PFontFile::P2PFontFile(GooString *fileNameA, GfxFont *fontA,
147
GfxFontType typeA, int faceIndexA)
149
fileName = new GooString(fileNameA);
152
faceIndex = faceIndexA;
157
setSecondPhase(gTrue);
158
if (type == fontCIDType2) {
159
charRefTable = new unsigned char[CIDTOGID_SIZE/8];
160
memset(charRefTable,0,CIDTOGID_SIZE/8);
164
if (type == fontCIDType2 || type == fontTrueType) {
167
tfont.init(fileName->getCString(),faceIndex);
169
fn = tfont.getFontName();
171
if (type == fontCIDType2 && !P2PDoc::options.fontEmbeddingWhole) {
181
tagLen = strlen(tag);
182
fnLen = fn->getLength();
183
len = tagLen+1+fnLen;
184
/* use gmalloc because UGooString uses it */
185
p = static_cast<Unicode *>(gmalloc(len*sizeof(Unicode)));
187
for (i = 0;i < tagLen;i++) {
193
for (j = 0;j < fnLen;j++) {
196
fontName = new UGooString(p,len);
198
fontName = new UGooString(*fn);
204
P2PCIDToGID *P2PFontFile::getCIDToGID(GBool wmode)
214
*p = new P2PCIDToGID(this,wmode);
220
P2PFontFile::~P2PFontFile()
225
if (charRefTable != 0) delete[] charRefTable;
226
if (fontName != 0) delete fontName;
227
/* font is deleted by P2PFontDict, you must not delete it here */
228
/* must not delete CIDToGID */
231
GBool P2PFontFile::isIdentity()
233
/* alway false now */
237
void P2PFontFile::outputCIDToGID(GBool wmode, P2POutputStream *str, XRef *xref)
239
#define N_UCS_CANDIDATES 2
240
/* space characters */
241
static unsigned long spaces[] = {
242
0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
243
0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
246
static const char *adobe_cns1_cmaps[] = {
253
static const char *adobe_gb1_cmaps[] = {
260
static const char *adobe_japan1_cmaps[] = {
267
static const char *adobe_japan2_cmaps[] = {
274
static const char *adobe_korea1_cmaps[] = {
281
static struct CMapListEntry {
282
const char *collection;
283
const char *scriptTag;
284
const char *toUnicodeMap;
326
if (charRefTable == 0 || maxRefCID == 0) {
331
tfont.setupGSUB(0); /* reset GSUB */
333
const char **cmapName;
336
CharCodeToUnicode *octu;
338
GfxCIDFont *cidfont = static_cast<GfxCIDFont *>(font);
339
for (lp = CMapList;lp->collection != 0;lp++) {
340
if (strcmp(lp->collection,cidfont->getCollection()->getCString()) == 0) {
344
tumap = new Unicode[maxRefCID+1];
345
if (lp->collection != 0) {
346
GooString tname(lp->toUnicodeMap);
347
P2PCharCodeToUnicode *ctu;
348
if ((ctu = P2PCharCodeToUnicode::parseCMapFromFile(&tname,16)) != 0) {
350
for (cid = 0;cid <= maxRefCID ;cid++) {
354
len = ctu->mapToUnicode(cid,ucodes,4);
356
tumap[cid] = ucodes[0];
358
/* if not single character, ignore it */
364
vumap = new Unicode[maxRefCID+1];
365
memset(vumap,0,sizeof(Unicode)*(maxRefCID+1));
366
humap = new Unicode[(maxRefCID+1)*N_UCS_CANDIDATES];
367
memset(humap,0,sizeof(Unicode)*(maxRefCID+1)*N_UCS_CANDIDATES);
368
for (cmapName = lp->CMaps;*cmapName != 0;cmapName++) {
369
GooString cname(*cmapName);
371
if ((cMap = P2PCMap::parse(&cmapCache,cidfont->getCollection(),&cname))
373
if (cMap->getWMode()) {
374
cMap->setReverseMap(vumap,maxRefCID+1,1);
376
cMap->setReverseMap(humap,maxRefCID+1,N_UCS_CANDIDATES);
381
tfont.setupGSUB(lp->scriptTag);
383
p2pError(-1,const_cast<char *>("Unknown character collection %s\n"),
384
cidfont->getCollection()->getCString());
385
if ((octu = cidfont->getToUnicode()) != 0) {
387
for (cid = 0;cid <= maxRefCID ;cid++) {
388
#ifdef OLD_MAPTOUNICODE
391
humap[cid*N_UCS_CANDIDATES] = ucode;
393
Unicode *ucode = NULL;
395
humap[cid*N_UCS_CANDIDATES] = *ucode;
397
for (i = 1;i < N_UCS_CANDIDATES;i++) {
398
humap[cid*N_UCS_CANDIDATES+i] = 0;
405
for (i = 0;i <= maxRefCID;i++) {
410
if ((charRefTable[i/8] & (1 << (i & (8-1)))) == 0) {
411
/* not referenced CID */
418
for (j = 0;j < N_UCS_CANDIDATES
419
&& gid == 0 && (unicode = humap[i*N_UCS_CANDIDATES+j]) != 0;j++) {
420
gid = tfont.getGID(unicode,gFalse,
421
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
424
if (gid == 0 && vumap != 0) {
427
gid = tfont.getGID(unicode,gTrue,
428
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
429
if (gid == 0 && tumap != 0) {
430
if ((unicode = tumap[i]) != 0) {
431
gid = tfont.getGID(unicode,gTrue,
432
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
437
if (gid == 0 && tumap != 0) {
438
if ((unicode = tumap[i]) != 0) {
439
gid = tfont.getGID(unicode,gFalse,
440
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
444
/* special handling space characters */
447
if (humap != 0) unicode = humap[i];
449
/* check if code is space character , so map code to 0x0020 */
450
for (p = spaces;*p != 0;p++) {
453
gid = tfont.getGID(unicode,wmode,
454
P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
463
should output big endian format.
465
str->putchar((gid >> 8) & 0xff);
466
str->putchar(gid & 0xff);
468
if (humap != 0) delete[] humap;
469
if (vumap != 0) delete[] vumap;
472
void P2PFontFile::output(P2POutputStream *str, XRef *xref)
477
P2PObj *lenObj = new P2PObj();
482
// fprintf(stderr,"INFO:Embedding font file from file %s\n",
483
// fileName->getCString());
485
/* output stream dictionary */
489
str->puts("/SubType /Type1C ");
490
/* should output Length1, Length2, Length3 */
493
str->puts("/SubType /CIDFontType0C ");
494
/* should output Length1, Length2, Length3 */
498
len1Obj = new P2PObj();
499
P2PXRef::put(len1Obj);
500
str->puts("/Length1 ");
501
len1Obj->outputRef(str);
505
/* should output Length1, Length2, Length3 */
510
P2PXRef::put(lenObj);
511
str->puts("/Length ");
512
lenObj->outputRef(str);
513
if (P2PDoc::options.fontCompress && str->canDeflate()) {
514
str->puts(" /Filter /FlateDecode ");
518
/* output stream body */
519
str->puts("stream\n");
520
if (P2PDoc::options.fontCompress) str->startDeflate();
521
cp = str->getPosition();
525
len1 = tfont.getLength();
533
if ((fd = open(fileName->getCString(),O_RDONLY)) < 0) {
534
p2pError(-1,const_cast<char *>("Cannot open FontFile:%s\n"),fileName->getCString());
537
while ((n = read(fd,buf,BUFSIZ)) > 0) {
552
if (P2PDoc::options.fontCompress) str->endDeflate();
553
len = str->getPosition()-cp; /* calculate length */
554
str->puts("\nendstream\n");
559
lenObj->outputBegin(str);
560
str->printf("%d\n",len);
561
lenObj->outputEnd(str);
565
len1Obj->outputBegin(str);
566
str->printf("%d\n",len1);
567
len1Obj->outputEnd(str);
571
P2PFontDescriptor::P2PFontDescriptor(Object *descriptorA,
572
GfxFont *fontA, GooString *fileName, GfxFontType typeA,
573
int faceIndexA, XRef *xref, int num, int gen) : P2PObject(num,gen)
575
descriptorA->copy(&descriptor);
576
fontFile = P2PFontFile::getFontFile(fileName,fontA,typeA,faceIndexA);
580
P2PFontDescriptor::~P2PFontDescriptor()
582
/* fontFile is pointed by multiple FontDescriptor,
583
so, don't delete it here. it is deleted by P2PXRef::clean() */
588
void P2PFontDescriptor::output(P2POutputStream *str, XRef *xref)
595
/* only indirect referenced */
604
keys[objsIndex] = "FontFile";
608
keys[objsIndex] = "FontFile2";
612
keys[objsIndex] = "FontFile3";
615
objs[objsIndex++] = fontFile;
616
fn = fontFile->getFontName();
620
p = fn->getCString();
621
fnobj.getObj()->initName(p);
622
keys[objsIndex] = "FontName";
623
objs[objsIndex++] = &fnobj;
627
P2POutput::outputDict(descriptor.getDict(),keys,objs,objsIndex,str,xref);
632
P2PCIDFontDict::P2PCIDFontDict(Object *fontDictA, GfxFont *fontA,
633
GfxFontType typeA, GfxFontType embeddedTypeA,
634
P2PFontDescriptor *fontDescriptorA, int num, int gen) : P2PObject(num,gen)
637
embeddedType = embeddedTypeA;
638
fontDictA->copy(&fontDict);
639
fontDescriptor = fontDescriptorA;
643
P2PCIDFontDict::~P2PCIDFontDict()
646
/* must not delete font, it is deleted by P2PFontDict::~P2PFonrDict(). */
649
void P2PCIDFontDict::output(P2POutputStream *str, XRef *xref)
654
P2PObj *subtypeObjp = 0;
657
if (embeddedType != type) {
660
subtypeObjp = new P2PObj();
661
switch (embeddedType) {
663
subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType0"));
666
subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType2"));
669
case fontUnknownType:
675
p2pError(-1,const_cast<char *>("P2PCIDFontDict: Illegal embedded font type"));
679
keys[objsIndex] = "Subtype";
680
objs[objsIndex++] = subtypeObjp;
682
if (embeddedType == fontCIDType2) {
683
/* Add CIDToGIDMap */
685
P2PFontFile *fontFile;
687
fontFile = fontDescriptor->getFontFile();
691
if (!(fontFile->isIdentity())) {
692
keys[objsIndex] = "CIDToGIDMap";
693
objp = fontFile->getCIDToGID(font->getWMode());
694
objs[objsIndex++] = objp;
696
fn = fontFile->getFontName();
698
char *p = fn->getCString();
699
fnobj.getObj()->initName(p);
700
keys[objsIndex] = "BaseFont";
701
objs[objsIndex++] = &fnobj;
708
P2POutput::outputDict(fontDict.getDict(),keys,objs,objsIndex,str,xref);
712
if (subtypeObjp != 0) {
717
P2PDescendantFontsWrapper::P2PDescendantFontsWrapper(P2PObject *elementA)
722
P2PDescendantFontsWrapper::~P2PDescendantFontsWrapper()
727
void P2PDescendantFontsWrapper::output(P2POutputStream *str, XRef *xref)
730
element->outputRef(str);
734
void P2PFontDict::doReadFontDescriptor(Object *dictObj,
735
GfxFontType type, const char *name, XRef *xref)
737
Dict *dict = dictObj->getDict();
743
if (dict->lookupNF(const_cast<char *>("FontDescriptor"),&obj) == 0
745
/* no FontDescriptor */
746
p2pError(-1,const_cast<char *>("Font:%s has no FontDescriptor entry.\n"),name);
750
/* not indirect reference is error */
751
p2pError(-1,const_cast<char *>("FontDescriptor entry of Font:%s is not indirect.\n"),name);
754
num = obj.getRefNum();
755
gen = obj.getRefGen();
756
if ((p = P2PObject::find(num,gen)) != 0) {
758
fontDescriptor = static_cast<P2PFontDescriptor *>(p);
759
embeddedType = fontDescriptor->getType();
763
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
767
fileName = globalParams->findSystemFontFile(font,&sftype,
770
p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
776
p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
787
embeddedType = fontCIDType2;
791
embeddedType = fontTrueType;
794
p2pError(-1, const_cast<char *>("Illegal type font\n"));
799
p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
804
GooString *fileName = font->getExtFontFile();
807
DisplayFontParam *dfp = 0;
808
/* look for substitute font */
810
if (font->getName()) {
811
dfp = globalParams->getDisplayFont(font);
812
/* a caller must not delete dfp */
815
p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
820
p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
830
embeddedType = fontCIDType2;
834
embeddedType = fontTrueType;
837
p2pError(-1, const_cast<char *>("Illegal type font\n"));
840
fileName = dfp->tt.fileName;
841
faceIndex = dfp->tt.faceIndex;
844
p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
853
xref->fetch(num,gen,&obj);
855
p2pError(-1, const_cast<char *>("Font Descriptor of Font:%s is not Dictionary. Not embedded\n"),name);
858
//fprintf(stderr, "DEBUG: Embedding Font fileName=%s for %s\n",fileName->getCString(),name);
859
fontDescriptor = new P2PFontDescriptor(&obj,font,fileName,
860
embeddedType, faceIndex, xref,num,gen);
861
P2PXRef::put(fontDescriptor);
862
fp = fontDescriptor->getFontFile();
865
ugs = fp->getFontName();
867
char *cs = ugs->getCString();
869
fprintf(stderr, "INFO: Embedded Font=%s, from fileName=%s for %s\n",
870
cs,fileName->getCString(),name);
875
fprintf(stderr, "INFO: Embedded Font from fileName=%s for %s\n",
876
fileName->getCString(),name);
883
void P2PFontDict::read8bitFontDescriptor(GfxFontType type, const char *name,
886
doReadFontDescriptor(&fontDict,type,name,xref);
889
void P2PFontDict::readCIDFontDescriptor(GfxFontType type, const char *name,
894
Dict *dict = fontDict.getDict();
895
int num = -1, gen = -1;
897
if (dict->lookup(const_cast<char *>("DescendantFonts"),&obj) == 0
899
/* no DescendantFonts */
900
p2pError(-1,const_cast<char *>("Font:%s has no DescendantFonts entry.\n"),name);
903
if (!obj.isArray() || obj.arrayGetNF(0,&descendant) == 0) {
904
/* illegal DescendantFonts */
905
p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
908
if (descendant.isRef()) {
909
num = descendant.getRefNum();
910
gen = descendant.getRefGen();
912
cidFontDict = static_cast<P2PCIDFontDict *>(
913
P2PObject::find(num,gen));
914
if (cidFontDict == 0) {
917
xref->fetch(num,gen,&descendant);
920
if (cidFontDict == 0) {
921
if (!descendant.isDict()) {
922
p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
925
doReadFontDescriptor(&descendant,type,name,xref);
926
cidFontDict = new P2PCIDFontDict(&descendant,font,type,
927
embeddedType,fontDescriptor,num,gen);
928
if (num > 0) P2PXRef::put(cidFontDict);
936
UGooString *P2PFontDict::getEmbeddingFontName()
938
P2PFontDescriptor *desc = fontDescriptor;
940
if (cidFontDict != 0) {
941
desc = cidFontDict->getFontDescriptor();
944
P2PFontFile *file = desc->getFontFile();
945
if (file != 0) return file->getFontName();
950
void P2PFontDict::output(P2POutputStream *str, XRef *xref)
959
fn = getEmbeddingFontName();
961
keys[nobjs] = "BaseFont";
962
char *p = fn->getCString();
963
fnobj.getObj()->initName(p);
964
objs[nobjs] = &fnobj;
968
/* output indirect referenced dictionary only */
970
if (cidFontDict != 0) {
971
cidFontDict->getNum(&num,&gen);
973
/* not indirect referenced, change it indirect referenced */
974
P2PDescendantFontsWrapper *wrap
975
= new P2PDescendantFontsWrapper(cidFontDict);
976
keys[nobjs] = "DescendantFonts";
980
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
982
P2PXRef::put(cidFontDict);
984
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
987
if (embeddedType != font->getType()) {
990
keys[nobjs] = "Subtype";
994
switch (embeddedType) {
996
obj.getObj()->initName(const_cast<char *>("TrueType"));
997
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1000
obj.getObj()->initName(const_cast<char *>("Type1"));
1001
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1006
/* change is not needed */
1007
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1010
case fontUnknownType:
1013
p2pError(-1,const_cast<char *>("P2PFontDict: Illegal embedded font type"));
1018
P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1025
P2PFontDict::P2PFontDict(Object *fontDictA, XRef *xref, int num, int gen)
1026
: P2PObject(num,gen)
1037
if (fontDictA == 0 || !fontDictA->isDict()) return;
1038
fontDictA->copy(&fontDict);
1040
dict = fontDict.getDict();
1041
dict->lookup(const_cast<char *>("BaseFont"),&name);
1042
if (!name.isName()) {
1043
p2pError(-1,const_cast<char *>("FontDictionary has not name type BaseFont entry\n"));
1046
/* font id and tag are not used */
1047
if ((font = GfxFont::makeFont(xref,const_cast<char *>(""),
1048
id,fontDict.getDict())) == 0) {
1049
p2pError(-1,const_cast<char *>("Can't get font %s. Not embedded\n"),
1053
embeddedType = type = font->getType();
1054
if (!font->getEmbeddedFontID(&embID)) {
1057
const char *namep = name.getName();
1059
//fprintf(stderr,"DEBUG:%s is not embedded\n",name.getName());
1061
/* check builtin fonts */
1062
for (i = 0;i < nBuiltinFonts;i++) {
1063
if (strcmp(namep, builtinFonts[i].name) == 0) {
1065
/* don't embed built in font */
1066
fprintf(stderr,"INFO:%s is builtin font. not embedded.\n",namep);
1071
if (!P2PDoc::options.fontEmbeddingPreLoad) {
1072
/* check pre-loaded fonts */
1073
for (i = 0;i < P2PDoc::options.numPreFonts;i++) {
1074
if (strcmp(namep, P2PDoc::options.preFonts[i]) == 0) {
1075
/* pre-loaded font */
1076
/* don't embed pre-loaded font */
1077
fprintf(stderr,"INFO:%s is pre-loaded font. not embedded.\n",namep);
1085
/* Type3 font is always embedded */
1089
case fontUnknownType:
1092
#ifdef FONTTYPE_ENUM2
1094
case fontTrueTypeOT:
1097
read8bitFontDescriptor(type,name.getName(),xref);
1102
#ifdef FONTTYPE_ENUM2
1103
case fontCIDType0COT:
1104
case fontCIDType2OT:
1107
readCIDFontDescriptor(type,name.getName(),xref);
1117
P2PFontDict::~P2PFontDict()
1122
/* fontDescriptor is pointed by multiple FontDict,
1123
so, don't delete it here. it is deleted by P2PXRef::clean() */
1124
/* cidFontDict is pointed by multiple FontDict,
1125
so, don't delete it here. it is deleted by P2PXRef::clean() */
1130
void P2PFontDict::showText(GooString *s)
1135
#ifdef OLD_MAPTOUNICODE
1142
double dx,dy,originX,originY;
1143
P2PFontFile *fontFile;
1145
if (font == 0 || fontDescriptor == 0) return;
1146
if ((fontFile = fontDescriptor->getFontFile()) == 0) return;
1147
p = s->getCString();
1148
len = s->getLength();
1150
#ifdef OLD_MAPTOUNICODE
1151
n = font->getNextChar(p,len,&code,u,(sizeof(u)/sizeof(Unicode)),&uLen,
1152
&dx,&dy,&originX,&originY);
1154
n = font->getNextChar(p,len,&code,&u,&uLen,
1155
&dx,&dy,&originX,&originY);
1157
code &= (CIDTOGID_SIZE-1); /* mask */
1158
fontFile->refChar(code);
1164
P2PFontResource::P2PFontResource()
1174
P2PFontResource::~P2PFontResource()
1179
for (i = 0;i < nDicts;i++) {
1184
if (fontDicts != 0) {
1185
for (i = 0;i < nDicts;i++) {
1186
if (fontDicts[i] != 0) {
1189
fontDicts[i]->getNum(&num,&gen);
1191
/* Not indirect referenced FontDict */
1192
/* output it as normal dictionary */
1193
/* so, not needed any more */
1194
delete fontDicts[i];
1196
/* indirect referenced FontDict is registered in P2PXRef */
1197
/* So, should not delete it. */
1202
if (extGStateKeys != 0) {
1203
for (i = 0;i < nExtGState;i++) {
1204
delete extGStateKeys[i];
1206
delete[] extGStateKeys;
1208
if (extGStateFonts != 0) {
1209
/* indirect referenced FontDict is registered in P2PXRef */
1210
/* So, should not delete it. */
1211
delete[] extGStateFonts;
1215
void P2PFontResource::setup(P2PResources *resources, XRef *xref)
1217
doSetup(resources->getFontResource(),xref);
1218
doSetupExtGState(resources->getExtGState(),xref);
1221
void P2PFontResource::setup(Dict *resources, XRef *xref)
1225
if (resources == 0) return;
1226
resources->lookup(const_cast<char *>("Font"),&obj);
1228
doSetup(obj.getDict(),xref);
1231
resources->lookup(const_cast<char *>("ExtGState"),&obj);
1233
doSetupExtGState(obj.getDict(),xref);
1238
void P2PFontResource::doSetup(Dict *fontResource, XRef *xref)
1243
if (fontResource == 0) return;
1244
nDicts = fontResource->getLength();
1245
keys = new UGooString *[nDicts];
1246
fontDicts = new P2PFontDict *[nDicts];
1247
for (i = 0;i < nDicts;i++) {
1249
#ifdef HAVE_UGOOSTRING_H
1250
UGooString *key = fontResource->getKey(i);
1252
UGooString *key = new UGooString(fontResource->getKey(i));
1255
fontResource->getValNF(i,&obj);
1257
int num = obj.getRefNum();
1258
int gen = obj.getRefGen();
1259
if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen))) == 0) {
1262
xref->fetch(num,gen,&fobj);
1263
if (fobj.isDict()) {
1264
p = new P2PFontDict(&fobj,xref,num,gen);
1265
/* register this in P2PXRef to output later */
1272
keys[i] = new UGooString(*key);
1274
} else if (obj.isDict()) {
1275
keys[i] = new UGooString(*key);
1276
fontDicts[i] = new P2PFontDict(&obj,xref);
1277
P2PXRef::put(fontDicts[i]);
1286
void P2PFontResource::doSetupExtGState(Dict *extGState, XRef *xref)
1291
if (extGState == 0) return;
1292
nExtGState = extGState->getLength();
1293
extGStateKeys = new UGooString *[nExtGState];
1294
extGStateFonts = new P2PFontDict *[nExtGState];
1295
for (i = 0;i < nExtGState;i++) {
1297
#ifdef HAVE_UGOOSTRING_H
1298
UGooString *key = extGState->getKey(i);
1300
char *key = extGState->getKey(i);
1303
extGStateKeys[i] = 0;
1304
extGStateFonts[i] = 0;
1305
extGState->getVal(i,&gstateObj);
1306
if (gstateObj.isDict()) {
1307
Object fontArrayObj;
1308
Dict *gstate = gstateObj.getDict();
1310
if (gstate->lookup(const_cast<char *>("Font"),&fontArrayObj) != 0) {
1311
if (fontArrayObj.isArray() && fontArrayObj.arrayGetLength() > 0) {
1314
if (fontArrayObj.arrayGetNF(0,&fontRefObj) && fontRefObj.isRef()) {
1315
int num = fontRefObj.getRefNum();
1316
int gen = fontRefObj.getRefGen();
1318
if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen)))
1321
xref->fetch(num,gen,&fontObj);
1322
if (fontObj.isDict()) {
1323
p = new P2PFontDict(&fontObj,xref,num,gen);
1324
/* register this in P2PXRef to output later */
1332
#ifdef HAVE_UGOOSTRING_H
1333
extGStateKeys[i] = new UGooString(*key);
1335
extGStateKeys[i] = new UGooString(key);
1337
extGStateFonts[i] = p;
1339
fontArrayObj.free();
1345
void P2PFontResource::output(P2POutputStream *str, XRef *xref)
1350
for (i = 0;i < nDicts;i++) {
1351
P2POutput::outputName(keys[i]->getCString(),str);
1353
fontDicts[i]->outputRef(str);
1359
P2PFontDict *P2PFontResource::lookup(const UGooString &key)
1363
for (i = 0;i < nDicts;i++) {
1364
if (key.cmp(keys[i]) == 0) {
1365
return fontDicts[i];
1371
P2PFontDict *P2PFontResource::lookupExtGState(const UGooString &key)
1375
for (i = 0;i < nExtGState;i++) {
1376
if (extGStateKeys != 0 && key.cmp(extGStateKeys[i]) == 0) {
1377
return extGStateFonts[i];