/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: http://www.qt-project.org/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QT_NO_FREETYPE
#include "qfile.h"
-#include "qabstractfileengine.h"
+#include "qfileinfo.h"
#include "qthreadstorage.h"
#include <qmath.h>
return HB_Err_Ok;
}
+extern QByteArray qt_fontdata_from_index(int);
+
/*
* One font file can contain more than one font (bold/italic for example)
* find the right one and return it.
QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
FT_Face face;
if (!face_id.filename.isEmpty()) {
- QFile file(QString::fromUtf8(face_id.filename));
+ QString fileName = QString::fromUtf8(face_id.filename);
if (face_id.filename.startsWith(":qmemoryfonts/")) {
// from qfontdatabase.cpp
- extern QByteArray qt_fontdata_from_index(int);
QByteArray idx = face_id.filename;
idx.remove(0, 14); // remove ':qmemoryfonts/'
bool ok = false;
newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
newFreetype->fontData = QByteArray();
- } else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
+ } else if (!QFileInfo(fileName).isNativePath()) {
+ QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
return 0;
}
newFreetype->matrix.yx = 0;
newFreetype->unicode_map = 0;
newFreetype->symbol_map = 0;
-#ifndef QT_NO_FONTCONFIG
- newFreetype->charset = 0;
-#endif
memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0);
-# if 0
- FcChar8 *name;
- FcPatternGetString(pattern, FC_FAMILY, 0, &name);
- qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,
- newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0,
- newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0,
- newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0);
-
- for (int i = 0; i < 256; i += 8)
- qDebug(" %x: %d %d %d %d %d %d %d %d", i,
- FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
- FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
- FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
- FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i));
-#endif
FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
QT_TRY {
if (!ref.deref()) {
qHBFreeFace(hbFace);
FT_Done_Face(face);
-#ifndef QT_NO_FONTCONFIG
- if (charset)
- FcCharSetDestroy(charset);
-#endif
if(freetypeData->faces.contains(face_id))
freetypeData->faces.take(face_id);
delete this;
}
Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0;
- if (g && g->format == format)
+ if (g && g->format == format && (fetchMetricsOnly || g->data))
return g;
QFontEngineFT::GlyphInfo info;
if (err != FT_Err_Ok)
qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
- if ((!set || set->outline_drawing) && fetchMetricsOnly)
- return 0;
-
FT_GlyphSlot slot = face->glyph;
+
if (embolden) Q_FT_GLYPHSLOT_EMBOLDEN(slot);
if (obliquen) {
Q_FT_GLYPHSLOT_OBLIQUE(slot);
info.xOff = TRUNC(ROUND(slot->advance.x));
info.yOff = 0;
+ if ((set && set->outline_drawing) || fetchMetricsOnly) {
+ // If the advance doesn't fit in signed char, don't cache it
+ if (qAbs(info.xOff) >= 128)
+ return 0;
+ g = new Glyph;
+ g->data = 0;
+ g->linearAdvance = slot->linearHoriAdvance >> 10;
+ int left = FLOOR(slot->metrics.horiBearingX);
+ int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
+ int top = CEIL(slot->metrics.horiBearingY);
+ int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
+ g->width = TRUNC(right-left);
+ g->height = TRUNC(top-bottom);
+ g->x = TRUNC(left);
+ g->y = TRUNC(top);
+ g->advance = TRUNC(ROUND(slot->advance.x));
+ g->format = format;
+
+ if (set)
+ set->setGlyph(glyph, subPixelPosition, g);
+
+ return g;
+ }
+
uchar *glyph_buffer = 0;
int glyph_buffer_size = 0;
#if defined(QT_USE_FREETYPE_LCDFILTER)
QFixed QFontEngineFT::descent() const
{
- // subtract a pixel to work around QFontMetrics's built-in + 1
- return QFixed::fromFixed(-metrics.descender - 64);
+ return QFixed::fromFixed(-metrics.descender);
}
QFixed QFontEngineFT::leading() const
bool QFontEngineFT::canRender(const QChar *string, int len)
{
FT_Face face = freetype->face;
-#if 0
- if (_cmap != -1) {
- lockFace();
- for ( int i = 0; i < len; i++ ) {
- unsigned int uc = getChar(string, i, len);
- if (!FcCharSetHasChar (_font->charset, uc) && getAdobeCharIndex(face, _cmap, uc) == 0) {
- allExist = false;
- break;
- }
- }
- unlockFace();
- } else
-#endif
{
for ( int i = 0; i < len; i++ ) {
unsigned int uc = getChar(string, i, len);
unsigned int uc = getChar(str, i, len);
glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
if ( !glyphs->glyphs[glyph_pos] ) {
- glyph_t glyph;
-#if !defined(QT_NO_FONTCONFIG)
- if (freetype->charset != 0 && FcCharSetHasChar(freetype->charset, uc)) {
-#else
- if (false) {
-#endif
- redo0:
+ // Symbol fonts can have more than one CMAPs, FreeType should take the
+ // correct one for us by default, so we always try FT_Get_Char_Index
+ // first. If it didn't work (returns 0), we will explicitly set the
+ // CMAP to symbol font one and try again. symbol_map is not always the
+ // correct one because in certain fonts like Wingdings symbol_map only
+ // contains PUA codepoints instead of the common ones.
+ glyph_t glyph = FT_Get_Char_Index(face, uc);
+ // Certain symbol fonts don't have no-break space (0xa0) and tab (0x9),
+ // while we usually want to render them as space
+ if (!glyph && (uc == 0xa0 || uc == 0x9)) {
+ uc = 0x20;
glyph = FT_Get_Char_Index(face, uc);
- if (!glyph && (uc == 0xa0 || uc == 0x9)) {
- uc = 0x20;
- goto redo0;
- }
- } else {
+ }
+ if (!glyph) {
FT_Set_Charmap(face, freetype->symbol_map);
glyph = FT_Get_Char_Index(face, uc);
FT_Set_Charmap(face, freetype->unicode_map);
uc = QChar::mirroredChar(uc);
glyphs->glyphs[glyph_pos] = uc < QFreetypeFace::cmapCacheSize ? freetype->cmapCache[uc] : 0;
if (!glyphs->glyphs[glyph_pos]) {
-#if !defined(QT_NO_FONTCONFIG)
- if (freetype->charset == 0 || FcCharSetHasChar(freetype->charset, uc))
-#endif
{
redo:
glyph_t glyph = FT_Get_Char_Index(face, uc);
(flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face);
for (int i = 0; i < glyphs->numGlyphs; i++) {
Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyphs->glyphs[i]) : 0;
- if (g) {
+ // Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph
+ GlyphFormat acceptableFormat = (defaultFormat != Format_None) ? defaultFormat : Format_Mono;
+ if (g && g->format == acceptableFormat) {
glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
} else {
if (!face)
glyph_metrics_t overall;
// initialize with line height, we get the same behaviour on all platforms
overall.y = -ascent();
- overall.height = ascent() + descent() + 1;
+ overall.height = ascent() + descent();
QFixed ymax = 0;
QFixed xmax = 0;
lockFace();
Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono);
- if (!glyph) {
+ if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
}
return img;
}
-QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, int margin, const QTransform &t)
+QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
if (t.type() > QTransform::TxTranslate)
- return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32);
- if (!glyph) {
+ if (!glyph || !glyph->data) {
unlockFace();
- return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
+ return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
}
QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
QFontEngine *QFontEngineFT::cloneWithSize(qreal pixelSize) const
{
- QFontDef fontDef;
+ QFontDef fontDef(this->fontDef);
fontDef.pixelSize = pixelSize;
QFontEngineFT *fe = new QFontEngineFT(fontDef);
if (!fe->initFromFontEngine(this)) {