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