Fix stretched fonts with large pixel size
The Windows and Cocoa font engines ignored the stretch factor when the pixel size is so large that QPainterPath rendering is used instead of native. Fixes: QTBUG-14315 Change-Id: I93390528ac264452b7d6af7d39f49f4b0dd56279 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>bb10
parent
0ba8ed2c5f
commit
e20f4d966e
|
|
@ -491,9 +491,11 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
|
|||
|
||||
struct ConvertPathInfo
|
||||
{
|
||||
ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {}
|
||||
ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos, qreal newStretch = 1.0) :
|
||||
path(newPath), pos(newPos), stretch(newStretch) {}
|
||||
QPainterPath *path;
|
||||
QPointF pos;
|
||||
qreal stretch;
|
||||
};
|
||||
|
||||
static void convertCGPathToQPainterPath(void *info, const CGPathElement *element)
|
||||
|
|
@ -501,25 +503,25 @@ static void convertCGPathToQPainterPath(void *info, const CGPathElement *element
|
|||
ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info);
|
||||
switch(element->type) {
|
||||
case kCGPathElementMoveToPoint:
|
||||
myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(),
|
||||
myInfo->path->moveTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[0].y + myInfo->pos.y());
|
||||
break;
|
||||
case kCGPathElementAddLineToPoint:
|
||||
myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(),
|
||||
myInfo->path->lineTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[0].y + myInfo->pos.y());
|
||||
break;
|
||||
case kCGPathElementAddQuadCurveToPoint:
|
||||
myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(),
|
||||
myInfo->path->quadTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[0].y + myInfo->pos.y(),
|
||||
element->points[1].x + myInfo->pos.x(),
|
||||
(element->points[1].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[1].y + myInfo->pos.y());
|
||||
break;
|
||||
case kCGPathElementAddCurveToPoint:
|
||||
myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(),
|
||||
myInfo->path->cubicTo((element->points[0].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[0].y + myInfo->pos.y(),
|
||||
element->points[1].x + myInfo->pos.x(),
|
||||
(element->points[1].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[1].y + myInfo->pos.y(),
|
||||
element->points[2].x + myInfo->pos.x(),
|
||||
(element->points[2].x * myInfo->stretch) + myInfo->pos.x(),
|
||||
element->points[2].y + myInfo->pos.y());
|
||||
break;
|
||||
case kCGPathElementCloseSubpath:
|
||||
|
|
@ -543,9 +545,10 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position
|
|||
if (synthesisFlags & QFontEngine::SynthesizedItalic)
|
||||
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
|
||||
|
||||
qreal stretch = fontDef.stretch ? qreal(fontDef.stretch) / 100 : 1.0;
|
||||
for (int i = 0; i < nGlyphs; ++i) {
|
||||
QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix);
|
||||
ConvertPathInfo info(path, positions[i].toPointF());
|
||||
ConvertPathInfo info(path, positions[i].toPointF(), stretch);
|
||||
CGPathApply(cgpath, &info, convertCGPathToQPainterPath);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -702,8 +702,8 @@ static inline double qt_fixed_to_double(const FIXED &p) {
|
|||
return ((p.value << 16) + p.fract) / 65536.0;
|
||||
}
|
||||
|
||||
static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) {
|
||||
return QPointF(qt_fixed_to_double(pt.x) * scale, -qt_fixed_to_double(pt.y) * scale);
|
||||
static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale, qreal stretch) {
|
||||
return QPointF(qt_fixed_to_double(pt.x) * scale * stretch, -qt_fixed_to_double(pt.y) * scale);
|
||||
}
|
||||
|
||||
#ifndef GGO_UNHINTED
|
||||
|
|
@ -711,7 +711,8 @@ static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) {
|
|||
#endif
|
||||
|
||||
static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
|
||||
QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1)
|
||||
QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0,
|
||||
qreal scale = 1.0, qreal stretch = 1.0)
|
||||
{
|
||||
MAT2 mat;
|
||||
mat.eM11.value = mat.eM22.value = 1;
|
||||
|
|
@ -761,7 +762,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
|
|||
while (headerOffset < bufferSize) {
|
||||
const TTPOLYGONHEADER *ttph = reinterpret_cast<const TTPOLYGONHEADER *>(dataBuffer + headerOffset);
|
||||
|
||||
QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale));
|
||||
QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale, stretch));
|
||||
path->moveTo(lastPoint + oset);
|
||||
offset += sizeof(TTPOLYGONHEADER);
|
||||
while (offset < headerOffset + ttph->cb) {
|
||||
|
|
@ -769,7 +770,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
|
|||
switch (curve->wType) {
|
||||
case TT_PRIM_LINE: {
|
||||
for (int i=0; i<curve->cpfx; ++i) {
|
||||
QPointF p = qt_to_qpointf(curve->apfx[i], scale) + oset;
|
||||
QPointF p = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset;
|
||||
path->lineTo(p);
|
||||
}
|
||||
break;
|
||||
|
|
@ -779,8 +780,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
|
|||
QPointF prev(elm.x, elm.y);
|
||||
QPointF endPoint;
|
||||
for (int i=0; i<curve->cpfx - 1; ++i) {
|
||||
QPointF p1 = qt_to_qpointf(curve->apfx[i], scale) + oset;
|
||||
QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale) + oset;
|
||||
QPointF p1 = qt_to_qpointf(curve->apfx[i], scale, stretch) + oset;
|
||||
QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale, stretch) + oset;
|
||||
if (i < curve->cpfx - 2) {
|
||||
endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2);
|
||||
} else {
|
||||
|
|
@ -795,9 +796,9 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
|
|||
}
|
||||
case TT_PRIM_CSPLINE: {
|
||||
for (int i=0; i<curve->cpfx; ) {
|
||||
QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
|
||||
QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
|
||||
QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale) + oset;
|
||||
QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
|
||||
QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
|
||||
QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale, stretch) + oset;
|
||||
path->cubicTo(p2, p3, p4);
|
||||
}
|
||||
break;
|
||||
|
|
@ -829,9 +830,11 @@ void QWindowsFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions
|
|||
HDC hdc = m_fontEngineData->hdc;
|
||||
HGDIOBJ oldfont = SelectObject(hdc, hf);
|
||||
|
||||
qreal scale = qreal(fontDef.pixelSize) / unitsPerEm;
|
||||
qreal stretch = fontDef.stretch ? qreal(fontDef.stretch) / 100 : 1.0;
|
||||
for(int i = 0; i < nglyphs; ++i) {
|
||||
if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0,
|
||||
qreal(fontDef.pixelSize) / unitsPerEm)) {
|
||||
scale, stretch)) {
|
||||
// Some windows fonts, like "Modern", are vector stroke
|
||||
// fonts, which are reported as TMPF_VECTOR but do not
|
||||
// support GetGlyphOutline, and thus we set this bit so
|
||||
|
|
|
|||
Loading…
Reference in New Issue