[poppler] poppler/CairoFontEngine.cc poppler/CairoFontEngine.h poppler/CairoOutputDev.cc

Jeff Muizelaar jrmuizel at kemper.freedesktop.org
Sat Nov 10 11:13:59 PST 2007


 poppler/CairoFontEngine.cc |   56 ++++++++++++++++++++++++++++++++++++++++++---
 poppler/CairoFontEngine.h  |    7 ++++-
 poppler/CairoOutputDev.cc  |    8 ++++--
 3 files changed, 65 insertions(+), 6 deletions(-)

New commits:
commit 5797f50a99d1494767edc5928f9c3e9d927b946d
Author: Jeff Muizelaar <jeff at infidigm.net>
Date:   Sat Nov 10 01:52:00 2007 -0500

    Scale text to match 'm' size
    
    This adds back the hack that was removed when fontconfig support was added long
    ago. It's not a great solution but lets us be at least as good as xpdf. Fixes
    #12304 with the cairo backend. The problem persists with the splash backend.

diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
old mode 100644
new mode 100755
index 8baca95..67034f0
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -62,6 +62,8 @@ CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool
   codeToGID = NULL;
   codeToGIDLen = 0;
   cairo_font_face = NULL;
+
+  GBool substitute = gFalse;
   
   ref = *gfxFont->getID();
   fontType = gfxFont->getType();
@@ -114,6 +116,7 @@ CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool
       fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType;
       break;
     }
+    substitute = gTrue;
   }
 
   switch (fontType) {
@@ -226,7 +229,7 @@ CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool
     goto err2; /* this doesn't do anything, but it looks like we're
 		* handling the error */
   } {
-  CairoFont *ret = new CairoFont(ref, cairo_font_face, face, codeToGID, codeToGIDLen);
+  CairoFont *ret = new CairoFont(ref, cairo_font_face, face, codeToGID, codeToGIDLen, substitute);
   cairo_font_face_set_user_data (cairo_font_face, 
 				 &cairo_font_face_key,
 				 ret,
@@ -241,9 +244,9 @@ CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool
 }
 
 CairoFont::CairoFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
-    Gushort *codeToGID, int codeToGIDLen) : ref(ref), cairo_font_face(cairo_font_face),
+    Gushort *codeToGID, int codeToGIDLen, GBool substitute) : ref(ref), cairo_font_face(cairo_font_face),
 					    face(face), codeToGID(codeToGID),
-					    codeToGIDLen(codeToGIDLen) { }
+					    codeToGIDLen(codeToGIDLen), substitute(substitute) { }
 
 CairoFont::~CairoFont() {
   FT_Done_Face (face);
@@ -273,6 +276,53 @@ CairoFont::getGlyph(CharCode code,
   return gid;
 }
 
+double
+CairoFont::getSubstitutionCorrection(GfxFont *gfxFont)
+{
+  double w1, w2,w3;
+  CharCode code;
+  char *name;
+
+  // for substituted fonts: adjust the font matrix -- compare the
+  // width of 'm' in the original font and the substituted font
+  if (isSubstitute() && !gfxFont->isCIDFont()) {
+    for (code = 0; code < 256; ++code) {
+      if ((name = ((Gfx8BitFont *)gfxFont)->getCharName(code)) &&
+	  name[0] == 'm' && name[1] == '\0') {
+	break;
+      }
+    }
+    if (code < 256) {
+      w1 = ((Gfx8BitFont *)gfxFont)->getWidth(code);
+      {
+	cairo_matrix_t m;
+	cairo_matrix_init_identity(&m);
+	cairo_font_options_t *options = cairo_font_options_create();
+	cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
+	cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF);
+	cairo_scaled_font_t *scaled_font = cairo_scaled_font_create(cairo_font_face, &m, &m, options);
+
+	cairo_text_extents_t extents;
+	cairo_scaled_font_text_extents(scaled_font, "m", &extents);
+
+	cairo_scaled_font_destroy(scaled_font);
+	cairo_font_options_destroy(options);
+	w3 = extents.width;
+	w2 = extents.x_advance;
+      }
+      if (!gfxFont->isSymbolic()) {
+	// if real font is substantially narrower than substituted
+	// font, reduce the font size accordingly
+	if (w1 > 0.01 && w1 < 0.9 * w2) {
+	  w1 /= w2;
+	  return w1;
+	}
+      }
+    }
+  }
+  return 1.0;
+}
+
 //------------------------------------------------------------------------
 // CairoFontEngine
 //------------------------------------------------------------------------
diff --git a/poppler/CairoFontEngine.h b/poppler/CairoFontEngine.h
index f32b6a9..b8af716 100644
--- a/poppler/CairoFontEngine.h
+++ b/poppler/CairoFontEngine.h
@@ -24,15 +24,20 @@ public:
   GBool matches(Ref &other);
   cairo_font_face_t *getFontFace(void);
   unsigned long getGlyph(CharCode code, Unicode *u, int uLen);
+  double getSubstitutionCorrection(GfxFont *gfxFont);
+
+  GBool isSubstitute() { return substitute; }
 private:
   CairoFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
-      Gushort *codeToGID, int codeToGIDLen);
+      Gushort *codeToGID, int codeToGIDLen, GBool substitute);
   Ref ref;
   cairo_font_face_t *cairo_font_face;
   FT_Face face;
 
   Gushort *codeToGID;
   int codeToGIDLen;
+
+  GBool substitute;
 };
 
 //------------------------------------------------------------------------
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
old mode 100644
new mode 100755
index fd2742a..68258d2
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -336,8 +336,12 @@ void CairoOutputDev::updateFont(GfxState *state) {
  
   double fontSize = state->getFontSize();
   double *m = state->getTextMat();
-  matrix.xx = m[0] * fontSize * state->getHorizScaling();
-  matrix.yx = m[1] * fontSize * state->getHorizScaling();
+  /* NOTE: adjusting by a constant is hack. The correct solution
+   * is probably to use user-fonts and compute the scale on a per
+   * glyph basis instead of for the entire font */
+  double w = currentFont->getSubstitutionCorrection(state->getFont());
+  matrix.xx = m[0] * fontSize * state->getHorizScaling() * w;
+  matrix.yx = m[1] * fontSize * state->getHorizScaling() * w;
   matrix.xy = -m[2] * fontSize;
   matrix.yy = -m[3] * fontSize;
   matrix.x0 = 0;


More information about the poppler mailing list