glyph_metrics_t QFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, GlyphFormat /*format*/) { glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance 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_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(); return glyph_metrics_t(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bbox.xoff, bbox.yoff); } else { return glyph_metrics_t(); } }
QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform) { UINT16 glyphIndex = t; 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 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); transform.m22 = xform.m22(); IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; HRESULT hr = m_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); rect.left -= margin; rect.top -= margin; rect.right += margin; rect.bottom += margin; int width = rect.right - rect.left; int height = rect.bottom - rect.top; int size = width * height * 3; if (size > 0) { BYTE *alphaValues = new BYTE[size]; qMemSet(alphaValues, size, 0); hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect, alphaValues, size); if (SUCCEEDED(hr)) { QImage img(width, height, QImage::Format_RGB32); img.fill(0xffffffff); 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("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed"); } } } else { qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateGlyphRunAnalysis failed"); } return QImage(); }
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform) { glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform); int width = (metrics.width + margin * 2 + 4).ceil().toInt() ; int height = (metrics.height + margin * 2 + 4).ceil().toInt(); UINT16 glyphIndex = t; FLOAT glyphAdvance = metrics.xoff.toReal(); 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; 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.m11 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); transform.m22 = xform.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; rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = height; int size = width * height * 3; BYTE *alphaValues = new BYTE[size]; memset(alphaValues, size, 0); hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect, alphaValues, size); if (SUCCEEDED(hr)) { QImage img(width, height, QImage::Format_RGB32); img.fill(0xffffffff); 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__); } } else { qErrnoWarning("%s: CreateGlyphRunAnalysis failed", __FUNCTION__); } return QImage(); }