Commit fee13e93 authored by Oliver Sander's avatar Oliver Sander Committed by Albert Astals Cid
Browse files

Implement Type3 font support for ArthurOutputDev

parent 79c58891
......@@ -51,6 +51,9 @@
#include "FontEncodingTables.h"
#include <fofi/FoFiTrueType.h>
#include "ArthurOutputDev.h"
#include "Page.h"
#include "Gfx.h"
#include "PDFDoc.h"
#include <QtCore/QtDebug>
#include <QRawFont>
......@@ -87,6 +90,86 @@ private:
#endif
class ArthurType3Font
{
public:
ArthurType3Font(PDFDoc* doc, Gfx8BitFont* font);
const QPicture& getGlyph(int gid) const;
private:
PDFDoc* m_doc;
Gfx8BitFont* m_font;
mutable std::vector<std::unique_ptr<QPicture> > glyphs;
public:
std::vector<int> codeToGID;
};
ArthurType3Font::ArthurType3Font(PDFDoc* doc, Gfx8BitFont* font)
: m_doc(doc), m_font(font)
{
char *name;
const Dict* charProcs = font->getCharProcs();
// Storage for the rendered glyphs
glyphs.resize(charProcs->getLength());
// Compute the code-to-GID map
char **enc = font->getEncoding();
codeToGID.resize(256);
for (int i = 0; i < 256; ++i) {
codeToGID[i] = 0;
if (charProcs && (name = enc[i])) {
for (int j = 0; j < charProcs->getLength(); j++) {
if (strcmp(name, charProcs->getKey(j)) == 0) {
codeToGID[i] = j;
}
}
}
}
}
const QPicture& ArthurType3Font::getGlyph(int gid) const
{
if (!glyphs[gid]) {
// Glyph has not been rendered before: render it now
// Smallest box that contains all the glyphs from this font
const double* fontBBox = m_font->getFontBBox();
PDFRectangle box(fontBBox[0], fontBBox[1], fontBBox[2], fontBBox[3]);
Dict* resDict = m_font->getResources();
QPainter glyphPainter;
glyphs[gid] = std::unique_ptr<QPicture>(new QPicture);
glyphPainter.begin(glyphs[gid].get());
std::unique_ptr<ArthurOutputDev> output_dev(new ArthurOutputDev(&glyphPainter));
std::unique_ptr<Gfx> gfx(new Gfx(m_doc, output_dev.get(), resDict,
&box, // pagebox
nullptr)); // cropBox
output_dev->startDoc(m_doc);
output_dev->startPage (1, gfx->getState(), gfx->getXRef());
const Dict* charProcs = m_font->getCharProcs();
Object charProc = charProcs->getVal(gid);
gfx->display(&charProc);
glyphPainter.end();
}
return *glyphs[gid];
}
//------------------------------------------------------------------------
// ArthurOutputDev
//------------------------------------------------------------------------
......@@ -107,8 +190,9 @@ ArthurOutputDev::~ArthurOutputDev()
#endif
}
void ArthurOutputDev::startDoc(XRef *xrefA) {
xref = xrefA;
void ArthurOutputDev::startDoc(PDFDoc* doc) {
xref = doc->getXRef();
m_doc = doc;
#ifdef HAVE_SPLASH
delete m_fontEngine;
......@@ -134,6 +218,7 @@ void ArthurOutputDev::saveState(GfxState *state)
m_currentPenStack.push(m_currentPen);
m_currentBrushStack.push(m_currentBrush);
m_rawFontStack.push(m_rawFont);
m_type3FontStack.push(m_currentType3Font);
m_codeToGIDStack.push(m_codeToGID);
m_painter.top()->save();
......@@ -147,6 +232,8 @@ void ArthurOutputDev::restoreState(GfxState *state)
m_codeToGIDStack.pop();
m_rawFont = m_rawFontStack.top();
m_rawFontStack.pop();
m_currentType3Font = m_type3FontStack.top();
m_type3FontStack.pop();
m_currentBrush = m_currentBrushStack.top();
m_currentBrushStack.pop();
m_currentPen = m_currentPenStack.top();
......@@ -362,8 +449,30 @@ void ArthurOutputDev::updateFont(GfxState *state)
return;
}
// is the font in the cache?
// The key to look in the font caches
ArthurFontID fontID = {*gfxFont->getID(), state->getFontSize()};
// Current font is a type3 font
if (gfxFont->getType() == fontType3)
{
auto cacheEntry = m_type3FontCache.find(fontID);
if (cacheEntry!=m_type3FontCache.end()) {
// Take the font from the cache
m_currentType3Font = cacheEntry->second.get();
} else {
m_currentType3Font = new ArthurType3Font(m_doc, (Gfx8BitFont*)gfxFont);
m_type3FontCache.insert(std::make_pair(fontID,std::unique_ptr<ArthurType3Font>(m_currentType3Font)));
}
return;
}
// Non-type3: is the font in the cache?
auto cacheEntry = m_rawFontCache.find(fontID);
if (cacheEntry!=m_rawFontCache.end()) {
......@@ -818,6 +927,52 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
double originX, double originY,
CharCode code, int nBytes, Unicode *u, int uLen) {
// First handle type3 fonts
GfxFont *gfxFont = state->getFont();
GfxFontType fontType = gfxFont->getType();
if (fontType == fontType3) {
/////////////////////////////////////////////////////////////////////
// Draw the QPicture that contains the glyph onto the page
/////////////////////////////////////////////////////////////////////
// Store the QPainter state; we need to modify it temporarily
m_painter.top()->save();
// Make the glyph position the coordinate origin -- that's our center of scaling
m_painter.top()->translate(QPointF(x-originX, y-originY));
const double* mat = gfxFont->getFontMatrix();
QTransform fontMatrix(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
// Scale with the font size
fontMatrix.scale(state->getFontSize(), state->getFontSize());
m_painter.top()->setTransform(fontMatrix,true);
// Apply the text matrix on top
const double *textMat = state->getTextMat();
QTransform textTransform(textMat[0] * state->getHorizScaling(),
textMat[1] * state->getHorizScaling(),
textMat[2],
textMat[3],
0,
0);
m_painter.top()->setTransform(textTransform,true);
// Actually draw the glyph
int gid = m_currentType3Font->codeToGID[code];
m_painter.top()->drawPicture(QPointF(0,0), m_currentType3Font->getGlyph(gid));
// Restore transformation
m_painter.top()->restore();
return;
}
// check for invisible text -- this is used by Acrobat Capture
int render = state->getRender();
if (render == 3 || !m_rawFont) {
......@@ -825,11 +980,6 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
return;
}
// Don't do anything for type3 fonts -- they are not yet supported
if (state->getFont()->getType() == fontType3) {
return;
}
if (!(render & 1))
{
quint32 glyphIndex = (m_codeToGID) ? m_codeToGID[code] : code;
......@@ -889,17 +1039,6 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
}
}
GBool ArthurOutputDev::beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen)
{
return gFalse;
}
void ArthurOutputDev::endType3Char(GfxState *state)
{
}
void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy)
{
}
......
......@@ -45,11 +45,14 @@
#include <QtGui/QPainter>
class GfxState;
class PDFDoc;
class SplashFontEngine;
class QRawFont;
class ArthurType3Font;
//------------------------------------------------------------------------
// ArthurOutputDev - Qt 5 QPainter renderer
//------------------------------------------------------------------------
......@@ -143,10 +146,6 @@ public:
double dx, double dy,
double originX, double originY,
CharCode code, int nBytes, Unicode *u, int uLen) override;
GBool beginType3Char(GfxState *state, double x, double y,
double dx, double dy,
CharCode code, Unicode *u, int uLen) override;
void endType3Char(GfxState *state) override;
void endTextObject(GfxState *state) override;
//----- image drawing
......@@ -182,8 +181,8 @@ public:
//----- special access
// Called to indicate that a new PDF document has been loaded.
void startDoc(XRef *xrefA);
void startDoc(PDFDoc* doc);
GBool isReverseVideo() { return gFalse; }
private:
......@@ -211,12 +210,16 @@ private:
GBool m_needFontUpdate; // set when the font needs to be updated
SplashFontEngine *m_fontEngine;
PDFDoc* m_doc;
XRef *xref; // xref table for current document
// The current font in use
QRawFont* m_rawFont;
std::stack<QRawFont*> m_rawFontStack;
ArthurType3Font* m_currentType3Font;
std::stack<ArthurType3Font*> m_type3FontStack;
// Identify a font by its 'Ref' and its font size
struct ArthurFontID
{
......@@ -232,6 +235,7 @@ private:
// Cache all fonts
std::map<ArthurFontID,std::unique_ptr<QRawFont> > m_rawFontCache;
std::map<ArthurFontID,std::unique_ptr<ArthurType3Font> > m_type3FontCache;
// The table that maps character codes to glyph indexes
int* m_codeToGID;
......
......@@ -17,7 +17,7 @@
* Copyright (C) 2015 William Bader <williambader@hotmail.com>
* Copyright (C) 2016 Arseniy Lartsev <arseniy@alumni.chalmers.se>
* Copyright (C) 2016, Hanno Meyer-Thurow <h.mth@web.de>
* Copyright (C) 2017, Oliver Sander <oliver.sander@tu-dresden.de>
* Copyright (C) 2017, 2018, Oliver Sander <oliver.sander@tu-dresden.de>
* Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
* Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
*
......@@ -456,7 +456,7 @@ static bool renderToArthur(QImageDumpingArthurOutputDev *arthur_output, QPainter
painter->setRenderHint(QPainter::TextAntialiasing);
painter->translate(x == -1 ? 0 : -x, y == -1 ? 0 : -y);
arthur_output->startDoc(page->parentDoc->doc->getXRef());
arthur_output->startDoc(page->parentDoc->doc);
const GBool hideAnnotations = page->parentDoc->m_hints & Document::HideAnnotations;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment