[poppler] poppler/poppler: CairoFontEngine.cc, 1.20, 1.21 CairoFontEngine.h, 1.7, 1.8 CairoOutputDev.cc, 1.35, 1.36 CairoOutputDev.h, 1.14, 1.15 Gfx.cc, 1.9, 1.10 TextOutputDev.cc, 1.18, 1.19

Kristian Høgsberg krh at kemper.freedesktop.org
Fri May 19 12:22:01 PDT 2006


Update of /cvs/poppler/poppler/poppler
In directory kemper:/tmp/cvs-serv22952/poppler

Modified Files:
	CairoFontEngine.cc CairoFontEngine.h CairoOutputDev.cc 
	CairoOutputDev.h Gfx.cc TextOutputDev.cc 
Log Message:
2006-05-19  Kristian Høgsberg  <krh at redhat.com>

	Memory leak patch from Carlos Garcia Campos (#6947).

	* glib/poppler-action.cc:
	* glib/poppler-document.cc:
	* glib/poppler-page.cc:
	* poppler/CairoFontEngine.cc:
	* poppler/CairoFontEngine.h:
	* poppler/CairoOutputDev.cc:
	* poppler/CairoOutputDev.h:
	* poppler/Gfx.cc:
	* poppler/TextOutputDev.cc:  Fix various memory leaks.



Index: CairoFontEngine.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoFontEngine.cc,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- CairoFontEngine.cc	21 Dec 2005 17:30:33 -0000	1.20
+++ CairoFontEngine.cc	19 May 2006 19:21:59 -0000	1.21
@@ -9,6 +9,7 @@
 
 #include <config.h>
 
+#include <math.h>
 #include "config.h"
 #include <string.h>
 #include "CairoFontEngine.h"
@@ -18,6 +19,11 @@
 #include <fofi/FoFiType1C.h>
 #include "goo/gfile.h"
 #include "Error.h"
+#include "Gfx.h"
+#include "Page.h"
+#include "Parser.h"
+#include "Lexer.h"
+#include "CairoOutputDev.h"
 
 #ifdef USE_GCC_PRAGMAS
 #pragma implementation
@@ -27,18 +33,261 @@
   fwrite(data, 1, len, (FILE *)stream);
 }
 
+static void
+init_cairo_matrix(cairo_matrix_t *matrix, double *d)
+{
+  matrix->xx = d[0];
+  matrix->yx = -d[2];
+  matrix->xy = d[1];
+  matrix->yy = -d[3];
+  matrix->x0 = d[2] + d[4];
+  matrix->y0 = d[3] + d[5];
+}		  
+
+static cairo_user_data_key_t cairo_font_face_key;
+
 //------------------------------------------------------------------------
-// CairoFont
+// CairoType3Font
 //------------------------------------------------------------------------
 
-static void cairo_font_face_destroy (void *data)
+class CairoType3Font : public CairoFont {
+public:
+  CairoType3Font(GfxFont *gfxFont, XRef *xref);
+
+private:
+
+  Gfx8BitFont *gfxFont;
+
+  /* Static functions for implementing the cairo user font interface. */
+  static void *scaled_font_create (cairo_scaled_font_t        *scaled_font,
+				   const cairo_matrix_t       *font_matrix,
+				   const cairo_matrix_t       *ctm,
+				   const cairo_font_options_t *options,
+				   cairo_font_extents_t       *metrics);
+  static void scaled_font_destroy (void *closure);
+
+  static unsigned long ucs4_to_index(void              *closure,
+				     unsigned long      ucs4);
+
+  static cairo_status_t get_glyph_metrics(void                 *closure,
+					  unsigned long         index,
+					  cairo_font_options_t *font_options,
+					  cairo_text_extents_t *metrics);
+  
+  static cairo_status_t render_glyph(void                 *closure,
+				     unsigned long         index,
+				     cairo_font_options_t *font_options,
+				     cairo_t              *cr);
+
+  static cairo_user_font_backend_t font_backend;
+};
+
+cairo_user_font_backend_t CairoType3Font::font_backend = {
+  CairoType3Font::scaled_font_create,
+  CairoType3Font::scaled_font_destroy,  
+  CairoType3Font::ucs4_to_index,
+  CairoType3Font::get_glyph_metrics,  
+  CairoType3Font::render_glyph
+};
+
+CairoType3Font::CairoType3Font(GfxFont *gfxFontA, XRef *xref)
+  : CairoFont(gfxFontA, xref)
 {
-  CairoFont *font = (CairoFont *) data;
+  this->gfxFont = (Gfx8BitFont *) gfxFontA;
+  cairo_font_face = cairo_user_font_face_create (&font_backend);
 
-  delete font;
+  printf ("created type3 font\n");
 }
 
-CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) {
+void *
+CairoType3Font::scaled_font_create (cairo_scaled_font_t        *scaled_font,
+				    const cairo_matrix_t       *font_matrix,
+				    const cairo_matrix_t       *ctm,
+				    const cairo_font_options_t *options,
+				    cairo_font_extents_t       *metrics)
+{
+  return cairo_scaled_font_get_font_face (scaled_font);
+}
+
+void
+CairoType3Font::scaled_font_destroy (void *closure)
+{
+}
+
+unsigned long
+CairoType3Font::ucs4_to_index(void          *closure,
+			      unsigned long  ucs4)
+{
+  return 0;
+}
+
+cairo_status_t
+CairoType3Font::get_glyph_metrics(void                 *closure,
+				  unsigned long         index,
+				  cairo_font_options_t *font_options,
+				  cairo_text_extents_t *metrics)
+{
+  CairoType3Font *font;
+  double *bbox;
+  Object charProc, obj;
+  Object argObjs[maxArgs];
+  Parser *parser;
+  char *name;
+  double args[maxArgs];
+  int i, numArgs;
+  cairo_matrix_t font_matrix;
+  cairo_font_face_t *face = (cairo_font_face_t *) closure;
+
+  font = (CairoType3Font *)
+    cairo_font_face_get_user_data (face, &cairo_font_face_key);
+
+  font->gfxFont->getCharProc(index, &charProc);
+  if (!charProc.isStream()) {
+      charProc.free();
+      return CAIRO_STATUS_SUCCESS;
+  }
+  parser = new Parser(font->xref, new Lexer(font->xref, &charProc));
+
+  numArgs = 0;
+  parser->getObj(&obj);
+  while (!obj.isEOF()) {
+
+    // got a command - execute it
+    if (obj.isCmd()) {
+
+      name = obj.getCmd();
+      if (strcmp(name, "d0") == 0) {
+	/* FIXME: Handle d0 glyphs. */
+      } else if (strcmp(name, "d1") == 0) {
+	if (numArgs < 6)
+	  goto cont;
+	for (i = 0; i < 6; i++) {
+	  if (!argObjs[numArgs - 6 + i].isNum())
+	    goto cont;
+	  args[i] = argObjs[numArgs - 6 + i].getNum();
+	}
+
+	/* Transform glyph coordinates to text coordinates, which is
+	 * what cairo expects. */
+	init_cairo_matrix (&font_matrix, font->gfxFont->getFontMatrix());
+	cairo_matrix_transform_distance (&font_matrix, &args[0], &args[1]);
+	cairo_matrix_transform_distance (&font_matrix, &args[2], &args[3]);
+	cairo_matrix_transform_distance (&font_matrix, &args[4], &args[5]);
+
+	metrics->x_bearing = args[2];
+	metrics->y_bearing = args[5];
+	metrics->width = args[4] - args[2];
+	metrics->height = args[3] - args[5];
+	metrics->x_advance = args[0];
+	metrics->y_advance = args[1];
+
+	break;
+      }
+    cont:
+      obj.free();
+      for (i = 0; i < numArgs; ++i)
+	argObjs[i].free();
+      numArgs = 0;
+    } else if (numArgs < maxArgs) {
+      argObjs[numArgs++] = obj;
+    }
+
+    parser->getObj(&obj);
+  }
+  obj.free();
+  for (i = 0; i < numArgs; ++i)
+    argObjs[i].free();
+
+  delete parser;
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+CairoType3Font::render_glyph(void                 *closure,
+			     unsigned long         index,
+			     cairo_font_options_t *font_options,
+			     cairo_t              *cr)
+{
+  Dict *resources;
+  Gfx *gfx;
+  Object charProc;
+  CairoOutputDev *out;
+  CairoType3Font *font;
+  cairo_matrix_t font_matrix;
+  cairo_font_face_t *face = (cairo_font_face_t *) closure;
+
+  cairo_surface_t *target;
+  int width, height;
+
+  target = cairo_get_target (cr);
+  width = cairo_image_surface_get_width (target);
+  height = cairo_image_surface_get_height (target);
+  PDFRectangle box(0, 0, width, height);
+
+  font = (CairoType3Font *)
+    cairo_font_face_get_user_data (face, &cairo_font_face_key);
+
+  out = new CairoOutputDev();
+  out->setCairo(cr);
+  resources = font->gfxFont->getResources();
+
+  gfx = new Gfx(font->xref, out, resources, &box, NULL);
+
+  font->gfxFont->getCharProc(index, &charProc);
+
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_set_source_rgba (cr, 0, 0, 0, 0);
+  cairo_paint (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+  cairo_move_to (cr, -10, 0);
+  cairo_line_to (cr, 10, 0);
+  cairo_move_to (cr, 0, -10);
+  cairo_line_to (cr, 0, 10);
+  cairo_move_to (cr, -10, -10);
+  cairo_line_to (cr, 10, 10);
+  cairo_move_to (cr, 10, -10);
+  cairo_line_to (cr, -10, 10);
+  cairo_set_line_width (cr, 5);
+  cairo_stroke (cr);
+
+  init_cairo_matrix(&font_matrix, font->gfxFont->getFontMatrix());
+  cairo_transform (cr, &font_matrix);
+
+  if (charProc.isStream()) {
+    gfx->display(&charProc, gFalse);
+  } else {
+    error(-1, "Missing or bad Type3 CharProc entry");
+  }
+
+  delete gfx;
+  delete out;
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
+//------------------------------------------------------------------------
+// CairoFTFont
+//------------------------------------------------------------------------
+
+class CairoFTFont : public CairoFont {
+public:
+  CairoFTFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs);
+  virtual ~CairoFTFont();
+
+  GBool matches(Ref &other);
+  cairo_font_face_t *getFontFace(void);
+  unsigned long getGlyph(CharCode code, Unicode *u, int uLen);
+
+private:
+  FT_Face face;
+};
+
+CairoFTFont::CairoFTFont(GfxFont *gfxFont, XRef *xref,
+			 FT_Library lib, GBool useCIDs)
+  : CairoFont(gfxFont, xref)
+{
   Ref embRef;
   Object refObj, strObj;
   GooString *tmpFileName, *fileName, *substName,*tmpFileName2;
@@ -52,14 +301,8 @@
   FoFiType1C *ff1c;
   CharCodeToUnicode *ctu;
   Unicode uBuf[8];
-  static cairo_user_data_key_t cairo_font_face_key;
   
   dfp = NULL;
-  codeToGID = NULL;
-  codeToGIDLen = 0;
-  cairo_font_face = NULL;
-  
-  ref = *gfxFont->getID();
   fontType = gfxFont->getType();
 
   tmpFileName = NULL;
@@ -219,7 +462,7 @@
       goto err2;
     }
     break;
-    
+
   default:
     printf ("font type not handled\n");
     goto err2;
@@ -237,25 +480,63 @@
   cairo_font_face = cairo_ft_font_face_create_for_ft_face (face,
 							   FT_LOAD_NO_HINTING |
 							   FT_LOAD_NO_BITMAP);
-  if (cairo_font_face == NULL) {
-    error(-1, "could not create cairo font\n");
-    goto err2; /* this doesn't do anything, but it looks like we're
-		* handling the error */
-  }
-
-  cairo_font_face_set_user_data (cairo_font_face, 
-				 &cairo_font_face_key,
-				 this,
-				 cairo_font_face_destroy);
-
   return;
  err2:
   /* hmm? */
   printf ("some font thing failed\n");
 }
 
-CairoFont::~CairoFont() {
+CairoFTFont::~CairoFTFont() {
   FT_Done_Face (face);
+}
+
+//------------------------------------------------------------------------
+// CairoFont
+//------------------------------------------------------------------------
+
+void cairo_font_destroy (void *data)
+{
+  CairoFont *font = (CairoFont *) data;
+
+  font->unreference();
+}
+
+CairoFont *
+CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs)
+{
+  CairoFont *font;
+
+  switch (gfxFont->getType()) {
+  case fontType3:
+    font = new CairoType3Font(gfxFont, xref);
+    break;
+  default:
+    font = new CairoFTFont(gfxFont, xref, lib, useCIDs);
+    break;
+  }
+
+  if (font->cairo_font_face == NULL)
+    error(-1, "could not create cairo font\n");
+  else
+    cairo_font_face_set_user_data (font->cairo_font_face, 
+				   &cairo_font_face_key,
+				   font->reference(),
+				   cairo_font_destroy);
+
+  return font;
+}
+
+CairoFont::CairoFont(GfxFont *gfxFont, XRef *xrefA)
+{
+  codeToGID = NULL;
+  codeToGIDLen = 0;
+  ref = *gfxFont->getID();
+  xref = xrefA;
+  refcount = 1;
+}
+
+CairoFont::~CairoFont()
+{
   gfree(codeToGID);
 }
 
@@ -274,7 +555,7 @@
 		    Unicode *u, int uLen) {
   FT_UInt gid;
 
-  if (codeToGID && code < codeToGIDLen) {
+  if (codeToGID && code < (unsigned) codeToGIDLen) {
     gid = (FT_UInt)codeToGID[code];
   } else {
     gid = (FT_UInt)code;
@@ -282,6 +563,8 @@
   return gid;
 }
 
+
+
 //------------------------------------------------------------------------
 // CairoFontEngine
 //------------------------------------------------------------------------
@@ -306,7 +589,7 @@
   
   for (i = 0; i < cairoFontCacheSize; ++i) {
     if (fontCache[i])
-      delete fontCache[i];
+      fontCache[i]->unreference();
   }
 }
 
@@ -315,13 +598,6 @@
   int i, j;
   Ref ref;
   CairoFont *font;
-  GfxFontType fontType;
-  
-  fontType = gfxFont->getType();
-  if (fontType == fontType3) {
-    /* Need to figure this out later */
-    //    return NULL;
-  }
 
   ref = *gfxFont->getID();
 
@@ -336,9 +612,9 @@
     }
   }
   
-  font = new CairoFont (gfxFont, xref, lib, useCIDs);
+  font = CairoFont::create (gfxFont, xref, lib, useCIDs);
   if (fontCache[cairoFontCacheSize - 1]) {
-    delete fontCache[cairoFontCacheSize - 1];
+    fontCache[cairoFontCacheSize - 1]->unreference();
   }
   for (j = cairoFontCacheSize - 1; j > 0; --j) {
     fontCache[j] = fontCache[j-1];
@@ -346,4 +622,3 @@
   fontCache[0] = font;
   return font;
 }
-

Index: CairoFontEngine.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoFontEngine.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- CairoFontEngine.h	20 Mar 2006 19:02:10 -0000	1.7
+++ CairoFontEngine.h	19 May 2006 19:21:59 -0000	1.8
@@ -18,19 +18,26 @@
 
 class CairoFont {
 public:
-  CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs);
-  ~CairoFont();
+  static CairoFont *create(GfxFont *gfxFont, XRef *xref,
+			   FT_Library lib, GBool useCIDs);
+
+  CairoFont *reference() { refcount++; return this; }
+  void unreference() { if (--refcount == 0) delete this; }
 
   GBool matches(Ref &other);
   cairo_font_face_t *getFontFace(void);
   unsigned long getGlyph(CharCode code, Unicode *u, int uLen);
-private:
+
+protected:
+  CairoFont(GfxFont *gfxFont, XRef *xref);
+  virtual ~CairoFont();
+
   Ref ref;
+  XRef *xref;
   cairo_font_face_t *cairo_font_face;
-  FT_Face face;
-
   Gushort *codeToGID;
   int codeToGIDLen;
+  int refcount;
 };
 
 //------------------------------------------------------------------------

Index: CairoOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoOutputDev.cc,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- CairoOutputDev.cc	27 Apr 2006 17:26:37 -0000	1.35
+++ CairoOutputDev.cc	19 May 2006 19:21:59 -0000	1.36
@@ -258,9 +258,6 @@
 
   needFontUpdate = gFalse;
 
-  if (state->getFont()->getType() == fontType3)
-    return;
-
   currentFont = fontEngine->getFont (state->getFont(), xref);
 
   state->getFontTransMat(&m11, &m12, &m21, &m22);
@@ -448,7 +445,7 @@
 }
 
 void CairoOutputDev::type3D1(GfxState *state, double wx, double wy,
-			      double llx, double lly, double urx, double ury) {
+			     double llx, double lly, double urx, double ury) {
 }
 
 void CairoOutputDev::endTextObject(GfxState *state) {

Index: CairoOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoOutputDev.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- CairoOutputDev.h	12 Apr 2006 06:52:07 -0000	1.14
+++ CairoOutputDev.h	19 May 2006 19:21:59 -0000	1.15
@@ -52,7 +52,7 @@
 
   // Does this device use beginType3Char/endType3Char?  Otherwise,
   // text in Type 3 fonts will be drawn with drawChar/drawString.
-  virtual GBool interpretType3Chars() { return gTrue; }
+  virtual GBool interpretType3Chars() { return gFalse; }
 
   //----- initialization and control
 

Index: Gfx.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Gfx.cc,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- Gfx.cc	2 May 2006 04:38:39 -0000	1.9
+++ Gfx.cc	19 May 2006 19:21:59 -0000	1.10
@@ -483,6 +483,7 @@
   // initialize
   out = outA;
   state = new GfxState(72, 72, box, 0, gFalse);
+  out->updateAll(state);
   fontChanged = gFalse;
   clip = clipNone;
   ignoreUndef = 0;

Index: TextOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/TextOutputDev.cc,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- TextOutputDev.cc	2 May 2006 04:38:39 -0000	1.18
+++ TextOutputDev.cc	19 May 2006 19:21:59 -0000	1.19
@@ -2375,6 +2375,8 @@
   //----- column assignment
 
   // sort blocks into xy order for column assignment
+  if (blocks)
+    gfree (blocks);
   blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
   for (blk = blkList, i = 0; blk; blk = blk->next, ++i) {
     blocks[i] = blk;
@@ -2512,6 +2514,11 @@
   //~ this also needs to account for right-to-left column ordering
   blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
   memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *));
+  while (flows) {
+    flow = flows;
+    flows = flows->next;
+    delete flow;
+  }
   flows = lastFlow = NULL;
   firstBlkIdx = 0;
   nBlocksLeft = nBlocks;
@@ -3375,6 +3382,8 @@
 		  word->charcode[i], 1, NULL, 0);
   
   out->endString(state);
+
+  delete string;
 }
 
 void TextWord::visitSelection(TextSelectionVisitor *visitor,



More information about the poppler mailing list