/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QFONTENGINE_FT_P_H #define QFONTENGINE_FT_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "private/qfontengine_p.h" #ifndef QT_NO_FREETYPE #include #include FT_FREETYPE_H #ifndef Q_OS_WIN #include #endif #ifndef QT_NO_FONTCONFIG #include #endif #include #include "private/qharfbuzz_copy_p.h" QT_BEGIN_NAMESPACE class QFontEngineFTRawFont; class QFontconfigDatabase; /* * This struct represents one font file on disk (like Arial.ttf) and is shared between all the font engines * that show this font file (at different pixel sizes). */ struct QFreetypeFace { void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing); QFontEngine::Properties properties() const; bool getSfntTable(uint tag, uchar *buffer, uint *length) const; static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id, const QByteArray &fontData = QByteArray()); void release(const QFontEngine::FaceId &face_id); // locks the struct for usage. Any read/write operations require locking. void lock() { _lock.lock(); } void unlock() { _lock.unlock(); } FT_Face face; HB_Face hbFace; #ifndef QT_NO_FONTCONFIG FcCharSet *charset; #endif int xsize; // 26.6 int ysize; // 26.6 FT_Matrix matrix; FT_CharMap unicode_map; FT_CharMap symbol_map; enum { cmapCacheSize = 0x200 }; glyph_t cmapCache[cmapCacheSize]; int fsType() const; HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale); static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false); private: friend class QFontEngineFT; friend struct QScopedPointerDeleter; QFreetypeFace() : _lock(QMutex::Recursive) {} ~QFreetypeFace() {} QAtomicInt ref; QMutex _lock; QByteArray fontData; }; // If this is exported this breaks compilation of the windows // plugin as qfontengine_ft_p.h/.cpp are also compiled there #ifndef Q_OS_WIN class Q_GUI_EXPORT QFontEngineFT : public QFontEngine #else class QFontEngineFT : public QFontEngine #endif { public: /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ struct Glyph { ~Glyph(); short linearAdvance; unsigned char width; unsigned char height; signed char x; signed char y; signed char advance; signed char format; uchar *data; }; enum SubpixelAntialiasingType { Subpixel_None, Subpixel_RGB, Subpixel_BGR, Subpixel_VRGB, Subpixel_VBGR }; struct GlyphInfo { unsigned short width; unsigned short height; short x; short y; short xOff; short yOff; }; struct GlyphAndSubPixelPosition { GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {} bool operator==(const GlyphAndSubPixelPosition &other) const { return glyph == other.glyph && subPixelPosition == other.subPixelPosition; } glyph_t glyph; QFixed subPixelPosition; }; struct QGlyphSet { QGlyphSet(); ~QGlyphSet(); FT_Matrix transformationMatrix; bool outline_drawing; void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition); void clear(); inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const { return (index < 256 && subPixelPosition == 0); } inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const; void setGlyph(glyph_t index, QFixed spp, Glyph *glyph); private: mutable QHash glyph_data; // maps from glyph index to glyph data mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256 mutable int fast_glyph_count; }; virtual QFontEngine::FaceId faceId() const; virtual QFontEngine::Properties properties() const; virtual QFixed emSquareSize() const; virtual bool supportsSubPixelPositions() const { return default_hint_style == HintLight || default_hint_style == HintNone; } virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; virtual int synthesized() const; virtual QFixed ascent() const; virtual QFixed descent() const; virtual QFixed leading() const; virtual QFixed xHeight() const; virtual QFixed averageCharWidth() const; virtual qreal maxCharWidth() const; virtual qreal minLeftBearing() const; virtual qreal minRightBearing() const; virtual QFixed lineThickness() const; virtual QFixed underlinePosition() const; void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; inline virtual Type type() const { return QFontEngine::Freetype; } inline virtual const char *name() const { return "freetype"; } virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); virtual bool canRender(const QChar *string, int len); virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); virtual glyph_metrics_t boundingBox(glyph_t glyph); virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix); virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); } virtual QImage alphaMapForGlyph(glyph_t, QFixed); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format); virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, GlyphFormat neededFormat, const QTransform &t, QPoint *offset); virtual bool hasInternalCaching() const { return cacheEnabled; } virtual void unlockAlphaMapForGlyph(); virtual void removeGlyphFromCache(glyph_t glyph); virtual int glyphMargin(QFontEngineGlyphCache::Type /* type */) { return 0; } virtual int glyphCount() const; enum Scaling { Scaled, Unscaled }; FT_Face lockFace(Scaling scale = Scaled) const; void unlockFace() const; FT_Face non_locked_face() const; inline bool drawAntialiased() const { return antialias; } inline bool invalid() const { return xsize == 0 && ysize == 0; } inline bool isBitmapFont() const { return defaultFormat == Format_Mono; } inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); } Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const; Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format); QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix); bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs, const QFixedPoint *positions, GlyphFormat format = Format_Render); QFontEngineFT(const QFontDef &fd); virtual ~QFontEngineFT(); bool init(FaceId faceId, bool antiaalias, GlyphFormat defaultFormat = Format_None, const QByteArray &fontData = QByteArray()); bool init(FaceId faceId, bool antialias, GlyphFormat format, QFreetypeFace *freetypeFace); virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); virtual void setDefaultHintStyle(HintStyle style); virtual QFontEngine *cloneWithSize(qreal pixelSize) const; bool initFromFontEngine(const QFontEngineFT *fontEngine); HintStyle defaultHintStyle() const { return default_hint_style; } protected: QFreetypeFace *freetype; int default_load_flags; HintStyle default_hint_style; bool antialias; bool transform; bool embolden; bool obliquen; SubpixelAntialiasingType subpixelType; int lcdFilterType; bool embeddedbitmap; bool cacheEnabled; private: friend class QFontEngineFTRawFont; friend class QFontconfigDatabase; friend class QFontEngineMultiFontConfig; int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const; GlyphFormat defaultFormat; FT_Matrix matrix; QList transformedGlyphSets; mutable QGlyphSet defaultGlyphSet; QFontEngine::FaceId face_id; int xsize; int ysize; mutable QFixed lbearing; mutable QFixed rbearing; QFixed line_thickness; QFixed underline_position; FT_Size_Metrics metrics; mutable bool kerning_pairs_loaded; }; inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g) { return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt(); } inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const { if (useFastGlyphData(index, subPixelPosition)) return fast_glyph_data[index]; return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition)); } QT_END_NAMESPACE #endif // QT_NO_FREETYPE #endif // QFONTENGINE_FT_P_H