Fix text rendering on windows (font size was incorrect throwing off intra-glyph spacing and line spacing)

This commit is contained in:
Kovid Goyal 2013-01-03 13:34:31 +05:30
parent f1863d3971
commit b33929bbae
5 changed files with 33 additions and 22 deletions

View File

@ -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)
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

View File

@ -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<QFontEngineWin *>(ti.fontEngine);
size = fe->tm.tmHeight;
}
#endif
int synthesized = ti.fontEngine->synthesized();
qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.;
QVarLengthArray<glyph_t> glyphs;
QVarLengthArray<QFixedPoint> positions;
QTransform m = QTransform::fromTranslate(p.x(), p.y());
fe->getGlyphPositions(ti.glyphs, m, ti.flags, glyphs, positions);
QVector<QPointF> points = QVector<QPointF>(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<const quint32 *>("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<QPointF> &positions, const QVector<unsigned int> &indices) :name(name), positions(positions), size(size), indices(indices) {
GlyphInfo::GlyphInfo(const QByteArray& name, qreal size, qreal stretch, const QVector<QPointF> &positions, const QVector<unsigned int> &indices) :name(name), positions(positions), size(size), stretch(stretch), indices(indices) {
}
QByteArray get_sfnt_table(const QTextItem &text_item, const char* tag_name) {

View File

@ -17,9 +17,10 @@ class GlyphInfo {
QByteArray name;
QVector<QPointF> positions;
qreal size;
qreal stretch;
QVector<unsigned int> indices;
GlyphInfo(const QByteArray &name, qreal size, const QVector<QPointF> &positions, const QVector<unsigned int> &indices);
GlyphInfo(const QByteArray &name, qreal size, qreal stretch, const QVector<QPointF> &positions, const QVector<unsigned int> &indices);
private:
GlyphInfo(const GlyphInfo&);

View File

@ -13,9 +13,10 @@ class GlyphInfo {
public:
QByteArray name;
qreal size;
qreal stretch;
QVector<QPointF> &positions;
QVector<unsigned int> indices;
GlyphInfo(const QByteArray &name, qreal size, const QVector<QPointF> &positions, const QVector<unsigned int> &indices);
GlyphInfo(const QByteArray &name, qreal size, qreal stretch, const QVector<QPointF> &positions, const QVector<unsigned int> &indices);
private:
GlyphInfo(const GlyphInfo& g);

View File

@ -8,7 +8,6 @@ __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__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)