blob: 2076fa4d8025ca61cd714b76f53d2804cf88979e [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFONTENGINE_P_H
#define QFONTENGINE_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 "QtCore/qglobal.h"
#include "QtCore/qatomic.h"
#include <QtCore/qvarlengtharray.h>
#include <QtCore/QLinkedList>
#include "private/qtextengine_p.h"
#include "private/qfont_p.h"
QT_BEGIN_NAMESPACE
class QPainterPath;
class QFontEngineGlyphCache;
struct QGlyphLayout;
#define MAKE_TAG(ch1, ch2, ch3, ch4) (\
(((quint32)(ch1)) << 24) | \
(((quint32)(ch2)) << 16) | \
(((quint32)(ch3)) << 8) | \
((quint32)(ch4)) \
)
// ### this only used in getPointInOutline(), refactor it and then remove these magic numbers
enum HB_Compat_Error {
Err_Ok = 0x0000,
Err_Not_Covered = 0xFFFF,
Err_Invalid_Argument = 0x1A66,
Err_Invalid_SubTable_Format = 0x157F,
Err_Invalid_SubTable = 0x1570
};
typedef void (*qt_destroy_func_t) (void *user_data);
typedef bool (*qt_get_font_table_func_t) (void *user_data, uint tag, uchar *buffer, uint *length);
class Q_GUI_EXPORT QFontEngine
{
public:
enum Type {
Box,
Multi,
// MS Windows types
Win,
// Apple Mac OS types
Mac,
// QWS types
Freetype,
QPF1,
QPF2,
Proxy,
DirectWrite,
TestFontEngine = 0x1000
};
enum GlyphFormat {
Format_None,
Format_Render = Format_None,
Format_Mono,
Format_A8,
Format_A32,
Format_ARGB
};
enum ShaperFlag {
DesignMetrics = 0x0002,
GlyphIndicesOnly = 0x0004
};
Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag)
virtual ~QFontEngine();
inline Type type() const { return m_type; }
// all of these are in unscaled metrics if the engine supports uncsaled metrics,
// otherwise in design metrics
struct Properties {
QByteArray postscriptName;
QByteArray copyright;
QRectF boundingBox;
QFixed emSquare;
QFixed ascent;
QFixed descent;
QFixed leading;
QFixed italicAngle;
QFixed capHeight;
QFixed lineWidth;
};
virtual Properties properties() const;
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
QByteArray getSfntTable(uint tag) const;
virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
struct FaceId {
FaceId() : index(0), encoding(0) {}
QByteArray filename;
QByteArray uuid;
int index;
int encoding;
};
virtual FaceId faceId() const { return FaceId(); }
enum SynthesizedFlags {
SynthesizedItalic = 0x1,
SynthesizedBold = 0x2,
SynthesizedStretch = 0x4
};
virtual int synthesized() const { return 0; }
virtual bool supportsSubPixelPositions() const { return false; }
virtual QFixed subPixelPositionForX(QFixed x) const;
virtual QFixed emSquareSize() const { return ascent(); }
/* returns 0 as glyph index for non existent glyphs */
virtual glyph_t glyphIndex(uint ucs4) const = 0;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, ShaperFlags) const;
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags);
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags,
QVarLengthArray<glyph_t> &glyphs_out, QVarLengthArray<QFixedPoint> &positions);
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
void addBitmapFontToPath(qreal x, qreal y, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags);
/**
* Create a qimage with the alpha values for the glyph.
* Returns an image indexed_8 with index values ranging from 0=fully transparent to 255=opaque
*/
// ### Refactor this into a smaller and more flexible API.
virtual QImage alphaMapForGlyph(glyph_t);
virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
GlyphFormat neededFormat,
const QTransform &t = QTransform(),
QPoint *offset = 0);
virtual void unlockAlphaMapForGlyph();
virtual bool hasInternalCaching() const { return false; }
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
{
return boundingBox(glyph, matrix);
}
virtual void removeGlyphFromCache(glyph_t);
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) = 0;
virtual glyph_metrics_t boundingBox(glyph_t glyph) = 0;
virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs);
virtual QFixed ascent() const = 0;
virtual QFixed descent() const = 0;
virtual QFixed leading() const = 0;
virtual QFixed xHeight() const;
virtual QFixed averageCharWidth() const;
virtual QFixed lineThickness() const;
virtual QFixed underlinePosition() const;
virtual qreal maxCharWidth() const = 0;
virtual qreal minLeftBearing() const { return qreal(); }
virtual qreal minRightBearing() const { return qreal(); }
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
inline bool canRender(uint ucs4) const { return glyphIndex(ucs4) != 0; }
virtual bool canRender(const QChar *str, int len) const;
virtual bool supportsTransformation(const QTransform &transform) const;
virtual int glyphCount() const;
virtual int glyphMargin(GlyphFormat format) { return format == Format_A32 ? 2 : 0; }
virtual QFontEngine *cloneWithSize(qreal /*pixelSize*/) const { return 0; }
void *harfbuzzFont() const;
void *harfbuzzFace() const;
bool supportsScript(QChar::Script script) const;
virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
void clearGlyphCache(const void *key);
void setGlyphCache(const void *key, QFontEngineGlyphCache *data);
QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const;
static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize);
static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode);
static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily);
virtual bool hasUnreliableGlyphOutline() const;
enum HintStyle {
HintNone,
HintLight,
HintMedium,
HintFull
};
virtual void setDefaultHintStyle(HintStyle) { }
enum SubpixelAntialiasingType {
Subpixel_None,
Subpixel_RGB,
Subpixel_BGR,
Subpixel_VRGB,
Subpixel_VBGR
};
private:
const Type m_type;
public:
QAtomicInt ref;
QFontDef fontDef;
mutable void *font_;
mutable qt_destroy_func_t font_destroy_func;
mutable void *face_;
mutable qt_destroy_func_t face_destroy_func;
struct FaceData {
void *user_data;
qt_get_font_table_func_t get_font_table;
} faceData;
uint cache_cost; // amount of mem used in kb by the font
uint fsType : 16;
bool symbol;
struct KernPair {
uint left_right;
QFixed adjust;
inline bool operator<(const KernPair &other) const
{
return left_right < other.left_right;
}
};
QVector<KernPair> kerning_pairs;
void loadKerningPairs(QFixed scalingFactor);
GlyphFormat glyphFormat;
QImage currentlyLockedAlphaMap;
int m_subPixelPositionCount; // Number of positions within a single pixel for this cache
inline QVariant userData() const { return m_userData; }
protected:
explicit QFontEngine(Type type);
QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false);
inline void setUserData(const QVariant &userData) { m_userData = userData; }
private:
struct GlyphCacheEntry {
GlyphCacheEntry();
GlyphCacheEntry(const GlyphCacheEntry &);
~GlyphCacheEntry();
GlyphCacheEntry &operator=(const GlyphCacheEntry &);
const void *context;
QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
bool operator==(const GlyphCacheEntry &other) const { return context == other.context && cache == other.cache; }
};
mutable QLinkedList<GlyphCacheEntry> m_glyphCaches;
private:
QVariant m_userData;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId &f2)
{
return (f1.index == f2.index) && (f1.encoding == f2.encoding) && (f1.filename == f2.filename);
}
inline uint qHash(const QFontEngine::FaceId &f)
{
return qHash((f.index << 16) + f.encoding) + qHash(f.filename + f.uuid);
}
class QGlyph;
class QFontEngineBox : public QFontEngine
{
public:
QFontEngineBox(int size);
~QFontEngineBox();
virtual glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE;
void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
virtual glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE;
virtual QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE;
virtual QFixed ascent() const Q_DECL_OVERRIDE;
virtual QFixed descent() const Q_DECL_OVERRIDE;
virtual QFixed leading() const Q_DECL_OVERRIDE;
virtual qreal maxCharWidth() const Q_DECL_OVERRIDE;
virtual qreal minLeftBearing() const Q_DECL_OVERRIDE { return 0; }
virtual qreal minRightBearing() const Q_DECL_OVERRIDE { return 0; }
virtual QImage alphaMapForGlyph(glyph_t) Q_DECL_OVERRIDE;
virtual bool canRender(const QChar *string, int len) const Q_DECL_OVERRIDE;
inline int size() const { return _size; }
protected:
explicit QFontEngineBox(Type type, int size);
private:
friend class QFontPrivate;
int _size;
};
class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
{
public:
explicit QFontEngineMulti(QFontEngine *engine, int script, const QStringList &fallbackFamilies = QStringList());
~QFontEngineMulti();
virtual glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE;
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const Q_DECL_OVERRIDE;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE;
virtual glyph_metrics_t boundingBox(glyph_t glyph) Q_DECL_OVERRIDE;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE;
virtual void doKerning(QGlyphLayout *, ShaperFlags) const Q_DECL_OVERRIDE;
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE;
virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0) Q_DECL_OVERRIDE;
virtual QFixed ascent() const Q_DECL_OVERRIDE;
virtual QFixed descent() const Q_DECL_OVERRIDE;
virtual QFixed leading() const Q_DECL_OVERRIDE;
virtual QFixed xHeight() const Q_DECL_OVERRIDE;
virtual QFixed averageCharWidth() const Q_DECL_OVERRIDE;
virtual QImage alphaMapForGlyph(glyph_t) Q_DECL_OVERRIDE;
virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE;
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t) Q_DECL_OVERRIDE;
virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE;
virtual QFixed lineThickness() const Q_DECL_OVERRIDE;
virtual QFixed underlinePosition() const Q_DECL_OVERRIDE;
virtual qreal maxCharWidth() const Q_DECL_OVERRIDE;
virtual qreal minLeftBearing() const Q_DECL_OVERRIDE;
virtual qreal minRightBearing() const Q_DECL_OVERRIDE;
virtual bool canRender(const QChar *string, int len) const Q_DECL_OVERRIDE;
inline int fallbackFamilyCount() const { return m_fallbackFamilies.size(); }
inline QString fallbackFamilyAt(int at) const { return m_fallbackFamilies.at(at); }
void setFallbackFamiliesList(const QStringList &fallbackFamilies);
inline QFontEngine *engine(int at) const
{ Q_ASSERT(at < m_engines.size()); return m_engines.at(at); }
void ensureEngineAt(int at);
static QFontEngine *createMultiFontEngine(QFontEngine *fe, int script);
protected:
virtual void ensureFallbackFamiliesQueried();
virtual bool shouldLoadFontEngineForCharacter(int at, uint ucs4) const;
virtual QFontEngine *loadEngine(int at);
private:
QVector<QFontEngine *> m_engines;
QStringList m_fallbackFamilies;
const int m_script;
bool m_fallbackFamiliesQueried;
};
class QTestFontEngine : public QFontEngineBox
{
public:
QTestFontEngine(int size);
};
QT_END_NAMESPACE
#endif // QFONTENGINE_P_H