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.serialize import (PDFStream, Path)
|
||||||
from calibre.ebooks.pdf.render.common import inch, A4, fmtnum
|
from calibre.ebooks.pdf.render.common import inch, A4, fmtnum
|
||||||
from calibre.ebooks.pdf.render.graphics import convert_path, Graphics
|
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
|
from calibre.utils.fonts.sfnt.metrics import FontMetrics
|
||||||
|
|
||||||
Point = namedtuple('Point', 'x y')
|
Point = namedtuple('Point', 'x y')
|
||||||
@ -224,7 +224,11 @@ class PdfEngine(QPaintEngine):
|
|||||||
|
|
||||||
def create_sfnt(self, text_item):
|
def create_sfnt(self, text_item):
|
||||||
get_table = partial(self.qt_hack.get_sfnt_table, 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)
|
glyph_map = self.qt_hack.get_glyph_map(text_item)
|
||||||
gm = {}
|
gm = {}
|
||||||
for uc, glyph_id in enumerate(glyph_map):
|
for uc, glyph_id in enumerate(glyph_map):
|
||||||
@ -251,18 +255,14 @@ class PdfEngine(QPaintEngine):
|
|||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
pass
|
pass
|
||||||
glyphs = []
|
glyphs = []
|
||||||
pdf_pos = point
|
last_x = last_y = 0
|
||||||
first_baseline = None
|
|
||||||
for i, pos in enumerate(gi.positions):
|
for i, pos in enumerate(gi.positions):
|
||||||
if first_baseline is None:
|
x, y = pos.x(), pos.y()
|
||||||
first_baseline = pos.y()
|
glyphs.append((x-last_x, last_y - y, gi.indices[i]))
|
||||||
glyph_pos = pos
|
last_x, last_y = x, y
|
||||||
delta = glyph_pos - pdf_pos
|
|
||||||
glyphs.append((delta.x(), pos.y()-first_baseline, gi.indices[i]))
|
|
||||||
pdf_pos = glyph_pos
|
|
||||||
|
|
||||||
self.pdf.draw_glyph_run([1, 0, 0, -1, point.x(),
|
self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics,
|
||||||
point.y()], gi.size, metrics, glyphs)
|
glyphs)
|
||||||
sip.delete(gi)
|
sip.delete(gi)
|
||||||
|
|
||||||
@store_error
|
@store_error
|
||||||
|
@ -17,18 +17,23 @@ GlyphInfo* get_glyphs(QPointF &p, const QTextItem &text_item) {
|
|||||||
QFontEngine *fe = ti.fontEngine;
|
QFontEngine *fe = ti.fontEngine;
|
||||||
qreal size = ti.fontEngine->fontDef.pixelSize;
|
qreal size = ti.fontEngine->fontDef.pixelSize;
|
||||||
#ifdef Q_WS_WIN
|
#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);
|
QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
|
||||||
size = fe->tm.tmHeight;
|
size = fe->tm.tmHeight;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
int synthesized = ti.fontEngine->synthesized();
|
||||||
|
qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.;
|
||||||
|
|
||||||
QVarLengthArray<glyph_t> glyphs;
|
QVarLengthArray<glyph_t> glyphs;
|
||||||
QVarLengthArray<QFixedPoint> positions;
|
QVarLengthArray<QFixedPoint> positions;
|
||||||
QTransform m = QTransform::fromTranslate(p.x(), p.y());
|
QTransform m = QTransform::fromTranslate(p.x(), p.y());
|
||||||
fe->getGlyphPositions(ti.glyphs, m, ti.flags, glyphs, positions);
|
fe->getGlyphPositions(ti.glyphs, m, ti.flags, glyphs, positions);
|
||||||
QVector<QPointF> points = QVector<QPointF>(positions.count());
|
QVector<QPointF> points = QVector<QPointF>(positions.count());
|
||||||
for (int i = 0; i < positions.count(); i++) {
|
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());
|
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");
|
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) {
|
QByteArray get_sfnt_table(const QTextItem &text_item, const char* tag_name) {
|
||||||
|
@ -17,9 +17,10 @@ class GlyphInfo {
|
|||||||
QByteArray name;
|
QByteArray name;
|
||||||
QVector<QPointF> positions;
|
QVector<QPointF> positions;
|
||||||
qreal size;
|
qreal size;
|
||||||
|
qreal stretch;
|
||||||
QVector<unsigned int> indices;
|
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:
|
private:
|
||||||
GlyphInfo(const GlyphInfo&);
|
GlyphInfo(const GlyphInfo&);
|
||||||
|
@ -13,9 +13,10 @@ class GlyphInfo {
|
|||||||
public:
|
public:
|
||||||
QByteArray name;
|
QByteArray name;
|
||||||
qreal size;
|
qreal size;
|
||||||
|
qreal stretch;
|
||||||
QVector<QPointF> &positions;
|
QVector<QPointF> &positions;
|
||||||
QVector<unsigned int> indices;
|
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:
|
private:
|
||||||
GlyphInfo(const GlyphInfo& g);
|
GlyphInfo(const GlyphInfo& g);
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from tempfile import gettempdir
|
|
||||||
|
|
||||||
from PyQt4.Qt import (QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF,
|
from PyQt4.Qt import (QBrush, QColor, QPoint, QPixmap, QPainterPath, QRectF,
|
||||||
QApplication, QPainter, Qt, QImage, QLinearGradient,
|
QApplication, QPainter, Qt, QImage, QLinearGradient,
|
||||||
@ -99,14 +98,19 @@ def pen(p, xmax, ymax):
|
|||||||
p.drawRect(0, xmax/3, xmax/3, xmax/2)
|
p.drawRect(0, xmax/3, xmax/3, xmax/2)
|
||||||
|
|
||||||
def text(p, xmax, ymax):
|
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():
|
def main():
|
||||||
app = QApplication([])
|
app = QApplication([])
|
||||||
app
|
app
|
||||||
tdir = gettempdir()
|
tdir = os.path.abspath('.')
|
||||||
pdf = os.path.join(tdir, 'painter.pdf')
|
pdf = os.path.join(tdir, 'painter.pdf')
|
||||||
func = full
|
func = text
|
||||||
dpi = 100
|
dpi = 100
|
||||||
with open(pdf, 'wb') as f:
|
with open(pdf, 'wb') as f:
|
||||||
dev = PdfDevice(f, xdpi=dpi, ydpi=dpi, compress=False)
|
dev = PdfDevice(f, xdpi=dpi, ydpi=dpi, compress=False)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user