[PATCH] Implement Type 3 fonts in cairo backend using cairo user-fonts
Adrian Johnson
ajohnson at redneon.com
Fri Oct 31 08:27:32 PDT 2008
---
poppler/CairoFontEngine.cc | 174 ++++++++++++++++++++++++++++++++++++++++++--
poppler/CairoFontEngine.h | 18 +++++
poppler/CairoOutputDev.cc | 9 ++-
poppler/CairoOutputDev.h | 4 +-
4 files changed, 194 insertions(+), 11 deletions(-)
diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index 75340b8..dc975be 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -32,12 +32,16 @@
#include "config.h"
#include <string.h>
#include "CairoFontEngine.h"
+#include "CairoOutputDev.h"
#include "CharCodeToUnicode.h"
#include "GlobalParams.h"
#include <fofi/FoFiTrueType.h>
#include <fofi/FoFiType1C.h>
#include "goo/gfile.h"
#include "Error.h"
+#include "XRef.h"
+#include "Gfx.h"
+#include "Page.h"
#if HAVE_FCNTL_H && HAVE_SYS_MMAN_H && HAVE_SYS_STAT_H
#include <fcntl.h>
@@ -531,6 +535,163 @@ CairoFreeTypeFont *CairoFreeTypeFont::create(GfxFont *gfxFont, XRef *xref,
return NULL;
}
+//------------------------------------------------------------------------
+// CairoType3Font
+//------------------------------------------------------------------------
+
+static const cairo_user_data_key_t type3_font_key = {0};
+
+typedef struct _type3_font_info {
+ GfxFont *font;
+ XRef *xref;
+ Catalog *catalog;
+ CairoFontEngine *fontEngine;
+} type3_font_info_t;
+
+static void
+_free_type3_font_info(void *closure)
+{
+ type3_font_info_t *info = (type3_font_info_t *) closure;
+
+ info->font->decRefCnt();
+ free (info);
+}
+
+static cairo_status_t
+_render_type3_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *metrics)
+{
+ Dict *charProcs;
+ Object charProc;
+ CairoOutputDev *output_dev;
+ cairo_matrix_t matrix;
+ double *mat;
+ double wx, wy;
+ PDFRectangle box;
+ type3_font_info_t *info;
+ GfxFont *font;
+ Dict *resDict;
+ Gfx *gfx;
+
+ info = (type3_font_info_t *)
+ cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
+ &type3_font_key);
+
+ font = info->font;
+ resDict = ((Gfx8BitFont *)font)->getResources();
+ charProcs = ((Gfx8BitFont *)(info->font))->getCharProcs();
+ if (!charProcs)
+ return CAIRO_STATUS_USER_FONT_ERROR;
+
+ if ((int)glyph >= charProcs->getLength())
+ return CAIRO_STATUS_USER_FONT_ERROR;
+
+ mat = font->getFontMatrix();
+ matrix.xx = mat[0];
+ matrix.yx = mat[1];
+ matrix.xy = mat[2];
+ matrix.yy = mat[3];
+ matrix.x0 = mat[4];
+ matrix.y0 = mat[5];
+ cairo_transform (cr, &matrix);
+ cairo_matrix_init_scale (&matrix, 1, -1);
+ cairo_transform (cr, &matrix);
+
+ output_dev = new CairoOutputDev();
+ output_dev->setCairo(cr);
+
+ box.x1 = mat[0];
+ box.y1 = mat[1];
+ box.x2 = mat[2];
+ box.y2 = mat[3];
+ gfx = new Gfx(info->xref, output_dev, resDict, info->catalog, &box, NULL);
+ output_dev->startDoc(info->xref, info->catalog, info->fontEngine);
+ output_dev->startPage (1, gfx->getState());
+ output_dev->setInType3Char(gTrue);
+ gfx->display(charProcs->getVal(glyph, &charProc));
+
+ output_dev->getType3GlyphWidth (&wx, &wy);
+ metrics->x_advance = wx;
+ metrics->y_advance = wy;
+ if (output_dev->hasType3GlyphBBox()) {
+ double *bbox = output_dev->getType3GlyphBBox();
+
+ cairo_matrix_transform_point (&matrix, &bbox[0], &bbox[1]);
+ cairo_matrix_transform_point (&matrix, &bbox[2], &bbox[3]);
+ metrics->x_bearing = bbox[0];
+ metrics->y_bearing = bbox[1];
+ metrics->width = bbox[2] - bbox[0];
+ metrics->height = bbox[3] - bbox[1];
+ }
+
+ delete gfx;
+ delete output_dev;
+ charProc.free();
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
+CairoType3Font *CairoType3Font::create(GfxFont *gfxFont, XRef *xref,
+ Catalog *catalog, CairoFontEngine *fontEngine) {
+ Object refObj, strObj;
+ type3_font_info_t *info;
+ cairo_font_face_t *font_face;
+ Ref ref;
+ Gushort *codeToGID;
+ int codeToGIDLen;
+ int i, j;
+ char **enc;
+ Dict *charProcs;
+ char *name;
+
+ charProcs = ((Gfx8BitFont *)gfxFont)->getCharProcs();
+ info = (type3_font_info_t *) malloc(sizeof(*info));
+ ref = *gfxFont->getID();
+ font_face = cairo_user_font_face_create();
+ cairo_user_font_face_set_render_glyph_func (font_face, _render_type3_glyph);
+ gfxFont->incRefCnt();
+ info->font = gfxFont;
+ info->xref = xref;
+ info->catalog = catalog;
+ info->fontEngine = fontEngine;
+
+ cairo_font_face_set_user_data (font_face, &type3_font_key, (void *) info, _free_type3_font_info);
+
+ enc = ((Gfx8BitFont *)gfxFont)->getEncoding();
+ codeToGID = (Gushort *)gmallocn(256, sizeof(int));
+ codeToGIDLen = 256;
+ for (i = 0; i < 256; ++i) {
+ codeToGID[i] = 0;
+ if ((name = enc[i])) {
+ for (j = 0; j < charProcs->getLength(); j++) {
+ if (strcmp(name, charProcs->getKey(j)) == 0) {
+ codeToGID[i] = (Gushort) j;
+ }
+ }
+ }
+ }
+
+ return new CairoType3Font(ref, xref, catalog, font_face, codeToGID, codeToGIDLen);
+}
+
+CairoType3Font::CairoType3Font(Ref ref,
+ XRef *xref,
+ Catalog *cat,
+ cairo_font_face_t *cairo_font_face,
+ Gushort *codeToGID,
+ int codeToGIDLen) : CairoFont(ref,
+ cairo_font_face,
+ codeToGID,
+ codeToGIDLen,
+ gFalse),
+ xref(xref),
+ catalog(catalog) { }
+
+CairoType3Font::~CairoType3Font() { }
+
//------------------------------------------------------------------------
// CairoFontEngine
@@ -567,12 +728,6 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog) {
CairoFont *font;
GfxFontType fontType;
- fontType = gfxFont->getType();
- if (fontType == fontType3) {
- /* Need to figure this out later */
- // return NULL;
- }
-
ref = *gfxFont->getID();
for (i = 0; i < cairoFontCacheSize; ++i) {
@@ -586,7 +741,12 @@ CairoFontEngine::getFont(GfxFont *gfxFont, XRef *xref, Catalog *catalog) {
}
}
- font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
+ fontType = gfxFont->getType();
+ if (fontType == fontType3)
+ font = CairoType3Font::create (gfxFont, xref, catalog, this);
+ else
+ font = CairoFreeTypeFont::create (gfxFont, xref, lib, useCIDs);
+
//XXX: if font is null should we still insert it into the cache?
if (fontCache[cairoFontCacheSize - 1]) {
delete fontCache[cairoFontCacheSize - 1];
diff --git a/poppler/CairoFontEngine.h b/poppler/CairoFontEngine.h
index 1f25026..2474dc6 100644
--- a/poppler/CairoFontEngine.h
+++ b/poppler/CairoFontEngine.h
@@ -37,6 +37,8 @@
#include "GfxFont.h"
#include "Catalog.h"
+class CairoFontEngine;
+
class CairoFont {
public:
CairoFont(Ref ref,
@@ -77,6 +79,22 @@ private:
//------------------------------------------------------------------------
+class CairoType3Font : public CairoFont {
+public:
+ static CairoType3Font *create(GfxFont *gfxFont, XRef *xref,
+ Catalog *catalog, CairoFontEngine *fontEngine);
+ virtual ~CairoType3Font();
+
+private:
+ CairoType3Font(Ref ref, XRef *xref, Catalog *catalog,
+ cairo_font_face_t *cairo_font_face,
+ Gushort *codeToGID, int codeToGIDLen);
+ XRef *xref;
+ Catalog *catalog;
+};
+
+//------------------------------------------------------------------------
+
#define cairoFontCacheSize 64
//------------------------------------------------------------------------
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 3a9d452..70911b5 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -126,6 +126,7 @@ CairoOutputDev::CairoOutputDev() {
currentFont = NULL;
prescaleImages = gTrue;
printing = gTrue;
+ inType3Char = gFalse;
t3_glyph_has_bbox = gFalse;
groupColorSpaceStack = NULL;
@@ -415,9 +416,6 @@ void CairoOutputDev::updateFont(GfxState *state) {
needFontUpdate = gFalse;
- if (state->getFont()->getType() == fontType3)
- return;
-
currentFont = fontEngine->getFont (state->getFont(), xref, catalog);
if (!currentFont)
@@ -440,6 +438,11 @@ void CairoOutputDev::updateFont(GfxState *state) {
matrix.yy = -m[3] * fontSize;
matrix.x0 = 0;
matrix.y0 = 0;
+ if (inType3Char) {
+ cairo_matrix_t m;
+ cairo_matrix_init_scale (&m, 1, -1);
+ cairo_matrix_multiply (&matrix, &m, &matrix);
+ }
cairo_set_font_matrix (cairo, &matrix);
}
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index b57f734..878d3e3 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -99,7 +99,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
@@ -214,6 +214,7 @@ public:
void setCairo (cairo_t *cr);
void setPrinting (GBool printing) { this->printing = printing; }
+ void setInType3Char(GBool inType3Char) { this->inType3Char = inType3Char; }
void getType3GlyphWidth (double *wx, double *wy) { *wx = t3_glyph_wx; *wy = t3_glyph_wy; }
GBool hasType3GlyphBBox () { return t3_glyph_has_bbox; }
double *getType3GlyphBBox () { return t3_glyph_bbox; }
@@ -244,6 +245,7 @@ protected:
cairo_glyph_t *glyphs;
int glyphCount;
cairo_path_t *textClipPath;
+ GBool inType3Char; // inside a Type 3 CharProc
double t3_glyph_wx, t3_glyph_wy;
GBool t3_glyph_has_bbox;
double t3_glyph_bbox[4];
--
1.5.6.3
--------------090504070501070603020308
Content-Type: text/x-patch;
name="0007-Require-cairo-1.8.2-for-user-font-support.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename*0="0007-Require-cairo-1.8.2-for-user-font-support.patch"
More information about the poppler
mailing list