summaryrefslogtreecommitdiff
path: root/poppler
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2006-05-19 19:21:59 +0000
committerKristian Høgsberg <krh@redhat.com>2006-05-19 19:21:59 +0000
commit78ae3efd9541d7b63ff5a2c4de3fde300806688f (patch)
tree0b1b4e1e7b9c570e971c7443f8fe68c15b87f5d8 /poppler
parent354c1926b7181fd668f221e1d672974e04fda747 (diff)
2006-05-19 Kristian Høgsberg <krh@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.
Diffstat (limited to 'poppler')
-rw-r--r--poppler/CairoFontEngine.cc347
-rw-r--r--poppler/CairoFontEngine.h17
-rw-r--r--poppler/CairoOutputDev.cc5
-rw-r--r--poppler/CairoOutputDev.h2
-rw-r--r--poppler/Gfx.cc1
-rw-r--r--poppler/TextOutputDev.cc9
6 files changed, 335 insertions, 46 deletions
diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index f5ab8cb0..f81f235a 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -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 @@ static void fileWrite(void *stream, char *data, int len) {
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);
+
+ printf ("created type3 font\n");
+}
+
+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;
- delete font;
+ return CAIRO_STATUS_SUCCESS;
}
-CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) {
+//------------------------------------------------------------------------
+// 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 @@ CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs
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 @@ CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs
goto err2;
}
break;
-
+
default:
printf ("font type not handled\n");
goto err2;
@@ -237,25 +480,63 @@ CairoFont::CairoFont(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs
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 @@ CairoFont::getGlyph(CharCode code,
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 @@ CairoFont::getGlyph(CharCode code,
return gid;
}
+
+
//------------------------------------------------------------------------
// CairoFontEngine
//------------------------------------------------------------------------
@@ -306,7 +589,7 @@ CairoFontEngine::~CairoFontEngine() {
for (i = 0; i < cairoFontCacheSize; ++i) {
if (fontCache[i])
- delete fontCache[i];
+ fontCache[i]->unreference();
}
}
@@ -315,13 +598,6 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref) {
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 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref) {
}
}
- 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 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref) {
fontCache[0] = font;
return font;
}
-
diff --git a/poppler/CairoFontEngine.h b/poppler/CairoFontEngine.h
index 2df4e02f..8cfac6f9 100644
--- a/poppler/CairoFontEngine.h
+++ b/poppler/CairoFontEngine.h
@@ -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;
};
//------------------------------------------------------------------------
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 04682ed2..4b1c2841 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -258,9 +258,6 @@ void CairoOutputDev::updateFont(GfxState *state) {
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::type3D0(GfxState *state, double wx, double wy) {
}
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) {
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 7300fc49..e3100630 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -52,7 +52,7 @@ public:
// 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
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 9ea0b625..cee3a189 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -483,6 +483,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict,
// initialize
out = outA;
state = new GfxState(72, 72, box, 0, gFalse);
+ out->updateAll(state);
fontChanged = gFalse;
clip = clipNone;
ignoreUndef = 0;
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index 22ce8b3e..e9cdd146 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -2375,6 +2375,8 @@ void TextPage::coalesce(GBool physLayout) {
//----- 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 @@ void TextPage::coalesce(GBool physLayout) {
//~ 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 @@ void TextSelectionPainter::visitWord (TextWord *word, int begin, int end,
word->charcode[i], 1, NULL, 0);
out->endString(state);
+
+ delete string;
}
void TextWord::visitSelection(TextSelectionVisitor *visitor,