added text field and jpeg counting
[swftools.git] / lib / pdf / InfoOutputDev.cc
index c2accf2..e6f3c03 100644 (file)
 InfoOutputDev::InfoOutputDev(XRef*xref) 
 {
     num_links = 0;
-    num_images = 0;
+    num_jpeg_images = 0;
+    num_ppm_images = 0;
     num_fonts = 0;
     num_polygons= 0;
+    fonts = 0;
     currentfont = 0;
     currentglyph = 0;
     id2font = new GHash(1);
@@ -62,6 +64,7 @@ FontInfo::FontInfo()
     this->lastchar = -1;
     this->lastx = 0;
     this->lasty = 0;
+    this->gfxfont = 0;
 }
 FontInfo::~FontInfo()
 {
@@ -105,6 +108,108 @@ void InfoOutputDev::drawLink(Link *link, Catalog *catalog)
 {
     num_links++;
 }
+   
+/* there's not yet a way to set this */
+int config_fontquality = 10;
+int config_bigchar = 0;
+
+/*  } else if(!strcmp(key,"fontquality")) {
+        this->config_fontquality = atof(value);
+       if(this->config_fontquality<=1)
+           this->config_fontquality=1;
+    } else if(!strcmp(key,"bigchar")) {
+        this->config_bigchar = atoi(value);
+    }
+ */
+
+gfxfont_t* InfoOutputDev::createGfxFont(GfxFont*xpdffont, FontInfo*src)
+{
+    gfxfont_t*font = (gfxfont_t*)malloc(sizeof(gfxfont_t));
+    memset(font, 0, sizeof(gfxfont_t));
+
+    font->glyphs = (gfxglyph_t*)malloc(sizeof(gfxglyph_t)*src->num_glyphs);
+    memset(font->glyphs, 0, sizeof(gfxglyph_t)*src->num_glyphs);
+    font->id = 0;
+    int t;
+
+    double quality = (INTERNAL_FONT_SIZE * 200 / config_fontquality) / src->max_size;
+    double scale = 1;
+    //printf("%d glyphs\n", font->num_glyphs);
+    font->num_glyphs = 0;
+    font->ascent = fabs(src->descender);
+    font->descent = fabs(src->ascender);
+    
+    for(t=0;t<src->num_glyphs;t++) {
+       if(src->glyphs[t]) {
+           SplashPath*path = src->glyphs[t]->path;
+           int len = path?path->getLength():0;
+           //printf("glyph %d) %08x (%d line segments)\n", t, path, len);
+           gfxglyph_t*glyph = &font->glyphs[font->num_glyphs];
+           src->glyphs[t]->glyphid = font->num_glyphs;
+           glyph->unicode = src->glyphs[t]->unicode;
+           if(glyph->unicode >= font->max_unicode)
+               font->max_unicode = glyph->unicode+1;
+           gfxdrawer_t drawer;
+           gfxdrawer_target_gfxline(&drawer);
+           int s;
+           int count = 0;
+           double xmax = 0;
+           for(s=0;s<len;s++) {
+               Guchar f;
+               double x, y;
+               path->getPoint(s, &x, &y, &f);
+               if(!s || x > xmax)
+                   xmax = x;
+               if(f&splashPathFirst) {
+                   drawer.moveTo(&drawer, x*scale, y*scale);
+               }
+               if(f&splashPathCurve) {
+                   double x2,y2;
+                   path->getPoint(++s, &x2, &y2, &f);
+                   if(f&splashPathCurve) {
+                       double x3,y3;
+                       path->getPoint(++s, &x3, &y3, &f);
+                       gfxdraw_cubicTo(&drawer, x*scale, y*scale, x2*scale, y2*scale, x3*scale, y3*scale, quality);
+                   } else {
+                       drawer.splineTo(&drawer, x*scale, y*scale, x2*scale, y2*scale);
+                   }
+               } else {
+                   drawer.lineTo(&drawer, x*scale, y*scale);
+               }
+            //   printf("%f %f %s %s\n", x, y, (f&splashPathCurve)?"curve":"",
+            //                           (f&splashPathFirst)?"first":"",
+            //                           (f&splashPathLast)?"last":"");
+           }
+
+           glyph->line = (gfxline_t*)drawer.result(&drawer);
+           if(src->glyphs[t]->advance>0) {
+               glyph->advance = src->glyphs[t]->advance;
+           } else {
+               msg("<warning> Approximating advance value for glyph %d", t);
+               glyph->advance = xmax*scale;
+           }
+           if(config_bigchar) {
+               double max = src->glyphs[t]->advance_max;
+               if(max>0 && max > glyph->advance) {
+                   glyph->advance = max;
+               }
+           }
+
+           font->num_glyphs++;
+       }
+    }
+    font->unicode2glyph = (int*)malloc(sizeof(int)*font->max_unicode);
+    memset(font->unicode2glyph, -1, sizeof(int)*font->max_unicode);
+    for(t=0;t<font->num_glyphs;t++) {
+       if(font->glyphs[t].unicode>0 && font->glyphs[t].unicode<font->max_unicode) {
+           font->unicode2glyph[font->glyphs[t].unicode] = t;
+       }
+
+    }
+    msg("<trace> %d glyphs.", t, font->num_glyphs);
+    return font;
+}
+
 double InfoOutputDev::getMaximumFontSize(char*id)
 {
     FontInfo*info = (FontInfo*)id2font->lookup(id);
@@ -165,8 +270,17 @@ void InfoOutputDev::updateFont(GfxState *state)
     state->setFont(font, 1024.0);
     splash->doUpdateFont(state);
     currentfont->splash_font = splash->getCurrentFont();
-    currentfont->ascender = currentfont->splash_font->ascender;
-    currentfont->descender = currentfont->splash_font->descender;
+    if(currentfont->splash_font) {
+        currentfont->ascender = currentfont->splash_font->ascender;
+        currentfont->descender = currentfont->splash_font->descender;
+    } else {
+        currentfont->ascender = currentfont->descender = 0;
+    }
+
+    currentfont->gfxfont = this->createGfxFont(font, currentfont);
+    currentfont->gfxfont->id = strdup(id);
+    fonts = gfxfontlist_addfont(fonts, currentfont->gfxfont);
+
     free(id);
 }
 
@@ -207,7 +321,7 @@ void InfoOutputDev::drawChar(GfxState *state, double x, double y,
     GlyphInfo*g = currentfont->glyphs[code];
     if(!g) {
        g = currentfont->glyphs[code] = new GlyphInfo();
-       g->advance_samples = 0;
+       g->advance_max = 0;
        currentfont->splash_font->last_advance = -1;
        g->path = currentfont->splash_font->getGlyphPath(code);
        g->advance = currentfont->splash_font->last_advance;
@@ -218,11 +332,8 @@ void InfoOutputDev::drawChar(GfxState *state, double x, double y,
     }
     if(currentfont->lastchar>=0 && currentfont->lasty == y) {
        double xshift = x - currentfont->lastx;
-       if(xshift>=0) {
-           AdvanceSample* old = g->advance_samples;
-           g->advance_samples = new AdvanceSample();
-           g->advance_samples->next = old;
-           g->advance_samples->advance = xshift;
+       if(xshift>=0 && xshift > g->advance_max) {
+           g->advance_max = xshift;
        }
     }
 
@@ -231,41 +342,6 @@ void InfoOutputDev::drawChar(GfxState *state, double x, double y,
     currentfont->lastchar = code;
 }
 
-static int compare_double(const void *_a, const void *_b)
-{
-    const double*a = (const double*)_a;
-    const double*b = (const double*)_b;
-    if(*a < *b) 
-       return -1;
-    if(*a > *b) 
-       return 1;
-    return 0;
-}
-
-double GlyphInfo::estimateAdvance()
-{
-    AdvanceSample*a = advance_samples;
-    int n=0;
-    while(a) {
-       n++;
-       a = a->next;
-    }
-    if(!n)
-       return -1;
-    double*list = (double*)malloc(sizeof(double)*n);
-    n = 0;
-    a = advance_samples;
-    while(a) {
-       list[n++] = a->advance;
-       a = a->next;
-    }
-    // FIXME: a true median algorithm would be faster
-    qsort(list, n, sizeof(double), compare_double);
-    double median = list[n/2];
-    free(list);
-    return median;
-}
-
 GBool InfoOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
 {
     GfxFont*font = state->getFont();
@@ -334,14 +410,16 @@ void InfoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
                           int width, int height, GBool invert,
                           GBool inlineImg) 
 {
-    num_images++;
+    if(str->getKind()==strDCT) num_jpeg_images++; else num_ppm_images++;
+
     OutputDev::drawImageMask(state,ref,str,width,height,invert,inlineImg);
 }
 void InfoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
                       int width, int height, GfxImageColorMap *colorMap,
                       int *maskColors, GBool inlineImg)
 {
-    num_images++;
+    if(str->getKind()==strDCT) num_jpeg_images++; else num_ppm_images++;
+
     OutputDev::drawImage(state,ref,str,width,height,colorMap,maskColors,inlineImg);
 }
 void InfoOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
@@ -351,6 +429,8 @@ void InfoOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
                                int maskWidth, int maskHeight,
                                GBool maskInvert) 
 {
+    if(str->getKind()==strDCT) num_jpeg_images++; else num_ppm_images++;
+
     OutputDev::drawMaskedImage(state,ref,str,width,height,colorMap,maskStr,maskWidth,maskHeight,maskInvert);
 }
 
@@ -361,5 +441,7 @@ void InfoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *st
                                    int maskWidth, int maskHeight,
                                    GfxImageColorMap *maskColorMap) 
 {
+    if(str->getKind()==strDCT) num_jpeg_images++; else num_ppm_images++;
+
     OutputDev::drawSoftMaskedImage(state,ref,str,width,height,colorMap,maskStr,maskWidth,maskHeight,maskColorMap);
 }