aboutsummaryrefslogtreecommitdiff
path: root/splash/SplashFontEngine.cc
diff options
context:
space:
mode:
Diffstat (limited to 'splash/SplashFontEngine.cc')
-rw-r--r--splash/SplashFontEngine.cc409
1 files changed, 409 insertions, 0 deletions
diff --git a/splash/SplashFontEngine.cc b/splash/SplashFontEngine.cc
new file mode 100644
index 0000000..81afe0c
--- /dev/null
+++ b/splash/SplashFontEngine.cc
@@ -0,0 +1,409 @@
+//========================================================================
+//
+// SplashFontEngine.cc
+//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
+//========================================================================
+
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+#include "gmem.h"
+#include "gmempp.h"
+#include "GString.h"
+#include "GList.h"
+#include "SplashMath.h"
+#include "SplashFTFontEngine.h"
+#include "SplashFontFile.h"
+#include "SplashFontFileID.h"
+#include "SplashFont.h"
+#include "SplashFontEngine.h"
+
+#ifdef VMS
+#if (__VMS_VER < 70000000)
+extern "C" int unlink(char *filename);
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// SplashFontEngine
+//------------------------------------------------------------------------
+
+SplashFontEngine::SplashFontEngine(
+#if HAVE_FREETYPE_H
+ GBool enableFreeType,
+ Guint freeTypeFlags,
+#endif
+ GBool aa) {
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ fontCache[i] = NULL;
+ }
+ badFontFiles = new GList();
+
+#if HAVE_FREETYPE_H
+ if (enableFreeType) {
+ ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags);
+ } else {
+ ftEngine = NULL;
+ }
+#endif
+}
+
+SplashFontEngine::~SplashFontEngine() {
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ if (fontCache[i]) {
+ delete fontCache[i];
+ }
+ }
+ deleteGList(badFontFiles, SplashFontFileID);
+
+#if HAVE_FREETYPE_H
+ if (ftEngine) {
+ delete ftEngine;
+ }
+#endif
+}
+
+SplashFontFile *SplashFontEngine::getFontFile(SplashFontFileID *id) {
+ SplashFontFile *fontFile;
+ int i;
+
+ for (i = 0; i < splashFontCacheSize; ++i) {
+ if (fontCache[i]) {
+ fontFile = fontCache[i]->getFontFile();
+ if (fontFile && fontFile->getID()->matches(id)) {
+ return fontFile;
+ }
+ }
+ }
+ return NULL;
+}
+
+GBool SplashFontEngine::checkForBadFontFile(SplashFontFileID *id) {
+ for (int i = 0; i < badFontFiles->getLength(); ++i) {
+ if (((SplashFontFileID *)badFontFiles->get(i))->matches(id)) {
+ return gTrue;
+ }
+ }
+ return gFalse;
+}
+
+SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadType1Font(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadType1CFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ const char **enc) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadOpenTypeT1CFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ enc);
+ }
+#endif
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadCIDFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int *codeToGID,
+ int codeToGIDLen) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadOpenTypeCFFFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
+#if LOAD_FONTS_FROM_MEM
+ GString *fontBuf,
+#else
+ char *fileName,
+ GBool deleteFile,
+#endif
+ int fontNum,
+ int *codeToGID,
+ int codeToGIDLen,
+ char *fontName) {
+ SplashFontFile *fontFile;
+
+ fontFile = NULL;
+#if HAVE_FREETYPE_H
+ if (!fontFile && ftEngine) {
+ fontFile = ftEngine->loadTrueTypeFont(idA,
+#if LOAD_FONTS_FROM_MEM
+ fontBuf,
+#else
+ fileName, deleteFile,
+#endif
+ fontNum, codeToGID, codeToGIDLen);
+ }
+#endif
+
+ if (!fontFile) {
+ gfree(codeToGID);
+ }
+
+#if !LOAD_FONTS_FROM_MEM && !defined(_WIN32) && !defined(__ANDROID__)
+ // delete the (temporary) font file -- with Unix hard link
+ // semantics, this will remove the last link; otherwise it will
+ // return an error, leaving the file to be deleted later (if
+ // loadXYZFont failed, the file will always be deleted)
+ if (deleteFile) {
+ unlink(fontFile ? fontFile->fileName->getCString() : fileName);
+ }
+#endif
+
+ if (!fontFile) {
+ badFontFiles->append(idA);
+ }
+
+ return fontFile;
+}
+
+SplashFont *SplashFontEngine::getFont(SplashFontFile *fontFile,
+ SplashCoord *textMat,
+ SplashCoord *ctm) {
+ SplashCoord mat[4];
+ SplashFont *font;
+ int i, j;
+
+ mat[0] = textMat[0] * ctm[0] + textMat[1] * ctm[2];
+ mat[1] = -(textMat[0] * ctm[1] + textMat[1] * ctm[3]);
+ mat[2] = textMat[2] * ctm[0] + textMat[3] * ctm[2];
+ mat[3] = -(textMat[2] * ctm[1] + textMat[3] * ctm[3]);
+ if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.01)) {
+ // avoid a singular (or close-to-singular) matrix
+ mat[0] = 0.01; mat[1] = 0;
+ mat[2] = 0; mat[3] = 0.01;
+ }
+
+ font = fontCache[0];
+ if (font && font->matches(fontFile, mat, textMat)) {
+ return font;
+ }
+ for (i = 1; i < splashFontCacheSize; ++i) {
+ font = fontCache[i];
+ if (font && font->matches(fontFile, mat, textMat)) {
+ for (j = i; j > 0; --j) {
+ fontCache[j] = fontCache[j-1];
+ }
+ fontCache[0] = font;
+ return font;
+ }
+ }
+ font = fontFile->makeFont(mat, textMat);
+ if (fontCache[splashFontCacheSize - 1]) {
+ delete fontCache[splashFontCacheSize - 1];
+ }
+ for (j = splashFontCacheSize - 1; j > 0; --j) {
+ fontCache[j] = fontCache[j-1];
+ }
+ fontCache[0] = font;
+ return font;
+}