Fix transformed text with DirectWrite engine
This is a port of f54c5d9133d7aa7636988db36fa6cc51d26434b6 from Qt 4.8 which was lost in the transition to Qt 5. It makes sure we use the correct bounding box for the transformed glyph by getting from DirectWrite itself. [ChangeLog][Windows] Fixed transformed text when using the DirectWrite font engine. Task-number: QTBUG-50009 Change-Id: I416ab64253165b878af6b9837348134fede8092e Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>bb10
parent
30bff91c39
commit
b9bd83c9c2
|
|
@ -520,13 +520,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
int margin,
|
||||
const QTransform &xform)
|
||||
{
|
||||
glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform);
|
||||
// This needs to be kept in sync with alphaMapBoundingBox
|
||||
int width = (metrics.width + margin * 2).ceil().toInt() ;
|
||||
int height = (metrics.height + margin * 2).ceil().toInt();
|
||||
|
||||
UINT16 glyphIndex = t;
|
||||
FLOAT glyphAdvance = metrics.xoff.toReal();
|
||||
FLOAT glyphAdvance = 0;
|
||||
|
||||
DWRITE_GLYPH_OFFSET glyphOffset;
|
||||
glyphOffset.advanceOffset = 0;
|
||||
|
|
@ -542,12 +537,9 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
glyphRun.bidiLevel = 0;
|
||||
glyphRun.glyphOffsets = &glyphOffset;
|
||||
|
||||
QFixed x = margin - metrics.x.floor() + subPixelPosition;
|
||||
QFixed y = margin - metrics.y.floor();
|
||||
|
||||
DWRITE_MATRIX transform;
|
||||
transform.dx = x.toReal();
|
||||
transform.dy = y.toReal();
|
||||
transform.dx = subPixelPosition.toReal();
|
||||
transform.dy = 0;
|
||||
transform.m11 = xform.m11();
|
||||
transform.m12 = xform.m12();
|
||||
transform.m21 = xform.m21();
|
||||
|
|
@ -571,46 +563,56 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
|
|||
|
||||
if (SUCCEEDED(hr)) {
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = width;
|
||||
rect.bottom = height;
|
||||
glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
|
||||
|
||||
int size = width * height * 3;
|
||||
BYTE *alphaValues = new BYTE[size];
|
||||
memset(alphaValues, 0, size);
|
||||
rect.left -= margin;
|
||||
rect.top -= margin;
|
||||
rect.right += margin;
|
||||
rect.bottom += margin;
|
||||
|
||||
hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||
&rect,
|
||||
alphaValues,
|
||||
size);
|
||||
const int width = rect.right - rect.left;
|
||||
const int height = rect.bottom - rect.top;
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
QImage img(width, height, QImage::Format_RGB32);
|
||||
img.fill(0xffffffff);
|
||||
const int size = width * height * 3;
|
||||
if (size > 0) {
|
||||
BYTE *alphaValues = new BYTE[size];
|
||||
memset(alphaValues, 0, size);
|
||||
|
||||
for (int y=0; y<height; ++y) {
|
||||
uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
|
||||
BYTE *src = alphaValues + width * 3 * y;
|
||||
hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||
&rect,
|
||||
alphaValues,
|
||||
size);
|
||||
|
||||
for (int x=0; x<width; ++x) {
|
||||
dest[x] = *(src) << 16
|
||||
| *(src + 1) << 8
|
||||
| *(src + 2);
|
||||
if (SUCCEEDED(hr)) {
|
||||
QImage img(width, height, QImage::Format_RGB32);
|
||||
img.fill(0xffffffff);
|
||||
|
||||
src += 3;
|
||||
for (int y=0; y<height; ++y) {
|
||||
uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
|
||||
BYTE *src = alphaValues + width * 3 * y;
|
||||
|
||||
for (int x=0; x<width; ++x) {
|
||||
dest[x] = *(src) << 16
|
||||
| *(src + 1) << 8
|
||||
| *(src + 2);
|
||||
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] alphaValues;
|
||||
glyphAnalysis->Release();
|
||||
|
||||
return img;
|
||||
} else {
|
||||
delete[] alphaValues;
|
||||
glyphAnalysis->Release();
|
||||
|
||||
qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
delete[] alphaValues;
|
||||
glyphAnalysis->Release();
|
||||
|
||||
return img;
|
||||
} else {
|
||||
delete[] alphaValues;
|
||||
glyphAnalysis->Release();
|
||||
|
||||
qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__);
|
||||
qWarning("%s: Glyph has no bounds", __FUNCTION__);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -724,16 +726,65 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
|
|||
return QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString();
|
||||
}
|
||||
|
||||
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format)
|
||||
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph,
|
||||
QFixed subPixelPosition,
|
||||
const QTransform &matrix,
|
||||
GlyphFormat format)
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
Q_UNUSED(format);
|
||||
glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance
|
||||
|
||||
int margin = glyphMargin(QFontEngine::Format_A32);
|
||||
glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix);
|
||||
gm.width += margin * 2;
|
||||
gm.height += margin * 2;
|
||||
return gm;
|
||||
UINT16 glyphIndex = glyph;
|
||||
FLOAT glyphAdvance = 0;
|
||||
|
||||
DWRITE_GLYPH_OFFSET glyphOffset;
|
||||
glyphOffset.advanceOffset = 0;
|
||||
glyphOffset.ascenderOffset = 0;
|
||||
|
||||
DWRITE_GLYPH_RUN glyphRun;
|
||||
glyphRun.fontFace = m_directWriteFontFace;
|
||||
glyphRun.fontEmSize = fontDef.pixelSize;
|
||||
glyphRun.glyphCount = 1;
|
||||
glyphRun.glyphIndices = &glyphIndex;
|
||||
glyphRun.glyphAdvances = &glyphAdvance;
|
||||
glyphRun.isSideways = false;
|
||||
glyphRun.bidiLevel = 0;
|
||||
glyphRun.glyphOffsets = &glyphOffset;
|
||||
|
||||
DWRITE_MATRIX transform;
|
||||
transform.dx = subPixelPosition.toReal();
|
||||
transform.dy = 0;
|
||||
transform.m11 = matrix.m11();
|
||||
transform.m12 = matrix.m12();
|
||||
transform.m21 = matrix.m21();
|
||||
transform.m22 = matrix.m22();
|
||||
|
||||
IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
|
||||
HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
|
||||
&glyphRun,
|
||||
1.0f,
|
||||
&transform,
|
||||
DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
0.0, 0.0,
|
||||
&glyphAnalysis
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
RECT rect;
|
||||
glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
|
||||
glyphAnalysis->Release();
|
||||
|
||||
int margin = glyphMargin(QFontEngine::Format_A32);
|
||||
|
||||
return glyph_metrics_t(rect.left,
|
||||
rect.top,
|
||||
rect.right - rect.left + margin * 2,
|
||||
rect.bottom - rect.top + margin * 2,
|
||||
bbox.xoff, bbox.yoff);
|
||||
} else {
|
||||
return glyph_metrics_t();
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
Loading…
Reference in New Issue