From b33929bbae37496a2a35e4cc41d576001677350f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 3 Jan 2013 13:34:31 +0530 Subject: [PATCH] Fix text rendering on windows (font size was incorrect throwing off intra-glyph spacing and line spacing) --- src/calibre/ebooks/pdf/render/engine.py | 24 +++++++++++------------ src/calibre/ebooks/pdf/render/qt_hack.cpp | 13 ++++++++---- src/calibre/ebooks/pdf/render/qt_hack.h | 3 ++- src/calibre/ebooks/pdf/render/qt_hack.sip | 3 ++- src/calibre/ebooks/pdf/render/test.py | 12 ++++++++---- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/calibre/ebooks/pdf/render/engine.py b/src/calibre/ebooks/pdf/render/engine.py index b65aed0660..149d75d1f0 100644 --- a/src/calibre/ebooks/pdf/render/engine.py +++ b/src/calibre/ebooks/pdf/render/engine.py @@ -19,7 +19,7 @@ from calibre.constants import plugins from calibre.ebooks.pdf.render.serialize import (PDFStream, Path) from calibre.ebooks.pdf.render.common import inch, A4, fmtnum from calibre.ebooks.pdf.render.graphics import convert_path, Graphics -from calibre.utils.fonts.sfnt.container import Sfnt +from calibre.utils.fonts.sfnt.container import Sfnt, UnsupportedFont from calibre.utils.fonts.sfnt.metrics import FontMetrics Point = namedtuple('Point', 'x y') @@ -224,7 +224,11 @@ class PdfEngine(QPaintEngine): def create_sfnt(self, text_item): get_table = partial(self.qt_hack.get_sfnt_table, text_item) - ans = Font(Sfnt(get_table)) + try: + ans = Font(Sfnt(get_table)) + except UnsupportedFont as e: + raise UnsupportedFont('The font %s is not a valid sfnt. Error: %s'%( + text_item.font().family(), e)) glyph_map = self.qt_hack.get_glyph_map(text_item) gm = {} for uc, glyph_id in enumerate(glyph_map): @@ -251,18 +255,14 @@ class PdfEngine(QPaintEngine): except (KeyError, ValueError): pass glyphs = [] - pdf_pos = point - first_baseline = None + last_x = last_y = 0 for i, pos in enumerate(gi.positions): - if first_baseline is None: - first_baseline = pos.y() - glyph_pos = pos - delta = glyph_pos - pdf_pos - glyphs.append((delta.x(), pos.y()-first_baseline, gi.indices[i])) - pdf_pos = glyph_pos + x, y = pos.x(), pos.y() + glyphs.append((x-last_x, last_y - y, gi.indices[i])) + last_x, last_y = x, y - self.pdf.draw_glyph_run([1, 0, 0, -1, point.x(), - point.y()], gi.size, metrics, glyphs) + self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics, + glyphs) sip.delete(gi) @store_error diff --git a/src/calibre/ebooks/pdf/render/qt_hack.cpp b/src/calibre/ebooks/pdf/render/qt_hack.cpp index f68f40c921..e5f74c0a0f 100644 --- a/src/calibre/ebooks/pdf/render/qt_hack.cpp +++ b/src/calibre/ebooks/pdf/render/qt_hack.cpp @@ -17,18 +17,23 @@ GlyphInfo* get_glyphs(QPointF &p, const QTextItem &text_item) { QFontEngine *fe = ti.fontEngine; qreal size = ti.fontEngine->fontDef.pixelSize; #ifdef Q_WS_WIN - if (ti.fontEngine->type() == QFontEngine::Win) { + if (false && ti.fontEngine->type() == QFontEngine::Win) { + // This is used in the Qt sourcecode, but it gives incorrect results, + // so I have disabled it. I dont understand how it works in qpdf.cpp QFontEngineWin *fe = static_cast(ti.fontEngine); size = fe->tm.tmHeight; } #endif + int synthesized = ti.fontEngine->synthesized(); + qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.; + QVarLengthArray glyphs; QVarLengthArray positions; QTransform m = QTransform::fromTranslate(p.x(), p.y()); fe->getGlyphPositions(ti.glyphs, m, ti.flags, glyphs, positions); QVector points = QVector(positions.count()); for (int i = 0; i < positions.count(); i++) { - points[i].setX(positions[i].x.toReal()); + points[i].setX(positions[i].x.toReal()/stretch); points[i].setY(positions[i].y.toReal()); } @@ -38,10 +43,10 @@ GlyphInfo* get_glyphs(QPointF &p, const QTextItem &text_item) { const quint32 *tag = reinterpret_cast("name"); - return new GlyphInfo(fe->getSfntTable(qToBigEndian(*tag)), size, points, indices); + return new GlyphInfo(fe->getSfntTable(qToBigEndian(*tag)), size, stretch, points, indices); } -GlyphInfo::GlyphInfo(const QByteArray& name, qreal size, const QVector &positions, const QVector &indices) :name(name), positions(positions), size(size), indices(indices) { +GlyphInfo::GlyphInfo(const QByteArray& name, qreal size, qreal stretch, const QVector &positions, const QVector &indices) :name(name), positions(positions), size(size), stretch(stretch), indices(indices) { } QByteArray get_sfnt_table(const QTextItem &text_item, const char* tag_name) { diff --git a/src/calibre/ebooks/pdf/render/qt_hack.h b/src/calibre/ebooks/pdf/render/qt_hack.h index d1cb5e208d..1bae8f2624 100644 --- a/src/calibre/ebooks/pdf/render/qt_hack.h +++ b/src/calibre/ebooks/pdf/render/qt_hack.h @@ -17,9 +17,10 @@ class GlyphInfo { QByteArray name; QVector positions; qreal size; + qreal stretch; QVector indices; - GlyphInfo(const QByteArray &name, qreal size, const QVector &positions, const QVector &indices); + GlyphInfo(const QByteArray &name, qreal size, qreal stretch, const QVector &positions, const QVector &indices); private: GlyphInfo(const GlyphInfo&); diff --git a/src/calibre/ebooks/pdf/render/qt_hack.sip b/src/calibre/ebooks/pdf/render/qt_hack.sip index b5a6fcf55e..54d8726f4d 100644 --- a/src/calibre/ebooks/pdf/render/qt_hack.sip +++ b/src/calibre/ebooks/pdf/render/qt_hack.sip @@ -13,9 +13,10 @@ class GlyphInfo { public: QByteArray name; qreal size; + qreal stretch; QVector &positions; QVector indices; - GlyphInfo(const QByteArray &name, qreal size, const QVector &positions, const QVector &indices); + GlyphInfo(const QByteArray &name, qreal size, qreal stretch, const QVector &positions, const QVector &indices); private: GlyphInfo(const GlyphInfo& g); diff --git a/src/calibre/ebooks/pdf/render/test.py b/src/calibre/ebooks/pdf/render/test.py index d57678a057..8c9c2f45bb 100644 --- a/src/calibre/ebooks/pdf/render/test.py +++ b/src/calibre/ebooks/pdf/render/test.py @@ -8,7 +8,6 @@ __copyright__ = '2012, Kovid Goyal ' __docformat__ = 'restructuredtext en' import os -from tempfile import gettempdir from PyQt4.Qt import (QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF, QApplication, QPainter, Qt, QImage, QLinearGradient, @@ -99,14 +98,19 @@ def pen(p, xmax, ymax): p.drawRect(0, xmax/3, xmax/3, xmax/2) def text(p, xmax, ymax): - p.drawText(QPoint(0, ymax/3), 'Text') + f = p.font() + f.setPixelSize(24) + f.setFamily('Candara') + p.setFont(f) + p.drawText(QPoint(0, 100), + 'Test intra glyph spacing ffagain imceo') def main(): app = QApplication([]) app - tdir = gettempdir() + tdir = os.path.abspath('.') pdf = os.path.join(tdir, 'painter.pdf') - func = full + func = text dpi = 100 with open(pdf, 'wb') as f: dev = PdfDevice(f, xdpi=dpi, ydpi=dpi, compress=False)