fixed italic font handling
[swftools.git] / lib / pdf / InfoOutputDev.cc
1 #include "SplashTypes.h"
2 #include "SplashOutputDev.h"
3 #include "SplashPath.h"
4 #include "SplashFontFile.h"
5 #include "InfoOutputDev.h"
6 #include "GfxState.h"
7 #include "../log.h"
8 #include <math.h>
9
10 InfoOutputDev::InfoOutputDev(XRef*xref) 
11 {
12     num_links = 0;
13     num_images = 0;
14     num_fonts = 0;
15     currentfont = 0;
16     currentglyph = 0;
17     id2font = new GHash(1);
18     SplashColor white = {255,255,255};
19     splash = new SplashOutputDev(splashModeRGB8,320,0,white,0,0);
20     splash->startDoc(xref);
21 }
22 InfoOutputDev::~InfoOutputDev() 
23 {
24     GHashIter*i;
25     id2font->startIter(&i);
26     GString*key;
27     FontInfo*fontinfo;
28     while(id2font->getNext(&i, &key, (void**)&fontinfo)) {
29         delete fontinfo;
30     }
31     id2font->killIter(&i);
32
33     delete id2font;
34     delete splash;
35 }
36 void FontInfo::grow(int size)
37 {
38     if(size >= this->num_glyphs) {
39         this->glyphs = (GlyphInfo**)realloc(this->glyphs, sizeof(GlyphInfo*)*(size));
40         memset(&this->glyphs[this->num_glyphs], 0, sizeof(SplashPath*)*((size)-this->num_glyphs));
41         this->num_glyphs = size;
42     }
43 }
44 FontInfo::FontInfo()
45 {
46     this->charid2glyph = 0;
47     this->seen = 0;
48     this->num_glyphs = 0;
49     this->glyphs = 0;
50     this->splash_font = 0;
51 }
52 FontInfo::~FontInfo()
53 {
54     this->font = 0;
55     if(this->charid2glyph) {
56         free(this->charid2glyph);
57         this->charid2glyph = 0;
58     }
59     int t;
60     for(t=0;t<num_glyphs;t++) {
61         if(glyphs[t]) {
62             delete glyphs[t]->path;glyphs[t]->path = 0;
63             delete glyphs[t];
64             glyphs[t]=0;
65         }
66     }
67 }
68 GBool InfoOutputDev::upsideDown() {return gTrue;}
69 GBool InfoOutputDev::useDrawChar() {return gTrue;}
70 GBool InfoOutputDev::interpretType3Chars() {return gTrue;}
71 GBool InfoOutputDev::useTilingPatternFill() {return gTrue;}
72
73 void InfoOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2)
74 {
75     double x1,y1,x2,y2;
76     state->transform(crop_x1,crop_y1,&x1,&y1);
77     state->transform(crop_x2,crop_y2,&x2,&y2);
78     if(x2<x1) {double x3=x1;x1=x2;x2=x3;}
79     if(y2<y1) {double y3=y1;y1=y2;y2=y3;}
80     this->x1 = (int)x1;
81     this->y1 = (int)y1;
82     this->x2 = (int)x2;
83     this->y2 = (int)y2;
84     msg("<verbose> Generating info structure for page %d", pageNum);
85 }
86 void InfoOutputDev::endPage()
87 {
88 }
89 void InfoOutputDev::drawLink(Link *link, Catalog *catalog) 
90 {
91     num_links++;
92 }
93 double InfoOutputDev::getMaximumFontSize(char*id)
94 {
95     FontInfo*info = (FontInfo*)id2font->lookup(id);
96     if(!info) {
97         msg("<error> Unknown font id: %s", id);
98         return 0.0;
99     }
100     return info->max_size;
101 }
102
103 char*getFontID(GfxFont*font)
104 {
105     Ref*ref = font->getID();
106     GString*gstr = font->getName();
107     char* fname = gstr==0?0:gstr->getCString();
108     char buf[128];
109     if(fname==0) {
110         if(font->getType() == fontType3) {
111             sprintf(buf, "t3font-%d-%d", ref->num, ref->gen);
112         } else {
113             sprintf(buf, "font-%d-%d", ref->num, ref->gen);
114         }
115     } else {
116         sprintf(buf, "%s-%d-%d", fname, ref->num, ref->gen);
117     }
118     return strdup(buf);
119 }
120
121 void InfoOutputDev::updateFont(GfxState *state) 
122 {
123     GfxFont*font = state->getFont();
124     if(!font) {
125         currentfont = 0;
126         return;
127     }
128     if(font->getType() == fontType3) {
129         currentfont = 0;
130         return;
131     }
132     char*id = getFontID(font);
133
134     if(currentfont)
135         currentfont->splash_font = 0;
136
137     currentfont = (FontInfo*)id2font->lookup(id);
138     if(!currentfont) {
139         currentfont = new FontInfo;
140         currentfont->font = font;
141         currentfont->max_size = 0;
142         GString* idStr = new GString(id);
143         id2font->add(idStr, (void*)currentfont);
144         num_fonts++;
145     }
146
147     state->setCTM(1.0,0,0,1.0,0,0);
148     splash->updateCTM(state, 0,0,0,0,0,0);
149     state->setTextMat(1.0,0,0,1.0,0,0);
150     state->setFont(font, 1024.0);
151     splash->doUpdateFont(state);
152     currentfont->splash_font = splash->getCurrentFont();
153     free(id);
154 }
155 FontInfo* InfoOutputDev::getFont(char*id)
156 {
157     return (FontInfo*)id2font->lookup(id);
158 }
159
160 void InfoOutputDev::drawChar(GfxState *state, double x, double y,
161                       double dx, double dy,
162                       double originX, double originY,
163                       CharCode code, int nBytes, Unicode *u, int uLen)
164 {
165     double m11,m21,m12,m22;
166     state->getFontTransMat(&m11, &m12, &m21, &m22);
167     m11 *= state->getHorizScaling();
168     m21 *= state->getHorizScaling();
169     double lenx = sqrt(m11*m11 + m12*m12);
170     double leny = sqrt(m21*m21 + m22*m22);
171     double len = lenx>leny?lenx:leny;
172     if(!currentfont || !currentfont->splash_font) {
173         return; //error
174     }
175     if(currentfont && currentfont->max_size < len) {
176         currentfont->max_size = len;
177     }
178     currentfont->grow(code+1);
179     GlyphInfo*g = currentfont->glyphs[code];
180     if(!g) {
181         g = currentfont->glyphs[code] = new GlyphInfo();
182         g->path = currentfont->splash_font->getGlyphPath(code);
183         g->unicode = 0;
184     }
185     if(uLen && (u[0]>=32 && u[0]<g->unicode || !g->unicode)) {
186         g->unicode = u[0];
187     }
188
189 }
190
191 GBool InfoOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
192 {
193     GfxFont*font = state->getFont();
194     if(!font)
195         return gTrue;
196     if(font->getType() != fontType3)
197         return gTrue;
198
199     char*id = getFontID(font);
200     currentfont = (FontInfo*)id2font->lookup(id);
201     if(!currentfont) {
202         currentfont = new FontInfo;
203         currentfont->font = font;
204         GString* idStr = new GString(id);
205         id2font->add(idStr, (void*)currentfont);
206         num_fonts++;
207     }
208     currentfont = currentfont;
209     free(id);
210
211     currentfont->grow(code+1);
212     if(!currentfont->glyphs[code]) {
213         currentglyph = currentfont->glyphs[code] = new GlyphInfo();
214         currentglyph->unicode = uLen?u[0]:0;
215         currentglyph->path = new SplashPath();
216         currentglyph->x1=0;
217         currentglyph->y1=0;
218         currentglyph->x2=dx;
219         currentglyph->y2=dy;
220         return gFalse;
221     } else {
222         return gTrue;
223     }
224 }
225
226 void InfoOutputDev::type3D0(GfxState *state, double wx, double wy)
227 {
228     currentglyph->x1=0;
229     currentglyph->y1=0;
230     currentglyph->x2=wx;
231     currentglyph->y2=wy;
232 }
233
234 void InfoOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury)
235 {
236     currentglyph->x1=llx;
237     currentglyph->y1=lly;
238     currentglyph->x2=urx;
239     currentglyph->y2=ury;
240 }
241
242 void InfoOutputDev::endType3Char(GfxState *state)
243 {
244     double x1 = currentglyph->x1;
245     double y1 = currentglyph->y1;
246     double x2 = currentglyph->x2;
247     double y2 = currentglyph->y2;
248     currentglyph->path->moveTo(x1,y1);
249     currentglyph->path->lineTo(x2,y1);
250     currentglyph->path->lineTo(x2,y2);
251     currentglyph->path->lineTo(x1,y2);
252     currentglyph->path->close();
253 }
254
255 void InfoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
256                            int width, int height, GBool invert,
257                            GBool inlineImg) 
258 {
259     num_images++;
260     OutputDev::drawImageMask(state,ref,str,width,height,invert,inlineImg);
261 }
262 void InfoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
263                        int width, int height, GfxImageColorMap *colorMap,
264                        int *maskColors, GBool inlineImg)
265 {
266     num_images++;
267     OutputDev::drawImage(state,ref,str,width,height,colorMap,maskColors,inlineImg);
268 }
269 void InfoOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
270                                 int width, int height,
271                                 GfxImageColorMap *colorMap,
272                                 Stream *maskStr,
273                                 int maskWidth, int maskHeight,
274                                 GBool maskInvert) 
275 {
276     OutputDev::drawMaskedImage(state,ref,str,width,height,colorMap,maskStr,maskWidth,maskHeight,maskInvert);
277 }
278
279 void InfoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
280                                     int width, int height,
281                                     GfxImageColorMap *colorMap,
282                                     Stream *maskStr,
283                                     int maskWidth, int maskHeight,
284                                     GfxImageColorMap *maskColorMap) 
285 {
286     OutputDev::drawSoftMaskedImage(state,ref,str,width,height,colorMap,maskStr,maskWidth,maskHeight,maskColorMap);
287 }