mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix text rendering on windows (font size was incorrect throwing off intra-glyph spacing and line spacing)
This commit is contained in:
parent
f1863d3971
commit
b33929bbae
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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&);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user