diff options
Diffstat (limited to 'src/gui/text/qfontengine_ft.cpp')
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 84 |
1 files changed, 35 insertions, 49 deletions
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index b79f971156..8ae178c6ad 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -891,8 +891,6 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, FT_Matrix_Multiply(&m, &matrix); } - FT_Library library = qt_getFreetype(); - info.xOff = TRUNC(ROUND(slot->advance.x)); info.yOff = 0; @@ -930,12 +928,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, return g; } - uchar *glyph_buffer = 0; int glyph_buffer_size = 0; + QScopedArrayPointer<uchar> glyph_buffer; #if defined(QT_USE_FREETYPE_LCDFILTER) bool useFreetypeRenderGlyph = false; if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) { - err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType); + err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType); if (err == FT_Err_Ok) useFreetypeRenderGlyph = true; } @@ -946,7 +944,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (err != FT_Err_Ok) qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE); + FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE); info.height = slot->bitmap.rows / vfactor; info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width; @@ -954,12 +952,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, info.y = slot->bitmap_top; glyph_buffer_size = info.width * info.height * 4; - glyph_buffer = new uchar[glyph_buffer_size]; + glyph_buffer.reset(new uchar[glyph_buffer_size]); if (hsubpixel) - convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false); + convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false); else if (vfactor != 1) - convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false); + convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false); } else #endif { @@ -1030,26 +1028,30 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, || ((signed char)(info.xOff) != info.xOff)); if (large_glyph) { - delete [] glyph_buffer; return 0; } int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 : (format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4)); - glyph_buffer_size = pitch * info.height; - glyph_buffer = new uchar[glyph_buffer_size]; - memset(glyph_buffer, 0, glyph_buffer_size); + if (glyph_buffer_size < pitch * info.height) { + glyph_buffer_size = pitch * info.height; + glyph_buffer.reset(new uchar[glyph_buffer_size]); + } + memset(glyph_buffer.data(), 0, glyph_buffer_size); if (slot->format == FT_GLYPH_FORMAT_OUTLINE) { FT_Bitmap bitmap; bitmap.rows = info.height*vfactor; bitmap.width = hpixels; bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3); - if (!hsubpixel && vfactor == 1 && format != Format_A32) - bitmap.buffer = glyph_buffer; - else - bitmap.buffer = new uchar[bitmap.rows*bitmap.pitch]; - memset(bitmap.buffer, 0, bitmap.rows*bitmap.pitch); + int bitmap_buffer_size = bitmap.rows * bitmap.pitch; + if (!hsubpixel && vfactor == 1 && format != Format_A32) { + Q_ASSERT(glyph_buffer_size <= bitmap_buffer_size); + bitmap.buffer = glyph_buffer.data(); + } else { + bitmap.buffer = new uchar[bitmap_buffer_size]; + memset(bitmap.buffer, 0, bitmap_buffer_size); + } bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY; FT_Matrix matrix; matrix.xx = (hsubpixel ? 3 : 1) << 16; @@ -1058,11 +1060,11 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, FT_Outline_Transform(&slot->outline, &matrix); FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor); - FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap); + FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap); if (hsubpixel) { Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); Q_ASSERT(antialias); - uchar *convoluted = new uchar[bitmap.rows*bitmap.pitch]; + uchar *convoluted = new uchar[bitmap_buffer_size]; bool useLegacyLcdFilter = false; #if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY); @@ -1072,20 +1074,20 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch); buffer = convoluted; } - convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter); + convertRGBToARGB(buffer + 1, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter); delete [] convoluted; } else if (vfactor != 1) { - convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true); + convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true); } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { - convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch); + convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch); } - if (bitmap.buffer != glyph_buffer) + if (bitmap.buffer != glyph_buffer.data()) delete [] bitmap.buffer; } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) { Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO); uchar *src = slot->bitmap.buffer; - uchar *dst = glyph_buffer; + uchar *dst = glyph_buffer.data(); int h = slot->bitmap.rows; if (format == Format_Mono) { int bytes = ((info.width + 7) & ~7) >> 3; @@ -1130,7 +1132,6 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, } } else { qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format); - delete [] glyph_buffer; return 0; } } @@ -1149,7 +1150,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, g->advance = info.xOff; g->format = format; delete [] g->data; - g->data = glyph_buffer; + g->data = glyph_buffer.take(); if (set) set->setGlyph(glyph, subPixelPosition, g); @@ -1333,14 +1334,14 @@ static inline FT_Matrix QTransformToFTMatrix(const QTransform &matrix) return m; } -QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransform &matrix) +QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix) { if (matrix.type() > QTransform::TxShear || !cacheEnabled) return 0; // FT_Set_Transform only supports scalable fonts if (!FT_IS_SCALABLE(freetype->face)) - return 0; + return matrix.type() <= QTransform::TxTranslate ? &defaultGlyphSet : Q_NULLPTR; FT_Matrix m = QTransformToFTMatrix(matrix); @@ -1757,15 +1758,11 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe QFontEngineFT::Glyph *glyph; QScopedPointer<QFontEngineFT::Glyph> glyphGuard; if (cacheEnabled) { - QFontEngineFT::QGlyphSet *gset = &defaultGlyphSet; + QGlyphSet *gset = loadGlyphSet(t); QFontEngine::HintStyle hintStyle = default_hint_style; if (t.type() >= QTransform::TxScale) { // disable hinting if the glyphs are transformed default_hint_style = HintNone; - if (t.isAffine()) - gset = loadTransformedGlyphSet(t); - else - gset = 0; } if (gset) { @@ -1842,31 +1839,20 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, const QTransform &t, bool fetchBoundingBox) { - FT_Face face = 0; - QGlyphSet *glyphSet = 0; - FT_Matrix ftMatrix = QTransformToFTMatrix(t); - if (cacheEnabled) { - if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) - glyphSet = loadTransformedGlyphSet(t); - else - glyphSet = &defaultGlyphSet; - Q_ASSERT(glyphSet != 0); - } - + QGlyphSet *glyphSet = loadGlyphSet(t); if (glyphSet != 0 && glyphSet->outline_drawing && !fetchBoundingBox) return 0; Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0; - if (!glyph || glyph->format != format) { - face = lockFace(); + if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) { + lockFace(); FT_Matrix m = this->matrix; + FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t); FT_Matrix_Multiply(&ftMatrix, &m); freetype->matrix = m; glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false); - } - - if (face) unlockFace(); + } return glyph; } |