[temp] add private Qt headers

This commit is contained in:
Berkus Decker 2017-02-22 19:54:26 +02:00
parent 60c77e0738
commit 9da39b0b56
12 changed files with 5085 additions and 0 deletions

View File

@ -0,0 +1,870 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCSSPARSER_P_H
#define QCSSPARSER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of the QLibrary class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include <QtCore/QVariant>
#include <QtCore/QPair>
#include <QtCore/QSize>
#include <QtCore/QMultiHash>
#include <QtGui/QFont>
#include <QtGui/QPalette>
#include <QtCore/QSharedData>
QT_BEGIN_NAMESPACE
class QIcon;
QT_END_NAMESPACE
#ifndef QT_NO_CSSPARSER
// VxWorks defines NONE as (-1) "for times when NULL won't do"
#if defined(Q_OS_VXWORKS) && defined(NONE)
# undef NONE
#endif
#if defined(Q_OS_INTEGRITY)
# undef Value
#endif
#define QT_CSS_DECLARE_TYPEINFO(Class, Type) \
} /* namespace QCss */ \
Q_DECLARE_TYPEINFO(QCss:: Class, Type); \
namespace QCss {
QT_BEGIN_NAMESPACE
namespace QCss
{
enum Property {
UnknownProperty,
BackgroundColor,
Color,
Float,
Font,
FontFamily,
FontSize,
FontStyle,
FontWeight,
Margin,
MarginBottom,
MarginLeft,
MarginRight,
MarginTop,
QtBlockIndent,
QtListIndent,
QtParagraphType,
QtTableType,
QtUserState,
TextDecoration,
TextIndent,
TextUnderlineStyle,
VerticalAlignment,
Whitespace,
QtSelectionForeground,
QtSelectionBackground,
Border,
BorderLeft,
BorderRight,
BorderTop,
BorderBottom,
Padding,
PaddingLeft,
PaddingRight,
PaddingTop,
PaddingBottom,
PageBreakBefore,
PageBreakAfter,
QtAlternateBackground,
BorderLeftStyle,
BorderRightStyle,
BorderTopStyle,
BorderBottomStyle,
BorderStyles,
BorderLeftColor,
BorderRightColor,
BorderTopColor,
BorderBottomColor,
BorderColor,
BorderLeftWidth,
BorderRightWidth,
BorderTopWidth,
BorderBottomWidth,
BorderWidth,
BorderTopLeftRadius,
BorderTopRightRadius,
BorderBottomLeftRadius,
BorderBottomRightRadius,
BorderRadius,
Background,
BackgroundOrigin,
BackgroundClip,
BackgroundRepeat,
BackgroundPosition,
BackgroundAttachment,
BackgroundImage,
BorderImage,
QtSpacing,
Width,
Height,
MinimumWidth,
MinimumHeight,
MaximumWidth,
MaximumHeight,
QtImage,
Left,
Right,
Top,
Bottom,
QtOrigin,
QtPosition,
Position,
QtStyleFeatures,
QtBackgroundRole,
ListStyleType,
ListStyle,
QtImageAlignment,
TextAlignment,
Outline,
OutlineOffset,
OutlineWidth,
OutlineColor,
OutlineStyle,
OutlineRadius,
OutlineTopLeftRadius,
OutlineTopRightRadius,
OutlineBottomLeftRadius,
OutlineBottomRightRadius,
FontVariant,
TextTransform,
QtListNumberPrefix,
QtListNumberSuffix,
LineHeight,
QtLineHeightType,
NumProperties
};
enum KnownValue {
UnknownValue,
Value_Normal,
Value_Pre,
Value_NoWrap,
Value_PreWrap,
Value_Small,
Value_Medium,
Value_Large,
Value_XLarge,
Value_XXLarge,
Value_Italic,
Value_Oblique,
Value_Bold,
Value_Underline,
Value_Overline,
Value_LineThrough,
Value_Sub,
Value_Super,
Value_Left,
Value_Right,
Value_Top,
Value_Bottom,
Value_Center,
Value_Native,
Value_Solid,
Value_Dotted,
Value_Dashed,
Value_DotDash,
Value_DotDotDash,
Value_Double,
Value_Groove,
Value_Ridge,
Value_Inset,
Value_Outset,
Value_Wave,
Value_Middle,
Value_Auto,
Value_Always,
Value_None,
Value_Transparent,
Value_Disc,
Value_Circle,
Value_Square,
Value_Decimal,
Value_LowerAlpha,
Value_UpperAlpha,
Value_LowerRoman,
Value_UpperRoman,
Value_SmallCaps,
Value_Uppercase,
Value_Lowercase,
/* keep these in same order as QPalette::ColorRole */
Value_FirstColorRole,
Value_WindowText = Value_FirstColorRole,
Value_Button,
Value_Light,
Value_Midlight,
Value_Dark,
Value_Mid,
Value_Text,
Value_BrightText,
Value_ButtonText,
Value_Base,
Value_Window,
Value_Shadow,
Value_Highlight,
Value_HighlightedText,
Value_Link,
Value_LinkVisited,
Value_AlternateBase,
Value_LastColorRole = Value_AlternateBase,
Value_Disabled,
Value_Active,
Value_Selected,
Value_On,
Value_Off,
NumKnownValues
};
enum BorderStyle {
BorderStyle_Unknown,
BorderStyle_None,
BorderStyle_Dotted,
BorderStyle_Dashed,
BorderStyle_Solid,
BorderStyle_Double,
BorderStyle_DotDash,
BorderStyle_DotDotDash,
BorderStyle_Groove,
BorderStyle_Ridge,
BorderStyle_Inset,
BorderStyle_Outset,
BorderStyle_Native,
NumKnownBorderStyles
};
enum Edge {
TopEdge,
RightEdge,
BottomEdge,
LeftEdge,
NumEdges
};
enum Corner {
TopLeftCorner,
TopRightCorner,
BottomLeftCorner,
BottomRightCorner
};
enum TileMode {
TileMode_Unknown,
TileMode_Round,
TileMode_Stretch,
TileMode_Repeat,
NumKnownTileModes
};
enum Repeat {
Repeat_Unknown,
Repeat_None,
Repeat_X,
Repeat_Y,
Repeat_XY,
NumKnownRepeats
};
enum Origin {
Origin_Unknown,
Origin_Padding,
Origin_Border,
Origin_Content,
Origin_Margin,
NumKnownOrigins
};
enum PositionMode {
PositionMode_Unknown,
PositionMode_Static,
PositionMode_Relative,
PositionMode_Absolute,
PositionMode_Fixed,
NumKnownPositionModes
};
enum Attachment {
Attachment_Unknown,
Attachment_Fixed,
Attachment_Scroll,
NumKnownAttachments
};
enum StyleFeature {
StyleFeature_None = 0,
StyleFeature_BackgroundColor = 1,
StyleFeature_BackgroundGradient = 2,
NumKnownStyleFeatures = 4
};
struct Value
{
enum Type {
Unknown,
Number,
Percentage,
Length,
String,
Identifier,
KnownIdentifier,
Uri,
Color,
Function,
TermOperatorSlash,
TermOperatorComma
};
inline Value() : type(Unknown) { }
Type type;
QVariant variant;
Q_GUI_EXPORT QString toString() const;
};
QT_CSS_DECLARE_TYPEINFO(Value, Q_MOVABLE_TYPE)
struct ColorData {
ColorData() : role(QPalette::NoRole), type(Invalid) {}
ColorData(const QColor &col) : color(col), role(QPalette::NoRole), type(Color) {}
ColorData(QPalette::ColorRole r) : role(r), type(Role) {}
QColor color;
QPalette::ColorRole role;
enum { Invalid, Color, Role} type;
};
QT_CSS_DECLARE_TYPEINFO(ColorData, Q_MOVABLE_TYPE)
struct BrushData {
BrushData() : role(QPalette::NoRole), type(Invalid) {}
BrushData(const QBrush &br) : brush(br), role(QPalette::NoRole), type(Brush) {}
BrushData(QPalette::ColorRole r) : role(r), type(Role) {}
QBrush brush;
QPalette::ColorRole role;
enum { Invalid, Brush, Role, DependsOnThePalette } type;
};
QT_CSS_DECLARE_TYPEINFO(BrushData, Q_MOVABLE_TYPE)
struct BackgroundData {
BrushData brush;
QString image;
Repeat repeat;
Qt::Alignment alignment;
};
QT_CSS_DECLARE_TYPEINFO(BackgroundData, Q_MOVABLE_TYPE)
struct LengthData {
qreal number;
enum { None, Px, Ex, Em } unit;
};
QT_CSS_DECLARE_TYPEINFO(LengthData, Q_PRIMITIVE_TYPE)
struct BorderData {
LengthData width;
BorderStyle style;
BrushData color;
};
QT_CSS_DECLARE_TYPEINFO(BorderData, Q_MOVABLE_TYPE)
// 1. StyleRule - x:hover, y:clicked > z:checked { prop1: value1; prop2: value2; }
// 2. QVector<Selector> - x:hover, y:clicked z:checked
// 3. QVector<BasicSelector> - y:clicked z:checked
// 4. QVector<Declaration> - { prop1: value1; prop2: value2; }
// 5. Declaration - prop1: value1;
struct Q_GUI_EXPORT Declaration
{
struct DeclarationData : public QSharedData
{
inline DeclarationData() : propertyId(UnknownProperty), important(false), inheritable(false) {}
QString property;
Property propertyId;
QVector<Value> values;
QVariant parsed;
bool important:1;
bool inheritable:1;
};
QExplicitlySharedDataPointer<DeclarationData> d;
inline Declaration() : d(new DeclarationData()) {}
inline bool isEmpty() const { return d->property.isEmpty() && d->propertyId == UnknownProperty; }
// helper functions
QColor colorValue(const QPalette & = QPalette()) const;
void colorValues(QColor *c, const QPalette & = QPalette()) const;
QBrush brushValue(const QPalette & = QPalette()) const;
void brushValues(QBrush *c, const QPalette & = QPalette()) const;
BorderStyle styleValue() const;
void styleValues(BorderStyle *s) const;
Origin originValue() const;
Repeat repeatValue() const;
Qt::Alignment alignmentValue() const;
PositionMode positionValue() const;
Attachment attachmentValue() const;
int styleFeaturesValue() const;
bool intValue(int *i, const char *unit = 0) const;
bool realValue(qreal *r, const char *unit = 0) const;
QSize sizeValue() const;
QRect rectValue() const;
QString uriValue() const;
QIcon iconValue() const;
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
};
QT_CSS_DECLARE_TYPEINFO(Declaration, Q_MOVABLE_TYPE)
const quint64 PseudoClass_Unknown = Q_UINT64_C(0x0000000000000000);
const quint64 PseudoClass_Enabled = Q_UINT64_C(0x0000000000000001);
const quint64 PseudoClass_Disabled = Q_UINT64_C(0x0000000000000002);
const quint64 PseudoClass_Pressed = Q_UINT64_C(0x0000000000000004);
const quint64 PseudoClass_Focus = Q_UINT64_C(0x0000000000000008);
const quint64 PseudoClass_Hover = Q_UINT64_C(0x0000000000000010);
const quint64 PseudoClass_Checked = Q_UINT64_C(0x0000000000000020);
const quint64 PseudoClass_Unchecked = Q_UINT64_C(0x0000000000000040);
const quint64 PseudoClass_Indeterminate = Q_UINT64_C(0x0000000000000080);
const quint64 PseudoClass_Unspecified = Q_UINT64_C(0x0000000000000100);
const quint64 PseudoClass_Selected = Q_UINT64_C(0x0000000000000200);
const quint64 PseudoClass_Horizontal = Q_UINT64_C(0x0000000000000400);
const quint64 PseudoClass_Vertical = Q_UINT64_C(0x0000000000000800);
const quint64 PseudoClass_Window = Q_UINT64_C(0x0000000000001000);
const quint64 PseudoClass_Children = Q_UINT64_C(0x0000000000002000);
const quint64 PseudoClass_Sibling = Q_UINT64_C(0x0000000000004000);
const quint64 PseudoClass_Default = Q_UINT64_C(0x0000000000008000);
const quint64 PseudoClass_First = Q_UINT64_C(0x0000000000010000);
const quint64 PseudoClass_Last = Q_UINT64_C(0x0000000000020000);
const quint64 PseudoClass_Middle = Q_UINT64_C(0x0000000000040000);
const quint64 PseudoClass_OnlyOne = Q_UINT64_C(0x0000000000080000);
const quint64 PseudoClass_PreviousSelected = Q_UINT64_C(0x0000000000100000);
const quint64 PseudoClass_NextSelected = Q_UINT64_C(0x0000000000200000);
const quint64 PseudoClass_Flat = Q_UINT64_C(0x0000000000400000);
const quint64 PseudoClass_Left = Q_UINT64_C(0x0000000000800000);
const quint64 PseudoClass_Right = Q_UINT64_C(0x0000000001000000);
const quint64 PseudoClass_Top = Q_UINT64_C(0x0000000002000000);
const quint64 PseudoClass_Bottom = Q_UINT64_C(0x0000000004000000);
const quint64 PseudoClass_Exclusive = Q_UINT64_C(0x0000000008000000);
const quint64 PseudoClass_NonExclusive = Q_UINT64_C(0x0000000010000000);
const quint64 PseudoClass_Frameless = Q_UINT64_C(0x0000000020000000);
const quint64 PseudoClass_ReadOnly = Q_UINT64_C(0x0000000040000000);
const quint64 PseudoClass_Active = Q_UINT64_C(0x0000000080000000);
const quint64 PseudoClass_Closable = Q_UINT64_C(0x0000000100000000);
const quint64 PseudoClass_Movable = Q_UINT64_C(0x0000000200000000);
const quint64 PseudoClass_Floatable = Q_UINT64_C(0x0000000400000000);
const quint64 PseudoClass_Minimized = Q_UINT64_C(0x0000000800000000);
const quint64 PseudoClass_Maximized = Q_UINT64_C(0x0000001000000000);
const quint64 PseudoClass_On = Q_UINT64_C(0x0000002000000000);
const quint64 PseudoClass_Off = Q_UINT64_C(0x0000004000000000);
const quint64 PseudoClass_Editable = Q_UINT64_C(0x0000008000000000);
const quint64 PseudoClass_Item = Q_UINT64_C(0x0000010000000000);
const quint64 PseudoClass_Closed = Q_UINT64_C(0x0000020000000000);
const quint64 PseudoClass_Open = Q_UINT64_C(0x0000040000000000);
const quint64 PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000);
const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000);
// The Any specifier is never generated, but can be used as a wildcard in searches.
const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff);
const int NumPseudos = 45;
struct Pseudo
{
Pseudo() : type(0), negated(false) { }
quint64 type;
QString name;
QString function;
bool negated;
};
QT_CSS_DECLARE_TYPEINFO(Pseudo, Q_MOVABLE_TYPE)
struct AttributeSelector
{
enum ValueMatchType {
NoMatch,
MatchEqual,
MatchContains,
MatchBeginsWith
};
inline AttributeSelector() : valueMatchCriterium(NoMatch) {}
QString name;
QString value;
ValueMatchType valueMatchCriterium;
};
QT_CSS_DECLARE_TYPEINFO(AttributeSelector, Q_MOVABLE_TYPE)
struct BasicSelector
{
inline BasicSelector() : relationToNext(NoRelation) {}
enum Relation {
NoRelation,
MatchNextSelectorIfAncestor,
MatchNextSelectorIfParent,
MatchNextSelectorIfPreceeds
};
QString elementName;
QStringList ids;
QVector<Pseudo> pseudos;
QVector<AttributeSelector> attributeSelectors;
Relation relationToNext;
};
QT_CSS_DECLARE_TYPEINFO(BasicSelector, Q_MOVABLE_TYPE)
struct Q_GUI_EXPORT Selector
{
QVector<BasicSelector> basicSelectors;
int specificity() const;
quint64 pseudoClass(quint64 *negated = 0) const;
QString pseudoElement() const;
};
QT_CSS_DECLARE_TYPEINFO(Selector, Q_MOVABLE_TYPE)
struct StyleRule
{
StyleRule() : order(0) { }
QVector<Selector> selectors;
QVector<Declaration> declarations;
int order;
};
QT_CSS_DECLARE_TYPEINFO(StyleRule, Q_MOVABLE_TYPE)
struct MediaRule
{
QStringList media;
QVector<StyleRule> styleRules;
};
QT_CSS_DECLARE_TYPEINFO(MediaRule, Q_MOVABLE_TYPE)
struct PageRule
{
QString selector;
QVector<Declaration> declarations;
};
QT_CSS_DECLARE_TYPEINFO(PageRule, Q_MOVABLE_TYPE)
struct ImportRule
{
QString href;
QStringList media;
};
QT_CSS_DECLARE_TYPEINFO(ImportRule, Q_MOVABLE_TYPE)
enum StyleSheetOrigin {
StyleSheetOrigin_Unspecified,
StyleSheetOrigin_UserAgent,
StyleSheetOrigin_User,
StyleSheetOrigin_Author,
StyleSheetOrigin_Inline
};
struct StyleSheet
{
StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { }
QVector<StyleRule> styleRules; //only contains rules that are not indexed
QVector<MediaRule> mediaRules;
QVector<PageRule> pageRules;
QVector<ImportRule> importRules;
StyleSheetOrigin origin;
int depth; // applicable only for inline style sheets
QMultiHash<QString, StyleRule> nameIndex;
QMultiHash<QString, StyleRule> idIndex;
Q_GUI_EXPORT void buildIndexes(Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive);
};
QT_CSS_DECLARE_TYPEINFO(StyleSheet, Q_MOVABLE_TYPE)
class Q_GUI_EXPORT StyleSelector
{
public:
StyleSelector() : nameCaseSensitivity(Qt::CaseSensitive) {}
virtual ~StyleSelector();
union NodePtr {
void *ptr;
int id;
};
QVector<StyleRule> styleRulesForNode(NodePtr node);
QVector<Declaration> declarationsForNode(NodePtr node, const char *extraPseudo = 0);
virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const;
virtual QString attribute(NodePtr node, const QString &name) const = 0;
virtual bool hasAttributes(NodePtr node) const = 0;
virtual QStringList nodeIds(NodePtr node) const;
virtual QStringList nodeNames(NodePtr node) const = 0;
virtual bool isNullNode(NodePtr node) const = 0;
virtual NodePtr parentNode(NodePtr node) const = 0;
virtual NodePtr previousSiblingNode(NodePtr node) const = 0;
virtual NodePtr duplicateNode(NodePtr node) const = 0;
virtual void freeNode(NodePtr node) const = 0;
QVector<StyleSheet> styleSheets;
QString medium;
Qt::CaseSensitivity nameCaseSensitivity;
private:
void matchRule(NodePtr node, const StyleRule &rules, StyleSheetOrigin origin,
int depth, QMap<uint, StyleRule> *weightedRules);
bool selectorMatches(const Selector &rule, NodePtr node);
bool basicSelectorMatches(const BasicSelector &rule, NodePtr node);
};
enum TokenType {
NONE,
S,
CDO,
CDC,
INCLUDES,
DASHMATCH,
LBRACE,
PLUS,
GREATER,
COMMA,
STRING,
INVALID,
IDENT,
HASH,
ATKEYWORD_SYM,
EXCLAMATION_SYM,
LENGTH,
PERCENTAGE,
NUMBER,
FUNCTION,
COLON,
SEMICOLON,
RBRACE,
SLASH,
MINUS,
DOT,
STAR,
LBRACKET,
RBRACKET,
EQUAL,
LPAREN,
RPAREN,
OR
};
struct Symbol
{
inline Symbol() : token(NONE), start(0), len(-1) {}
TokenType token;
QString text;
int start, len;
Q_GUI_EXPORT QString lexem() const;
};
QT_CSS_DECLARE_TYPEINFO(Symbol, Q_MOVABLE_TYPE)
class Q_GUI_EXPORT Scanner
{
public:
static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
};
class Q_GUI_EXPORT Parser
{
public:
Parser();
explicit Parser(const QString &css, bool file = false);
void init(const QString &css, bool file = false);
bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive);
Symbol errorSymbol();
bool parseImport(ImportRule *importRule);
bool parseMedia(MediaRule *mediaRule);
bool parseMedium(QStringList *media);
bool parsePage(PageRule *pageRule);
bool parsePseudoPage(QString *selector);
bool parseNextOperator(Value *value);
bool parseCombinator(BasicSelector::Relation *relation);
bool parseProperty(Declaration *decl);
bool parseRuleset(StyleRule *styleRule);
bool parseSelector(Selector *sel);
bool parseSimpleSelector(BasicSelector *basicSel);
bool parseClass(QString *name);
bool parseElementName(QString *name);
bool parseAttrib(AttributeSelector *attr);
bool parsePseudo(Pseudo *pseudo);
bool parseNextDeclaration(Declaration *declaration);
bool parsePrio(Declaration *declaration);
bool parseExpr(QVector<Value> *values);
bool parseTerm(Value *value);
bool parseFunction(QString *name, QString *args);
bool parseHexColor(QColor *col);
bool testAndParseUri(QString *uri);
inline bool testRuleset() { return testSelector(); }
inline bool testSelector() { return testSimpleSelector(); }
inline bool parseNextSelector(Selector *sel) { if (!testSelector()) return recordError(); return parseSelector(sel); }
bool testSimpleSelector();
inline bool parseNextSimpleSelector(BasicSelector *basicSel) { if (!testSimpleSelector()) return recordError(); return parseSimpleSelector(basicSel); }
inline bool testElementName() { return test(IDENT) || test(STAR); }
inline bool testClass() { return test(DOT); }
inline bool testAttrib() { return test(LBRACKET); }
inline bool testPseudo() { return test(COLON); }
inline bool testMedium() { return test(IDENT); }
inline bool parseNextMedium(QStringList *media) { if (!testMedium()) return recordError(); return parseMedium(media); }
inline bool testPseudoPage() { return test(COLON); }
inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("import")); }
inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("media")); }
inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("page")); }
inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(S); }
inline bool testProperty() { return test(IDENT); }
bool testTerm();
inline bool testExpr() { return testTerm(); }
inline bool parseNextExpr(QVector<Value> *values) { if (!testExpr()) return recordError(); return parseExpr(values); }
bool testPrio();
inline bool testHexColor() { return test(HASH); }
inline bool testFunction() { return test(FUNCTION); }
inline bool parseNextFunction(QString *name, QString *args) { if (!testFunction()) return recordError(); return parseFunction(name, args); }
inline bool lookupElementName() const { return lookup() == IDENT || lookup() == STAR; }
inline void skipSpace() { while (test(S)) {}; }
inline bool hasNext() const { return index < symbols.count(); }
inline TokenType next() { return symbols.at(index++).token; }
bool next(TokenType t);
bool test(TokenType t);
inline void prev() { index--; }
inline const Symbol &symbol() const { return symbols.at(index - 1); }
inline QString lexem() const { return symbol().lexem(); }
QString unquotedLexem() const;
QString lexemUntil(TokenType t);
bool until(TokenType target, TokenType target2 = NONE);
inline TokenType lookup() const {
return (index - 1) < symbols.count() ? symbols.at(index - 1).token : NONE;
}
bool testTokenAndEndsWith(TokenType t, QLatin1String str);
inline bool recordError() { errorIndex = index; return false; }
QVector<Symbol> symbols;
int index;
int errorIndex;
bool hasEscapeSequences;
QString sourcePath;
};
struct Q_GUI_EXPORT ValueExtractor
{
ValueExtractor(const QVector<Declaration> &declarations, const QPalette & = QPalette());
bool extractFont(QFont *font, int *fontSizeAdjustment);
bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *,
QCss::Origin *);
bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh);
bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *,
QCss::PositionMode *, Qt::Alignment *);
bool extractBox(int *margins, int *paddings, int *spacing = 0);
bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii);
bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets);
bool extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg);
int extractStyleFeatures();
bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size);
int lengthValue(const Declaration &decl);
private:
void extractFont();
void borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color);
LengthData lengthValue(const Value& v);
void lengthValues(const Declaration &decl, int *m);
QSize sizeValue(const Declaration &decl);
void sizeValues(const Declaration &decl, QSize *radii);
QVector<Declaration> declarations;
QFont f;
int adjustment;
int fontExtracted;
QPalette pal;
};
} // namespace QCss
QT_END_NAMESPACE
Q_DECLARE_METATYPE( QCss::BackgroundData )
Q_DECLARE_METATYPE( QCss::LengthData )
Q_DECLARE_METATYPE( QCss::BorderData )
#undef QT_CSS_DECLARE_TYPEINFO
#endif // QT_NO_CSSPARSER
#endif

301
Telegram/private/qfont_p.h Normal file
View File

@ -0,0 +1,301 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFONT_P_H
#define QFONT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of internal files. This header file may change from version to version
// without notice, or even be removed.
//
// We mean it.
//
#include "QtGui/qfont.h"
#include "QtCore/qmap.h"
#include "QtCore/qhash.h"
#include "QtCore/qobject.h"
#include "QtCore/qstringlist.h"
#include <QtGui/qfontdatabase.h>
#include "private/qfixed_p.h"
QT_BEGIN_NAMESPACE
// forwards
class QFontCache;
class QFontEngine;
struct QFontDef
{
inline QFontDef()
: pointSize(-1.0), pixelSize(-1),
styleStrategy(QFont::PreferDefault), styleHint(QFont::AnyStyle),
weight(50), fixedPitch(false), style(QFont::StyleNormal), stretch(100),
hintingPreference(QFont::PreferDefaultHinting), ignorePitch(true),
fixedPitchComputed(0), reserved(0)
{
}
QString family;
QString styleName;
QStringList fallBackFamilies;
qreal pointSize;
qreal pixelSize;
uint styleStrategy : 16;
uint styleHint : 8;
uint weight : 7; // 0-99
uint fixedPitch : 1;
uint style : 2;
uint stretch : 12; // 0-4000
uint hintingPreference : 2;
uint ignorePitch : 1;
uint fixedPitchComputed : 1; // for Mac OS X only
int reserved : 14; // for future extensions
bool exactMatch(const QFontDef &other) const;
bool operator==(const QFontDef &other) const
{
return pixelSize == other.pixelSize
&& weight == other.weight
&& style == other.style
&& stretch == other.stretch
&& styleHint == other.styleHint
&& styleStrategy == other.styleStrategy
&& ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch
&& family == other.family
&& styleName == other.styleName
&& hintingPreference == other.hintingPreference
;
}
inline bool operator<(const QFontDef &other) const
{
if (pixelSize != other.pixelSize) return pixelSize < other.pixelSize;
if (weight != other.weight) return weight < other.weight;
if (style != other.style) return style < other.style;
if (stretch != other.stretch) return stretch < other.stretch;
if (styleHint != other.styleHint) return styleHint < other.styleHint;
if (styleStrategy != other.styleStrategy) return styleStrategy < other.styleStrategy;
if (family != other.family) return family < other.family;
if (styleName != other.styleName)
return styleName < other.styleName;
if (hintingPreference != other.hintingPreference) return hintingPreference < other.hintingPreference;
if (ignorePitch != other.ignorePitch) return ignorePitch < other.ignorePitch;
if (fixedPitch != other.fixedPitch) return fixedPitch < other.fixedPitch;
return false;
}
};
inline uint qHash(const QFontDef &fd, uint seed = 0) Q_DECL_NOTHROW
{
return qHash(qRound64(fd.pixelSize*10000)) // use only 4 fractional digits
^ qHash(fd.weight)
^ qHash(fd.style)
^ qHash(fd.stretch)
^ qHash(fd.styleHint)
^ qHash(fd.styleStrategy)
^ qHash(fd.ignorePitch)
^ qHash(fd.fixedPitch)
^ qHash(fd.family, seed)
^ qHash(fd.styleName)
^ qHash(fd.hintingPreference)
;
}
class QFontEngineData
{
public:
QFontEngineData();
~QFontEngineData();
QAtomicInt ref;
const int fontCacheId;
QFontEngine *engines[QChar::ScriptCount];
private:
Q_DISABLE_COPY(QFontEngineData)
};
class Q_GUI_EXPORT QFontPrivate
{
public:
QFontPrivate();
QFontPrivate(const QFontPrivate &other);
~QFontPrivate();
QFontEngine *engineForScript(int script) const;
void alterCharForCapitalization(QChar &c) const;
QAtomicInt ref;
QFontDef request;
mutable QFontEngineData *engineData;
int dpi;
int screen;
uint underline : 1;
uint overline : 1;
uint strikeOut : 1;
uint kerning : 1;
uint capital : 3;
bool letterSpacingIsAbsolute : 1;
QFixed letterSpacing;
QFixed wordSpacing;
mutable QFontPrivate *scFont;
QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); }
QFontPrivate *smallCapsFontPrivate() const;
static QFontPrivate *get(const QFont &font)
{
return font.d.data();
}
void resolve(uint mask, const QFontPrivate *other);
static void detachButKeepEngineData(QFont *font);
private:
QFontPrivate &operator=(const QFontPrivate &) { return *this; }
};
class Q_AUTOTEST_EXPORT QFontCache : public QObject
{
public:
// note: these static functions work on a per-thread basis
static QFontCache *instance();
static void cleanup();
QFontCache();
~QFontCache();
int id() const { return m_id; }
void clear();
struct Key {
Key() : script(0), multi(0), screen(0) { }
Key(const QFontDef &d, uchar c, bool m = 0, uchar s = 0)
: def(d), script(c), multi(m), screen(s) { }
QFontDef def;
uchar script;
uchar multi: 1;
uchar screen: 7;
inline bool operator<(const Key &other) const
{
if (script != other.script) return script < other.script;
if (screen != other.screen) return screen < other.screen;
if (multi != other.multi) return multi < other.multi;
if (multi && def.fallBackFamilies.size() != other.def.fallBackFamilies.size())
return def.fallBackFamilies.size() < other.def.fallBackFamilies.size();
return def < other.def;
}
inline bool operator==(const Key &other) const
{
return script == other.script
&& screen == other.screen
&& multi == other.multi
&& (!multi || def.fallBackFamilies == other.def.fallBackFamilies)
&& def == other.def;
}
};
// QFontEngineData cache
typedef QMap<QFontDef, QFontEngineData*> EngineDataCache;
EngineDataCache engineDataCache;
QFontEngineData *findEngineData(const QFontDef &def) const;
void insertEngineData(const QFontDef &def, QFontEngineData *engineData);
// QFontEngine cache
struct Engine {
Engine() : data(0), timestamp(0), hits(0) { }
Engine(QFontEngine *d) : data(d), timestamp(0), hits(0) { }
QFontEngine *data;
uint timestamp;
uint hits;
};
typedef QMap<Key,Engine> EngineCache;
EngineCache engineCache;
QHash<QFontEngine *, int> engineCacheCount;
QFontEngine *findEngine(const Key &key);
void updateHitCountAndTimeStamp(Engine &value);
void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false);
private:
void increaseCost(uint cost);
void decreaseCost(uint cost);
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
void decreaseCache();
static const uint min_cost;
uint total_cost, max_cost;
uint current_timestamp;
bool fast;
int timer_id;
const int m_id;
};
Q_GUI_EXPORT int qt_defaultDpiX();
Q_GUI_EXPORT int qt_defaultDpiY();
Q_GUI_EXPORT int qt_defaultDpi();
QT_END_NAMESPACE
#endif // QFONT_P_H

View File

@ -0,0 +1,506 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $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 <QtCore/qhashfunctions.h>
#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;
virtual qreal minRightBearing() const;
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; }
virtual Qt::HANDLE handle() const;
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, int cmapSize, 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;
class Holder { // replace by std::unique_ptr once available
void *ptr;
qt_destroy_func_t destroy_func;
public:
Holder() : ptr(nullptr), destroy_func(nullptr) {}
explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
Holder(Holder &&other) Q_DECL_NOTHROW
: ptr(other.ptr),
destroy_func(other.destroy_func)
{
other.ptr = nullptr;
other.destroy_func = nullptr;
}
Holder &operator=(Holder &&other) Q_DECL_NOTHROW
{ swap(other); return *this; }
void swap(Holder &other) Q_DECL_NOTHROW
{
qSwap(ptr, other.ptr);
qSwap(destroy_func, other.destroy_func);
}
void *get() const Q_DECL_NOTHROW { return ptr; }
void *release() Q_DECL_NOTHROW {
void *result = ptr;
ptr = nullptr;
destroy_func = nullptr;
return result;
}
void reset() Q_DECL_NOTHROW { Holder().swap(*this); }
qt_destroy_func_t get_deleter() const Q_DECL_NOTHROW { return destroy_func; }
bool operator!() const Q_DECL_NOTHROW { return !ptr; }
};
mutable Holder font_; // \ NOTE: Declared before m_glyphCaches, so font_, face_
mutable Holder face_; // / are destroyed _after_ m_glyphCaches is destroyed.
struct FaceData {
void *user_data;
qt_get_font_table_func_t get_font_table;
} faceData;
uint cache_cost; // amount of mem used in bytes 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;
mutable qreal m_minLeftBearing;
mutable qreal m_minRightBearing;
};
Q_DECLARE_TYPEINFO(QFontEngine::KernPair, Q_PRIMITIVE_TYPE);
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 && f1.uuid == f2.uuid;
}
inline uint qHash(const QFontEngine::FaceId &f, uint seed = 0)
Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(f.filename)))
{
QtPrivate::QHashCombine hash;
seed = hash(seed, f.filename);
seed = hash(seed, f.uuid);
seed = hash(seed, f.index);
seed = hash(seed, f.encoding);
return seed;
}
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

View File

@ -0,0 +1,888 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QFRAGMENTMAP_P_H
#define QFRAGMENTMAP_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 <stdlib.h>
#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
template <int N = 1>
class QFragment
{
public:
quint32 parent;
quint32 left;
quint32 right;
quint32 color;
quint32 size_left_array[N];
quint32 size_array[N];
enum {size_array_max = N };
};
template <class Fragment>
class QFragmentMapData
{
enum Color { Red, Black };
public:
QFragmentMapData();
~QFragmentMapData();
void init();
class Header
{
public:
quint32 root; // this relies on being at the same position as parent in the fragment struct
quint32 tag;
quint32 freelist;
quint32 node_count;
quint32 allocated;
};
enum {fragmentSize = sizeof(Fragment) };
int length(uint field = 0) const;
inline Fragment *fragment(uint index) {
return (fragments + index);
}
inline const Fragment *fragment(uint index) const {
return (fragments + index);
}
inline Fragment &F(uint index) { return fragments[index] ; }
inline const Fragment &F(uint index) const { return fragments[index] ; }
inline bool isRoot(uint index) const {
return !fragment(index)->parent;
}
inline uint position(uint node, uint field = 0) const {
Q_ASSERT(field < Fragment::size_array_max);
const Fragment *f = fragment(node);
uint offset = f->size_left_array[field];
while (f->parent) {
uint p = f->parent;
f = fragment(p);
if (f->right == node)
offset += f->size_left_array[field] + f->size_array[field];
node = p;
}
return offset;
}
inline uint sizeRight(uint node, uint field = 0) const {
Q_ASSERT(field < Fragment::size_array_max);
uint sr = 0;
const Fragment *f = fragment(node);
node = f->right;
while (node) {
f = fragment(node);
sr += f->size_left_array[field] + f->size_array[field];
node = f->right;
}
return sr;
}
inline uint sizeLeft(uint node, uint field = 0) const {
Q_ASSERT(field < Fragment::size_array_max);
return fragment(node)->size_left_array[field];
}
inline uint size(uint node, uint field = 0) const {
Q_ASSERT(field < Fragment::size_array_max);
return fragment(node)->size_array[field];
}
inline void setSize(uint node, int new_size, uint field = 0) {
Q_ASSERT(field < Fragment::size_array_max);
Fragment *f = fragment(node);
int diff = new_size - f->size_array[field];
f->size_array[field] = new_size;
while (f->parent) {
uint p = f->parent;
f = fragment(p);
if (f->left == node)
f->size_left_array[field] += diff;
node = p;
}
}
uint findNode(int k, uint field = 0) const;
uint insert_single(int key, uint length);
uint erase_single(uint f);
uint minimum(uint n) const {
while (n && fragment(n)->left)
n = fragment(n)->left;
return n;
}
uint maximum(uint n) const {
while (n && fragment(n)->right)
n = fragment(n)->right;
return n;
}
uint next(uint n) const;
uint previous(uint n) const;
inline uint root() const {
Q_ASSERT(!head->root || !fragment(head->root)->parent);
return head->root;
}
inline void setRoot(uint new_root) {
Q_ASSERT(!head->root || !fragment(new_root)->parent);
head->root = new_root;
}
inline bool isValid(uint n) const {
return n > 0 && n != head->freelist;
}
union {
Header *head;
Fragment *fragments;
};
private:
void rotateLeft(uint x);
void rotateRight(uint x);
void rebalance(uint x);
void removeAndRebalance(uint z);
uint createFragment();
void freeFragment(uint f);
};
template <class Fragment>
QFragmentMapData<Fragment>::QFragmentMapData()
: fragments(0)
{
init();
}
template <class Fragment>
void QFragmentMapData<Fragment>::init()
{
// the following code will realloc an existing fragment or create a new one.
// it will also ignore errors when shrinking an existing fragment.
Fragment *newFragments = (Fragment *)realloc(fragments, 64*fragmentSize);
if (newFragments) {
fragments = newFragments;
head->allocated = 64;
}
Q_CHECK_PTR(fragments);
head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p');
head->root = 0;
head->freelist = 1;
head->node_count = 0;
// mark all items to the right as unused
F(head->freelist).right = 0;
}
template <class Fragment>
QFragmentMapData<Fragment>::~QFragmentMapData()
{
free(fragments);
}
template <class Fragment>
uint QFragmentMapData<Fragment>::createFragment()
{
Q_ASSERT(head->freelist <= head->allocated);
uint freePos = head->freelist;
if (freePos == head->allocated) {
// need to create some free space
if (freePos >= uint(MaxAllocSize) / fragmentSize)
qBadAlloc();
uint needed = qAllocMore((freePos+1)*fragmentSize, 0);
Q_ASSERT(needed/fragmentSize > head->allocated);
Fragment *newFragments = (Fragment *)realloc(fragments, needed);
Q_CHECK_PTR(newFragments);
fragments = newFragments;
head->allocated = needed/fragmentSize;
F(freePos).right = 0;
}
uint nextPos = F(freePos).right;
if (!nextPos) {
nextPos = freePos+1;
if (nextPos < head->allocated)
F(nextPos).right = 0;
}
head->freelist = nextPos;
++head->node_count;
return freePos;
}
template <class Fragment>
void QFragmentMapData<Fragment>::freeFragment(uint i)
{
F(i).right = head->freelist;
head->freelist = i;
--head->node_count;
}
template <class Fragment>
uint QFragmentMapData<Fragment>::next(uint n) const {
Q_ASSERT(n);
if (F(n).right) {
n = F(n).right;
while (F(n).left)
n = F(n).left;
} else {
uint y = F(n).parent;
while (F(n).parent && n == F(y).right) {
n = y;
y = F(y).parent;
}
n = y;
}
return n;
}
template <class Fragment>
uint QFragmentMapData<Fragment>::previous(uint n) const {
if (!n)
return maximum(root());
if (F(n).left) {
n = F(n).left;
while (F(n).right)
n = F(n).right;
} else {
uint y = F(n).parent;
while (F(n).parent && n == F(y).left) {
n = y;
y = F(y).parent;
}
n = y;
}
return n;
}
/*
x y
\ / \
y --> x b
/ \ \
a b a
*/
template <class Fragment>
void QFragmentMapData<Fragment>::rotateLeft(uint x)
{
uint p = F(x).parent;
uint y = F(x).right;
if (y) {
F(x).right = F(y).left;
if (F(y).left)
F(F(y).left).parent = x;
F(y).left = x;
F(y).parent = p;
} else {
F(x).right = 0;
}
if (!p) {
Q_ASSERT(head->root == x);
head->root = y;
}
else if (x == F(p).left)
F(p).left = y;
else
F(p).right = y;
F(x).parent = y;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(y).size_left_array[field] += F(x).size_left_array[field] + F(x).size_array[field];
}
/*
x y
/ / \
y --> a x
/ \ /
a b b
*/
template <class Fragment>
void QFragmentMapData<Fragment>::rotateRight(uint x)
{
uint y = F(x).left;
uint p = F(x).parent;
if (y) {
F(x).left = F(y).right;
if (F(y).right)
F(F(y).right).parent = x;
F(y).right = x;
F(y).parent = p;
} else {
F(x).left = 0;
}
if (!p) {
Q_ASSERT(head->root == x);
head->root = y;
}
else if (x == F(p).right)
F(p).right = y;
else
F(p).left = y;
F(x).parent = y;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(x).size_left_array[field] -= F(y).size_left_array[field] + F(y).size_array[field];
}
template <class Fragment>
void QFragmentMapData<Fragment>::rebalance(uint x)
{
F(x).color = Red;
while (F(x).parent && F(F(x).parent).color == Red) {
uint p = F(x).parent;
uint pp = F(p).parent;
Q_ASSERT(pp);
if (p == F(pp).left) {
uint y = F(pp).right;
if (y && F(y).color == Red) {
F(p).color = Black;
F(y).color = Black;
F(pp).color = Red;
x = pp;
} else {
if (x == F(p).right) {
x = p;
rotateLeft(x);
p = F(x).parent;
pp = F(p).parent;
}
F(p).color = Black;
if (pp) {
F(pp).color = Red;
rotateRight(pp);
}
}
} else {
uint y = F(pp).left;
if (y && F(y).color == Red) {
F(p).color = Black;
F(y).color = Black;
F(pp).color = Red;
x = pp;
} else {
if (x == F(p).left) {
x = p;
rotateRight(x);
p = F(x).parent;
pp = F(p).parent;
}
F(p).color = Black;
if (pp) {
F(pp).color = Red;
rotateLeft(pp);
}
}
}
}
F(root()).color = Black;
}
template <class Fragment>
uint QFragmentMapData<Fragment>::erase_single(uint z)
{
uint w = previous(z);
uint y = z;
uint x;
uint p;
if (!F(y).left) {
x = F(y).right;
} else if (!F(y).right) {
x = F(y).left;
} else {
y = F(y).right;
while (F(y).left)
y = F(y).left;
x = F(y).right;
}
if (y != z) {
F(F(z).left).parent = y;
F(y).left = F(z).left;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(y).size_left_array[field] = F(z).size_left_array[field];
if (y != F(z).right) {
/*
z y
/ \ / \
a b a b
/ /
... --> ...
/ /
y x
/ \
0 x
*/
p = F(y).parent;
if (x)
F(x).parent = p;
F(p).left = x;
F(y).right = F(z).right;
F(F(z).right).parent = y;
uint n = p;
while (n != y) {
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(n).size_left_array[field] -= F(y).size_array[field];
n = F(n).parent;
}
} else {
/*
z y
/ \ / \
a y --> a x
/ \
0 x
*/
p = y;
}
uint zp = F(z).parent;
if (!zp) {
Q_ASSERT(head->root == z);
head->root = y;
} else if (F(zp).left == z) {
F(zp).left = y;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(zp).size_left_array[field] -= F(z).size_array[field];
} else {
F(zp).right = y;
}
F(y).parent = zp;
// Swap the colors
uint c = F(y).color;
F(y).color = F(z).color;
F(z).color = c;
y = z;
} else {
/*
p p p p
/ / \ \
z --> x z --> x
| |
x x
*/
p = F(z).parent;
if (x)
F(x).parent = p;
if (!p) {
Q_ASSERT(head->root == z);
head->root = x;
} else if (F(p).left == z) {
F(p).left = x;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(p).size_left_array[field] -= F(z).size_array[field];
} else {
F(p).right = x;
}
}
uint n = z;
while (F(n).parent) {
uint p = F(n).parent;
if (F(p).left == n) {
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(p).size_left_array[field] -= F(z).size_array[field];
}
n = p;
}
freeFragment(z);
if (F(y).color != Red) {
while (F(x).parent && (x == 0 || F(x).color == Black)) {
if (x == F(p).left) {
uint w = F(p).right;
if (F(w).color == Red) {
F(w).color = Black;
F(p).color = Red;
rotateLeft(p);
w = F(p).right;
}
if ((F(w).left == 0 || F(F(w).left).color == Black) &&
(F(w).right == 0 || F(F(w).right).color == Black)) {
F(w).color = Red;
x = p;
p = F(x).parent;
} else {
if (F(w).right == 0 || F(F(w).right).color == Black) {
if (F(w).left)
F(F(w).left).color = Black;
F(w).color = Red;
rotateRight(F(p).right);
w = F(p).right;
}
F(w).color = F(p).color;
F(p).color = Black;
if (F(w).right)
F(F(w).right).color = Black;
rotateLeft(p);
break;
}
} else {
uint w = F(p).left;
if (F(w).color == Red) {
F(w).color = Black;
F(p).color = Red;
rotateRight(p);
w = F(p).left;
}
if ((F(w).right == 0 || F(F(w).right).color == Black) &&
(F(w).left == 0 || F(F(w).left).color == Black)) {
F(w).color = Red;
x = p;
p = F(x).parent;
} else {
if (F(w).left == 0 || F(F(w).left).color == Black) {
if (F(w).right)
F(F(w).right).color = Black;
F(w).color = Red;
rotateLeft(F(p).left);
w = F(p).left;
}
F(w).color = F(p).color;
F(p).color = Black;
if (F(w).left)
F(F(w).left).color = Black;
rotateRight(p);
break;
}
}
}
if (x)
F(x).color = Black;
}
return w;
}
template <class Fragment>
uint QFragmentMapData<Fragment>::findNode(int k, uint field) const
{
Q_ASSERT(field < Fragment::size_array_max);
uint x = root();
uint s = k;
while (x) {
if (sizeLeft(x, field) <= s) {
if (s < sizeLeft(x, field) + size(x, field))
return x;
s -= sizeLeft(x, field) + size(x, field);
x = F(x).right;
} else {
x = F(x).left;
}
}
return 0;
}
template <class Fragment>
uint QFragmentMapData<Fragment>::insert_single(int key, uint length)
{
Q_ASSERT(!findNode(key) || (int)this->position(findNode(key)) == key);
uint z = createFragment();
F(z).left = 0;
F(z).right = 0;
F(z).size_array[0] = length;
for (uint field = 1; field < Fragment::size_array_max; ++field)
F(z).size_array[field] = 1;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(z).size_left_array[field] = 0;
uint y = 0;
uint x = root();
Q_ASSERT(!x || F(x).parent == 0);
uint s = key;
bool right = false;
while (x) {
y = x;
if (s <= F(x).size_left_array[0]) {
x = F(x).left;
right = false;
} else {
s -= F(x).size_left_array[0] + F(x).size_array[0];
x = F(x).right;
right = true;
}
}
F(z).parent = y;
if (!y) {
head->root = z;
} else if (!right) {
F(y).left = z;
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(y).size_left_array[field] = F(z).size_array[field];
} else {
F(y).right = z;
}
while (y && F(y).parent) {
uint p = F(y).parent;
if (F(p).left == y) {
for (uint field = 0; field < Fragment::size_array_max; ++field)
F(p).size_left_array[field] += F(z).size_array[field];
}
y = p;
}
rebalance(z);
return z;
}
template <class Fragment>
int QFragmentMapData<Fragment>::length(uint field) const {
uint root = this->root();
return root ? sizeLeft(root, field) + size(root, field) + sizeRight(root, field) : 0;
}
template <class Fragment> // NOTE: must inherit QFragment
class QFragmentMap
{
public:
class Iterator
{
public:
QFragmentMap *pt;
quint32 n;
Iterator() : pt(0), n(0) {}
Iterator(QFragmentMap *p, int node) : pt(p), n(node) {}
Iterator(const Iterator& it) : pt(it.pt), n(it.n) {}
inline bool atEnd() const { return !n; }
bool operator==(const Iterator& it) const { return pt == it.pt && n == it.n; }
bool operator!=(const Iterator& it) const { return pt != it.pt || n != it.n; }
bool operator<(const Iterator &it) const { return position() < it.position(); }
Fragment *operator*() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
const Fragment *operator*() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
Fragment *operator->() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
const Fragment *operator->() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); }
const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
Fragment *value() { Q_ASSERT(!atEnd()); return pt->fragment(n); }
Iterator& operator++() {
n = pt->data.next(n);
return *this;
}
Iterator& operator--() {
n = pt->data.previous(n);
return *this;
}
};
class ConstIterator
{
public:
const QFragmentMap *pt;
quint32 n;
/**
* Functions
*/
ConstIterator() : pt(0), n(0) {}
ConstIterator(const QFragmentMap *p, int node) : pt(p), n(node) {}
ConstIterator(const ConstIterator& it) : pt(it.pt), n(it.n) {}
ConstIterator(const Iterator& it) : pt(it.pt), n(it.n) {}
inline bool atEnd() const { return !n; }
bool operator==(const ConstIterator& it) const { return pt == it.pt && n == it.n; }
bool operator!=(const ConstIterator& it) const { return pt != it.pt || n != it.n; }
bool operator<(const ConstIterator &it) const { return position() < it.position(); }
const Fragment *operator*() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
const Fragment *operator->() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
int position() const { Q_ASSERT(!atEnd()); return pt->data.position(n); }
int size() const { Q_ASSERT(!atEnd()); return pt->data.size(n); }
const Fragment *value() const { Q_ASSERT(!atEnd()); return pt->fragment(n); }
ConstIterator& operator++() {
n = pt->data.next(n);
return *this;
}
ConstIterator& operator--() {
n = pt->data.previous(n);
return *this;
}
};
QFragmentMap() {}
~QFragmentMap()
{
if (!data.fragments)
return; // in case of out-of-memory, we won't have fragments
for (Iterator it = begin(); !it.atEnd(); ++it)
it.value()->free();
}
inline void clear() {
for (Iterator it = begin(); !it.atEnd(); ++it)
it.value()->free();
data.init();
}
inline Iterator begin() { return Iterator(this, data.minimum(data.root())); }
inline Iterator end() { return Iterator(this, 0); }
inline ConstIterator begin() const { return ConstIterator(this, data.minimum(data.root())); }
inline ConstIterator end() const { return ConstIterator(this, 0); }
inline ConstIterator last() const { return ConstIterator(this, data.maximum(data.root())); }
inline bool isEmpty() const { return data.head->node_count == 0; }
inline int numNodes() const { return data.head->node_count; }
int length(uint field = 0) const { return data.length(field); }
Iterator find(int k, uint field = 0) { return Iterator(this, data.findNode(k, field)); }
ConstIterator find(int k, uint field = 0) const { return ConstIterator(this, data.findNode(k, field)); }
uint findNode(int k, uint field = 0) const { return data.findNode(k, field); }
uint insert_single(int key, uint length)
{
uint f = data.insert_single(key, length);
if (f != 0) {
Fragment *frag = fragment(f);
Q_ASSERT(frag);
frag->initialize();
}
return f;
}
uint erase_single(uint f)
{
if (f != 0) {
Fragment *frag = fragment(f);
Q_ASSERT(frag);
frag->free();
}
return data.erase_single(f);
}
inline Fragment *fragment(uint index) {
Q_ASSERT(index != 0);
return data.fragment(index);
}
inline const Fragment *fragment(uint index) const {
Q_ASSERT(index != 0);
return data.fragment(index);
}
inline uint position(uint node, uint field = 0) const { return data.position(node, field); }
inline bool isValid(uint n) const { return data.isValid(n); }
inline uint next(uint n) const { return data.next(n); }
inline uint previous(uint n) const { return data.previous(n); }
inline uint size(uint node, uint field = 0) const { return data.size(node, field); }
inline void setSize(uint node, int new_size, uint field = 0)
{ data.setSize(node, new_size, field);
if (node != 0 && field == 0) {
Fragment *frag = fragment(node);
Q_ASSERT(frag);
frag->invalidate();
}
}
inline int firstNode() const { return data.minimum(data.root()); }
private:
friend class Iterator;
friend class ConstIterator;
QFragmentMapData<Fragment> data;
QFragmentMap(const QFragmentMap& m);
QFragmentMap& operator= (const QFragmentMap& m);
};
QT_END_NAMESPACE
#endif // QFRAGMENTMAP_P_H

View File

@ -0,0 +1,355 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// 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.
//
#ifndef QHARFBUZZ_P_H
#define QHARFBUZZ_P_H
#include <QtCore/qchar.h>
#if defined(QT_BUILD_CORE_LIB)
# include <harfbuzz-shaper.h>
#else
// a minimal set of HB types required for Qt libs other than Core
extern "C" {
typedef enum {
/* no error */
HB_Err_Ok = 0x0000,
HB_Err_Not_Covered = 0xFFFF,
/* _hb_err() is called whenever returning the following errors,
* and in a couple places for HB_Err_Not_Covered too. */
/* programmer error */
HB_Err_Invalid_Argument = 0x1A66,
/* font error */
HB_Err_Invalid_SubTable_Format = 0x157F,
HB_Err_Invalid_SubTable = 0x1570,
HB_Err_Read_Error = 0x6EAD,
/* system error */
HB_Err_Out_Of_Memory = 0xDEAD
} HB_Error;
typedef QT_PREPEND_NAMESPACE(qint8) hb_int8;
typedef QT_PREPEND_NAMESPACE(quint8) hb_uint8;
typedef QT_PREPEND_NAMESPACE(qint16) hb_int16;
typedef QT_PREPEND_NAMESPACE(quint16) hb_uint16;
typedef QT_PREPEND_NAMESPACE(qint32) hb_int32;
typedef QT_PREPEND_NAMESPACE(quint32) hb_uint32;
typedef hb_uint8 HB_Bool;
typedef hb_uint8 HB_Byte;
typedef hb_uint16 HB_UShort;
typedef hb_uint32 HB_UInt;
typedef hb_int8 HB_Char;
typedef hb_int16 HB_Short;
typedef hb_int32 HB_Int;
typedef hb_uint16 HB_UChar16;
typedef hb_uint32 HB_UChar32;
typedef hb_uint32 HB_Glyph;
typedef hb_int32 HB_Fixed; /* 26.6 */
typedef hb_int32 HB_16Dot16; /* 16.16 */
typedef hb_uint32 HB_Tag;
typedef struct {
HB_Fixed x;
HB_Fixed y;
} HB_FixedPoint;
typedef enum {
HB_Script_Common,
HB_Script_Greek,
HB_Script_Cyrillic,
HB_Script_Armenian,
HB_Script_Hebrew,
HB_Script_Arabic,
HB_Script_Syriac,
HB_Script_Thaana,
HB_Script_Devanagari,
HB_Script_Bengali,
HB_Script_Gurmukhi,
HB_Script_Gujarati,
HB_Script_Oriya,
HB_Script_Tamil,
HB_Script_Telugu,
HB_Script_Kannada,
HB_Script_Malayalam,
HB_Script_Sinhala,
HB_Script_Thai,
HB_Script_Lao,
HB_Script_Tibetan,
HB_Script_Myanmar,
HB_Script_Georgian,
HB_Script_Hangul,
HB_Script_Ogham,
HB_Script_Runic,
HB_Script_Khmer,
HB_Script_Nko,
HB_Script_Inherited,
HB_ScriptCount = HB_Script_Inherited
} HB_Script;
#ifdef __xlC__
typedef unsigned hb_bitfield;
#else
typedef hb_uint8 hb_bitfield;
#endif
typedef struct {
hb_bitfield justification :4; /* Justification class */
hb_bitfield clusterStart :1; /* First glyph of representation of cluster */
hb_bitfield mark :1; /* needs to be positioned around base char */
hb_bitfield zeroWidth :1; /* ZWJ, ZWNJ etc, with no width */
hb_bitfield dontPrint :1;
hb_bitfield combiningClass :8;
} HB_GlyphAttributes;
typedef void * HB_GDEF;
typedef void * HB_GSUB;
typedef void * HB_GPOS;
typedef void * HB_Buffer;
typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length);
typedef struct HB_FaceRec_ {
HB_Bool isSymbolFont;
HB_GDEF gdef;
HB_GSUB gsub;
HB_GPOS gpos;
HB_Bool supported_scripts[HB_ScriptCount];
HB_Buffer buffer;
HB_Script current_script;
int current_flags; /* HB_ShaperFlags */
HB_Bool has_opentype_kerning;
HB_Bool glyphs_substituted;
HB_GlyphAttributes *tmpAttributes;
unsigned int *tmpLogClusters;
int length;
int orig_nglyphs;
void *font_for_init;
HB_GetFontTableFunc get_font_table_func;
} HB_FaceRec;
typedef struct {
HB_Fixed x, y;
HB_Fixed width, height;
HB_Fixed xOffset, yOffset;
} HB_GlyphMetrics;
typedef enum {
HB_FontAscent
} HB_FontMetric;
struct HB_Font_;
typedef struct HB_Font_ *HB_Font;
typedef struct HB_FaceRec_ *HB_Face;
typedef struct {
HB_Bool (*convertStringToGlyphIndices)(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft);
void (*getGlyphAdvances)(HB_Font font, const HB_Glyph *glyphs, hb_uint32 numGlyphs, HB_Fixed *advances, int flags /*HB_ShaperFlag*/);
HB_Bool (*canRender)(HB_Font font, const HB_UChar16 *string, hb_uint32 length);
/* implementation needs to make sure to load a scaled glyph, so /no/ FT_LOAD_NO_SCALE */
HB_Error (*getPointInOutline)(HB_Font font, HB_Glyph glyph, int flags /*HB_ShaperFlag*/, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints);
void (*getGlyphMetrics)(HB_Font font, HB_Glyph glyph, HB_GlyphMetrics *metrics);
HB_Fixed (*getFontMetric)(HB_Font font, HB_FontMetric metric);
} HB_FontClass;
typedef struct HB_Font_ {
const HB_FontClass *klass;
/* Metrics */
HB_UShort x_ppem, y_ppem;
HB_16Dot16 x_scale, y_scale;
void *userData;
} HB_FontRec;
typedef enum {
HB_LeftToRight = 0,
HB_RightToLeft = 1
} HB_StringToGlyphsFlags;
typedef enum {
HB_ShaperFlag_Default = 0,
HB_ShaperFlag_NoKerning = 1,
HB_ShaperFlag_UseDesignMetrics = 2
} HB_ShaperFlag;
typedef struct
{
hb_uint32 pos;
hb_uint32 length;
HB_Script script;
hb_uint8 bidiLevel;
} HB_ScriptItem;
typedef struct HB_ShaperItem_ HB_ShaperItem;
struct HB_ShaperItem_ {
const HB_UChar16 *string; /* input: the Unicode UTF16 text to be shaped */
hb_uint32 stringLength; /* input: the length of the input in 16-bit words */
HB_ScriptItem item; /* input: the current run to be shaped: a run of text all in the same script that is a substring of <string> */
HB_Font font; /* input: the font: scale, units and function pointers supplying glyph indices and metrics */
HB_Face face; /* input: the shaper state; current script, access to the OpenType tables , etc. */
int shaperFlags; /* input (unused) should be set to 0; intended to support flags defined in HB_ShaperFlag */
HB_Bool glyphIndicesPresent; /* input: true if the <glyphs> array contains glyph indices ready to be shaped */
hb_uint32 initialGlyphCount; /* input: if glyphIndicesPresent is true, the number of glyph indices in the <glyphs> array */
hb_uint32 num_glyphs; /* input: capacity of output arrays <glyphs>, <attributes>, <advances>, <offsets>, and <log_clusters>; */
/* output: required capacity (may be larger than actual capacity) */
HB_Glyph *glyphs; /* output: <num_glyphs> indices of shaped glyphs */
HB_GlyphAttributes *attributes; /* output: <num_glyphs> glyph attributes */
HB_Fixed *advances; /* output: <num_glyphs> advances */
HB_FixedPoint *offsets; /* output: <num_glyphs> offsets */
unsigned short *log_clusters; /* output: for each output glyph, the index in the input of the start of its logical cluster */
/* internal */
HB_Bool kerning_applied; /* output: true if kerning was applied by the shaper */
};
}
#endif // QT_BUILD_CORE_LIB
QT_BEGIN_NAMESPACE
static inline HB_Script script_to_hbscript(uchar script)
{
switch (script) {
case QChar::Script_Inherited: return HB_Script_Inherited;
case QChar::Script_Common: return HB_Script_Common;
case QChar::Script_Arabic: return HB_Script_Arabic;
case QChar::Script_Armenian: return HB_Script_Armenian;
case QChar::Script_Bengali: return HB_Script_Bengali;
case QChar::Script_Cyrillic: return HB_Script_Cyrillic;
case QChar::Script_Devanagari: return HB_Script_Devanagari;
case QChar::Script_Georgian: return HB_Script_Georgian;
case QChar::Script_Greek: return HB_Script_Greek;
case QChar::Script_Gujarati: return HB_Script_Gujarati;
case QChar::Script_Gurmukhi: return HB_Script_Gurmukhi;
case QChar::Script_Hangul: return HB_Script_Hangul;
case QChar::Script_Hebrew: return HB_Script_Hebrew;
case QChar::Script_Kannada: return HB_Script_Kannada;
case QChar::Script_Khmer: return HB_Script_Khmer;
case QChar::Script_Lao: return HB_Script_Lao;
case QChar::Script_Malayalam: return HB_Script_Malayalam;
case QChar::Script_Myanmar: return HB_Script_Myanmar;
case QChar::Script_Ogham: return HB_Script_Ogham;
case QChar::Script_Oriya: return HB_Script_Oriya;
case QChar::Script_Runic: return HB_Script_Runic;
case QChar::Script_Sinhala: return HB_Script_Sinhala;
case QChar::Script_Syriac: return HB_Script_Syriac;
case QChar::Script_Tamil: return HB_Script_Tamil;
case QChar::Script_Telugu: return HB_Script_Telugu;
case QChar::Script_Thaana: return HB_Script_Thaana;
case QChar::Script_Thai: return HB_Script_Thai;
case QChar::Script_Tibetan: return HB_Script_Tibetan;
case QChar::Script_Nko: return HB_Script_Nko;
default: break;
};
return HB_Script_Common;
}
static inline uchar hbscript_to_script(uchar script)
{
switch (script) {
case HB_Script_Inherited: return QChar::Script_Inherited;
case HB_Script_Common: return QChar::Script_Common;
case HB_Script_Arabic: return QChar::Script_Arabic;
case HB_Script_Armenian: return QChar::Script_Armenian;
case HB_Script_Bengali: return QChar::Script_Bengali;
case HB_Script_Cyrillic: return QChar::Script_Cyrillic;
case HB_Script_Devanagari: return QChar::Script_Devanagari;
case HB_Script_Georgian: return QChar::Script_Georgian;
case HB_Script_Greek: return QChar::Script_Greek;
case HB_Script_Gujarati: return QChar::Script_Gujarati;
case HB_Script_Gurmukhi: return QChar::Script_Gurmukhi;
case HB_Script_Hangul: return QChar::Script_Hangul;
case HB_Script_Hebrew: return QChar::Script_Hebrew;
case HB_Script_Kannada: return QChar::Script_Kannada;
case HB_Script_Khmer: return QChar::Script_Khmer;
case HB_Script_Lao: return QChar::Script_Lao;
case HB_Script_Malayalam: return QChar::Script_Malayalam;
case HB_Script_Myanmar: return QChar::Script_Myanmar;
case HB_Script_Ogham: return QChar::Script_Ogham;
case HB_Script_Oriya: return QChar::Script_Oriya;
case HB_Script_Runic: return QChar::Script_Runic;
case HB_Script_Sinhala: return QChar::Script_Sinhala;
case HB_Script_Syriac: return QChar::Script_Syriac;
case HB_Script_Tamil: return QChar::Script_Tamil;
case HB_Script_Telugu: return QChar::Script_Telugu;
case HB_Script_Thaana: return QChar::Script_Thaana;
case HB_Script_Thai: return QChar::Script_Thai;
case HB_Script_Tibetan: return QChar::Script_Tibetan;
case HB_Script_Nko: return QChar::Script_Nko;
default: break;
};
return QChar::Script_Common;
}
Q_CORE_EXPORT HB_Bool qShapeItem(HB_ShaperItem *item);
// ### temporary
Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc);
Q_CORE_EXPORT void qHBFreeFace(HB_Face);
Q_CORE_EXPORT HB_Face qHBLoadFace(HB_Face face);
Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(HB_ScriptItem, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
#endif // QHARFBUZZ_P_H

View File

@ -0,0 +1,441 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QOBJECT_P_H
#define QOBJECT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
// file may change from version to version without notice, or even be removed.
//
// We mean it.
//
#include "QtCore/qobject.h"
#include "QtCore/qpointer.h"
#include "QtCore/qsharedpointer.h"
#include "QtCore/qcoreevent.h"
#include "QtCore/qlist.h"
#include "QtCore/qvector.h"
#include "QtCore/qvariant.h"
#include "QtCore/qreadwritelock.h"
QT_BEGIN_NAMESPACE
class QVariant;
class QThreadData;
class QObjectConnectionListVector;
namespace QtSharedPointer { struct ExternalRefCountData; }
/* for Qt Test */
struct QSignalSpyCallbackSet
{
typedef void (*BeginCallback)(QObject *caller, int signal_or_method_index, void **argv);
typedef void (*EndCallback)(QObject *caller, int signal_or_method_index);
BeginCallback signal_begin_callback,
slot_begin_callback;
EndCallback signal_end_callback,
slot_end_callback;
};
void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
enum { QObjectPrivateVersion = QT_VERSION };
class Q_CORE_EXPORT QAbstractDeclarativeData
{
public:
static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *);
static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **);
static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int);
static bool (*isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int);
static void (*setWidgetParent)(QObject *, QObject *); // Used by the QML engine to specify parents for widgets. Set by QtWidgets.
};
// This is an implementation of QAbstractDeclarativeData that is identical with
// the implementation in QtDeclarative and QtQml for the first bit
struct QAbstractDeclarativeDataImpl : public QAbstractDeclarativeData
{
quint32 ownedByQml1:1;
quint32 unused: 31;
};
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
{
Q_DECLARE_PUBLIC(QObject)
public:
struct ExtraData
{
ExtraData() {}
#ifndef QT_NO_USERDATA
QVector<QObjectUserData *> userData;
#endif
QList<QByteArray> propertyNames;
QVector<QVariant> propertyValues;
QVector<int> runningTimers;
QList<QPointer<QObject> > eventFilters;
QString objectName;
};
typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
struct Connection
{
QObject *sender;
QObject *receiver;
union {
StaticMetaCallFunction callFunction;
QtPrivate::QSlotObjectBase *slotObj;
};
// The next pointer for the singly-linked ConnectionList
Connection *nextConnectionList;
//senders linked list
Connection *next;
Connection **prev;
QAtomicPointer<const int> argumentTypes;
QAtomicInt ref_;
ushort method_offset;
ushort method_relative;
uint signal_index : 27; // In signal range (see QObjectPrivate::signalIndex())
ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
ushort isSlotObject : 1;
ushort ownArgumentTypes : 1;
Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) {
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
}
~Connection();
int method() const { Q_ASSERT(!isSlotObject); return method_offset + method_relative; }
void ref() { ref_.ref(); }
void deref() {
if (!ref_.deref()) {
Q_ASSERT(!receiver);
delete this;
}
}
};
// ConnectionList is a singly-linked list
struct ConnectionList {
ConnectionList() : first(0), last(0) {}
Connection *first;
Connection *last;
};
struct Sender
{
QObject *sender;
int signal;
int ref;
};
QObjectPrivate(int version = QObjectPrivateVersion);
virtual ~QObjectPrivate();
void deleteChildren();
void setParent_helper(QObject *);
void moveToThread_helper();
void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
void _q_reregisterTimers(void *pointer);
bool isSender(const QObject *receiver, const char *signal) const;
QObjectList receiverList(const char *signal) const;
QObjectList senderList() const;
void addConnection(int signal, Connection *c);
void cleanConnectionLists();
static inline Sender *setCurrentSender(QObject *receiver,
Sender *sender);
static inline void resetCurrentSender(QObject *receiver,
Sender *currentSender,
Sender *previousSender);
static QObjectPrivate *get(QObject *o) {
return o->d_func();
}
int signalIndex(const char *signalName, const QMetaObject **meta = 0) const;
inline bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
inline bool isDeclarativeSignalConnected(uint signalIdx) const;
// To allow abitrary objects to call connectNotify()/disconnectNotify() without making
// the API public in QObject. This is used by QQmlNotifierEndpoint.
inline void connectNotify(const QMetaMethod &signal);
inline void disconnectNotify(const QMetaMethod &signal);
template <typename Func1, typename Func2>
static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection);
template <typename Func1, typename Func2>
static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
const QObject *receiver, void **slot,
QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
const int *types, const QMetaObject *senderMetaObject);
static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
static bool disconnect(const QObject *sender, int signal_index, void **slot);
public:
ExtraData *extraData; // extra data set by the user
QThreadData *threadData; // id of the thread that owns the object
QObjectConnectionListVector *connectionLists;
Connection *senders; // linked list of connections connected to this object
Sender *currentSender; // object currently activating the object
mutable quint32 connectedSignals[2];
union {
QObject *currentChildBeingDeleted;
QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
};
// these objects are all used to indicate that a QObject was deleted
// plus QPointer, which keeps a separate list
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
/*! \internal
Returns \c true if the signal with index \a signal_index from object \a sender is connected.
Signals with indices above a certain range are always considered connected (see connectedSignals
in QObjectPrivate).
\a signal_index must be the index returned by QObjectPrivate::signalIndex;
*/
inline bool QObjectPrivate::isSignalConnected(uint signal_index, bool checkDeclarative) const
{
return signal_index >= sizeof(connectedSignals) * 8
|| (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
|| (checkDeclarative && isDeclarativeSignalConnected(signal_index)));
}
inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
{
return declarativeData && QAbstractDeclarativeData::isSignalConnected
&& QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
}
inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
Sender *sender)
{
Sender *previousSender = receiver->d_func()->currentSender;
receiver->d_func()->currentSender = sender;
return previousSender;
}
inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
Sender *currentSender,
Sender *previousSender)
{
// ref is set to zero when this object is deleted during the metacall
if (currentSender->ref == 1)
receiver->d_func()->currentSender = previousSender;
// if we've recursed, we need to tell the caller about the objects deletion
if (previousSender)
previousSender->ref = currentSender->ref;
}
inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
{
q_ptr->connectNotify(signal);
}
inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
{
q_ptr->disconnectNotify(signal);
}
namespace QtPrivate {
template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase
{
typedef QtPrivate::FunctionPointer<Func> FuncType;
Func function;
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
{
switch (which) {
case Destroy:
delete static_cast<QPrivateSlotObject*>(this_);
break;
case Call:
FuncType::template call<Args, R>(static_cast<QPrivateSlotObject*>(this_)->function,
static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
break;
case Compare:
*ret = *reinterpret_cast<Func *>(a) == static_cast<QPrivateSlotObject*>(this_)->function;
break;
case NumOperations: ;
}
}
public:
explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
};
} //namespace QtPrivate
template <typename Func1, typename Func2>
inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
Qt::ConnectionType type)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
//compilation error if the arguments does not match.
Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
"The slot requires more arguments than the signal provides.");
Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
"Signal and slot arguments are not compatible.");
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
const int *types = 0;
if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return QObject::connectImpl(sender, reinterpret_cast<void **>(&signal),
receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
type, types, &SignalType::Object::staticMetaObject);
}
template <typename Func1, typename Func2>
bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object* sender, Func1 signal,
const typename QtPrivate::FunctionPointer< Func2 >::Object* receiverPrivate, Func2 slot)
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
typedef QtPrivate::FunctionPointer<Func2> SlotType;
Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");
//compilation error if the arguments does not match.
Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
"Signal and slot arguments are not compatible.");
return QObject::disconnectImpl(sender, reinterpret_cast<void **>(&signal),
receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
&SignalType::Object::staticMetaObject);
}
Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
class QSemaphore;
class Q_CORE_EXPORT QMetaCallEvent : public QEvent
{
public:
QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
/*! \internal
\a signalId is in the signal index range (see QObjectPrivate::signalIndex()).
*/
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj, const QObject *sender, int signalId,
int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
~QMetaCallEvent();
inline int id() const { return method_offset_ + method_relative_; }
inline const QObject *sender() const { return sender_; }
inline int signalId() const { return signalId_; }
inline void **args() const { return args_; }
virtual void placeMetaCall(QObject *object);
private:
QtPrivate::QSlotObjectBase *slotObj_;
const QObject *sender_;
int signalId_;
int nargs_;
int *types_;
void **args_;
QSemaphore *semaphore_;
QObjectPrivate::StaticMetaCallFunction callFunction_;
ushort method_offset_;
ushort method_relative_;
};
class QBoolBlocker
{
Q_DISABLE_COPY(QBoolBlocker)
public:
explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
inline ~QBoolBlocker(){block = reset; }
private:
bool &block;
bool reset;
};
void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
struct QAbstractDynamicMetaObject;
struct Q_CORE_EXPORT QDynamicMetaObjectData
{
virtual ~QDynamicMetaObjectData();
virtual void objectDestroyed(QObject *) { delete this; }
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) = 0;
virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;
};
struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject
{
~QAbstractDynamicMetaObject();
virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) Q_DECL_OVERRIDE { return this; }
virtual int createProperty(const char *, const char *) { return -1; }
virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) Q_DECL_OVERRIDE
{ return metaCall(c, _id, a); }
virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
};
QT_END_NAMESPACE
#endif // QOBJECT_P_H

View File

@ -0,0 +1,411 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTDOCUMENT_P_H
#define QTEXTDOCUMENT_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/qstring.h"
#include "QtCore/qvector.h"
#include "QtCore/qlist.h"
#include "private/qobject_p.h"
#include "private/qfragmentmap_p.h"
#include "private/qtextlayout.h"
#include "QtGui/qtextoption.h"
#include "private/qtextformat_p.h"
#include "QtGui/qtextdocument.h"
#include "QtGui/qtextobject.h"
#include "QtGui/qtextcursor.h"
#include "QtCore/qmap.h"
#include "QtCore/qvariant.h"
#include "QtCore/qurl.h"
#include "private/qcssparser_p.h"
// #define QT_QMAP_DEBUG
#ifdef QT_QMAP_DEBUG
#include <iostream>
#endif
QT_BEGIN_NAMESPACE
class QTextFormatCollection;
class QTextFormat;
class QTextBlockFormat;
class QTextCursorPrivate;
class QAbstractTextDocumentLayout;
class QTextDocument;
class QTextFrame;
#define QTextBeginningOfFrame QChar(0xfdd0)
#define QTextEndOfFrame QChar(0xfdd1)
class QTextFragmentData : public QFragment<>
{
public:
inline void initialize() {}
inline void invalidate() const {}
inline void free() {}
int stringPosition;
int format;
};
class QTextBlockData : public QFragment<3>
{
public:
inline void initialize()
{ layout = 0; userData = 0; userState = -1; revision = 0; hidden = 0; }
void invalidate() const;
inline void free()
{ delete layout; layout = 0; delete userData; userData = 0; }
mutable int format;
// ##### probably store a QTextEngine * here!
mutable QTextLayout *layout;
mutable QTextBlockUserData *userData;
mutable int userState;
mutable int revision : 31;
mutable uint hidden : 1;
};
class QAbstractUndoItem;
class QTextUndoCommand
{
public:
enum Command {
Inserted = 0,
Removed = 1,
CharFormatChanged = 2,
BlockFormatChanged = 3,
BlockInserted = 4,
BlockRemoved = 5,
BlockAdded = 6,
BlockDeleted = 7,
GroupFormatChange = 8,
CursorMoved = 9,
Custom = 256
};
enum Operation {
KeepCursor = 0,
MoveCursor = 1
};
quint16 command;
uint block_part : 1; // all commands that are part of an undo block (including the first and the last one) have this set to 1
uint block_end : 1; // the last command in an undo block has this set to 1.
uint block_padding : 6; // padding since block used to be a quint8
quint8 operation;
int format;
quint32 strPos;
quint32 pos;
union {
int blockFormat;
quint32 length;
QAbstractUndoItem *custom;
int objectIndex;
};
quint32 revision;
bool tryMerge(const QTextUndoCommand &other);
};
Q_DECLARE_TYPEINFO(QTextUndoCommand, Q_PRIMITIVE_TYPE);
class Q_AUTOTEST_EXPORT QTextDocumentPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTextDocument)
public:
typedef QFragmentMap<QTextFragmentData> FragmentMap;
typedef FragmentMap::ConstIterator FragmentIterator;
typedef QFragmentMap<QTextBlockData> BlockMap;
QTextDocumentPrivate();
~QTextDocumentPrivate();
void init();
void clear();
void setLayout(QAbstractTextDocumentLayout *layout);
void insert(int pos, const QString &text, int format);
void insert(int pos, int strPos, int strLength, int format);
int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
int insertBlock(QChar blockSeparator, int pos, int blockFormat, int charFormat,
QTextUndoCommand::Operation op = QTextUndoCommand::MoveCursor);
void move(int from, int to, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
void remove(int pos, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
void aboutToRemoveCell(int cursorFrom, int cursorEnd);
QTextFrame *insertFrame(int start, int end, const QTextFrameFormat &format);
void removeFrame(QTextFrame *frame);
enum FormatChangeMode { MergeFormat, SetFormat, SetFormatAndPreserveObjectIndices };
void setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode = SetFormat);
void setBlockFormat(const QTextBlock &from, const QTextBlock &to,
const QTextBlockFormat &newFormat, FormatChangeMode mode = SetFormat);
void emitUndoAvailable(bool available);
void emitRedoAvailable(bool available);
int undoRedo(bool undo);
inline void undo() { undoRedo(true); }
inline void redo() { undoRedo(false); }
void appendUndoItem(QAbstractUndoItem *);
inline void beginEditBlock() { if (0 == editBlock++) ++revision; }
void joinPreviousEditBlock();
void endEditBlock();
void finishEdit();
inline bool isInEditBlock() const { return editBlock; }
void enableUndoRedo(bool enable);
inline bool isUndoRedoEnabled() const { return undoEnabled; }
inline bool isUndoAvailable() const { return undoEnabled && undoState > 0; }
inline bool isRedoAvailable() const { return undoEnabled && undoState < undoStack.size(); }
inline int availableUndoSteps() const { return undoEnabled ? undoState : 0; }
inline int availableRedoSteps() const { return undoEnabled ? qMax(undoStack.size() - undoState - 1, 0) : 0; }
inline QString buffer() const { return text; }
QString plainText() const;
inline int length() const { return fragments.length(); }
inline QTextFormatCollection *formatCollection() { return &formats; }
inline const QTextFormatCollection *formatCollection() const { return &formats; }
inline QAbstractTextDocumentLayout *layout() const { return lout; }
inline FragmentIterator find(int pos) const { return fragments.find(pos); }
inline FragmentIterator begin() const { return fragments.begin(); }
inline FragmentIterator end() const { return fragments.end(); }
inline QTextBlock blocksBegin() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.firstNode()); }
inline QTextBlock blocksEnd() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), 0); }
inline QTextBlock blocksFind(int pos) const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.findNode(pos)); }
int blockCharFormatIndex(int node) const;
inline int numBlocks() const { return blocks.numNodes(); }
const BlockMap &blockMap() const { return blocks; }
const FragmentMap &fragmentMap() const { return fragments; }
BlockMap &blockMap() { return blocks; }
FragmentMap &fragmentMap() { return fragments; }
static const QTextBlockData *block(const QTextBlock &it) { return it.p->blocks.fragment(it.n); }
int nextCursorPosition(int position, QTextLayout::CursorMode mode) const;
int previousCursorPosition(int position, QTextLayout::CursorMode mode) const;
int leftCursorPosition(int position) const;
int rightCursorPosition(int position) const;
void changeObjectFormat(QTextObject *group, int format);
void setModified(bool m);
inline bool isModified() const { return modified; }
inline QFont defaultFont() const { return formats.defaultFont(); }
inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
void clearUndoRedoStacks(QTextDocument::Stacks stacksToClear, bool emitSignals = false);
private:
bool split(int pos);
bool unite(uint f);
void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
int remove_string(int pos, uint length, QTextUndoCommand::Operation op);
int remove_block(int pos, int *blockformat, int command, QTextUndoCommand::Operation op);
void insert_frame(QTextFrame *f);
void scan_frames(int pos, int charsRemoved, int charsAdded);
static void clearFrame(QTextFrame *f);
void adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op);
bool wasUndoAvailable;
bool wasRedoAvailable;
public:
void documentChange(int from, int length);
inline void addCursor(QTextCursorPrivate *c) { cursors.append(c); }
inline void removeCursor(QTextCursorPrivate *c) { cursors.removeAll(c); }
QTextFrame *frameAt(int pos) const;
QTextFrame *rootFrame() const;
QTextObject *objectForIndex(int objectIndex) const;
QTextObject *objectForFormat(int formatIndex) const;
QTextObject *objectForFormat(const QTextFormat &f) const;
QTextObject *createObject(const QTextFormat &newFormat, int objectIndex = -1);
void deleteObject(QTextObject *object);
QTextDocument *document() { return q_func(); }
const QTextDocument *document() const { return q_func(); }
bool ensureMaximumBlockCount();
private:
QTextDocumentPrivate(const QTextDocumentPrivate& m);
QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
void appendUndoItem(const QTextUndoCommand &c);
void contentsChanged();
void compressPieceTable();
QString text;
uint unreachableCharacterCount;
QVector<QTextUndoCommand> undoStack;
bool undoEnabled;
int undoState;
int revision;
// position in undo stack of the last setModified(false) call
int modifiedState;
bool modified;
int editBlock;
int editBlockCursorPosition;
int docChangeFrom;
int docChangeOldLength;
int docChangeLength;
bool framesDirty;
QTextFormatCollection formats;
mutable QTextFrame *rtFrame;
QAbstractTextDocumentLayout *lout;
FragmentMap fragments;
BlockMap blocks;
int initialBlockCharFormatIndex;
QList<QTextCursorPrivate *> cursors;
QMap<int, QTextObject *> objects;
QMap<QUrl, QVariant> resources;
QMap<QUrl, QVariant> cachedResources;
QString defaultStyleSheet;
int lastBlockCount;
public:
QTextOption defaultTextOption;
Qt::CursorMoveStyle defaultCursorMoveStyle;
#ifndef QT_NO_CSSPARSER
QCss::StyleSheet parsedDefaultStyleSheet;
#endif
int maximumBlockCount;
uint needsEnsureMaximumBlockCount : 1;
uint inContentsChange : 1;
uint blockCursorAdjustment : 1;
QSizeF pageSize;
QString title;
QString url;
qreal indentWidth;
qreal documentMargin;
QUrl baseUrl;
void mergeCachedResources(const QTextDocumentPrivate *priv);
friend class QTextHtmlExporter;
friend class QTextCursor;
};
class QTextTable;
class QTextHtmlExporter
{
public:
QTextHtmlExporter(const QTextDocument *_doc);
enum ExportMode {
ExportEntireDocument,
ExportFragment
};
QString toHtml(const QByteArray &encoding, ExportMode mode = ExportEntireDocument);
private:
enum StyleMode { EmitStyleTag, OmitStyleTag };
enum FrameType { TextFrame, TableFrame, RootFrame };
void emitFrame(QTextFrame::Iterator frameIt);
void emitTextFrame(const QTextFrame *frame);
void emitBlock(const QTextBlock &block);
void emitTable(const QTextTable *table);
void emitFragment(const QTextFragment &fragment);
void emitBlockAttributes(const QTextBlock &block);
bool emitCharFormatStyle(const QTextCharFormat &format);
void emitTextLength(const char *attribute, const QTextLength &length);
void emitAlignment(Qt::Alignment alignment);
void emitFloatStyle(QTextFrameFormat::Position pos, StyleMode mode = EmitStyleTag);
void emitMargins(const QString &top, const QString &bottom, const QString &left, const QString &right);
void emitAttribute(const char *attribute, const QString &value);
void emitFrameStyle(const QTextFrameFormat &format, FrameType frameType);
void emitBorderStyle(QTextFrameFormat::BorderStyle style);
void emitPageBreakPolicy(QTextFormat::PageBreakFlags policy);
void emitFontFamily(const QString &family);
void emitBackgroundAttribute(const QTextFormat &format);
QString findUrlForImage(const QTextDocument *doc, qint64 cacheKey, bool isPixmap);
QString html;
QTextCharFormat defaultCharFormat;
const QTextDocument *doc;
bool fragmentMarkers;
};
QT_END_NAMESPACE
#endif // QTEXTDOCUMENT_P_H

View File

@ -0,0 +1,721 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTENGINE_P_H
#define QTEXTENGINE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtCore/qglobal.h"
#include "QtCore/qstring.h"
#include "QtCore/qvarlengtharray.h"
#include "QtCore/qnamespace.h"
#include "private/qtextlayout.h"
#include "private/qtextformat_p.h"
#include "private/qfont_p.h"
#include "QtCore/qvector.h"
#include "QtGui/qpaintengine.h"
#include "QtGui/qtextobject.h"
#include "QtGui/qtextoption.h"
#include "QtGui/qtextcursor.h"
#include "QtCore/qset.h"
#include "QtCore/qdebug.h"
#ifndef QT_BUILD_COMPAT_LIB
#include "private/qtextdocument_p.h"
#endif
#include "private/qfixed_p.h"
#include <private/qunicodetools_p.h>
#include <stdlib.h>
QT_BEGIN_NAMESPACE
class QFontPrivate;
class QFontEngine;
class QString;
class QPainter;
class QAbstractTextDocumentLayout;
typedef quint32 glyph_t;
// this uses the same coordinate system as Qt, but a different one to freetype.
// * y is usually negative, and is equal to the ascent.
// * negative yoff means the following stuff is drawn higher up.
// the characters bounding rect is given by QRect(x,y,width,height), its advance by
// xoo and yoff
struct Q_GUI_EXPORT glyph_metrics_t
{
inline glyph_metrics_t()
: x(100000), y(100000) {}
inline glyph_metrics_t(QFixed _x, QFixed _y, QFixed _width, QFixed _height, QFixed _xoff, QFixed _yoff)
: x(_x),
y(_y),
width(_width),
height(_height),
xoff(_xoff),
yoff(_yoff)
{}
QFixed x;
QFixed y;
QFixed width;
QFixed height;
QFixed xoff;
QFixed yoff;
glyph_metrics_t transformed(const QTransform &xform) const;
inline bool isValid() const {return x != 100000 && y != 100000;}
inline QFixed leftBearing() const
{
if (!isValid())
return QFixed();
return x;
}
inline QFixed rightBearing() const
{
if (!isValid())
return QFixed();
return xoff - x - width;
}
};
Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE);
struct Q_AUTOTEST_EXPORT QScriptAnalysis
{
enum Flags {
None = 0,
Lowercase = 1,
Uppercase = 2,
SmallCaps = 3,
LineOrParagraphSeparator = 4,
Space = 5,
SpaceTabOrObject = Space,
Tab = 6,
TabOrObject = Tab,
Object = 7
};
unsigned short script : 7;
unsigned short bidiLevel : 6; // Unicode Bidi algorithm embedding level (0-61)
unsigned short flags : 3;
inline bool operator == (const QScriptAnalysis &other) const {
return script == other.script && bidiLevel == other.bidiLevel && flags == other.flags;
}
};
Q_DECLARE_TYPEINFO(QScriptAnalysis, Q_PRIMITIVE_TYPE);
struct QGlyphJustification
{
inline QGlyphJustification()
: type(0), nKashidas(0), space_18d6(0)
{}
enum JustificationType {
JustifyNone,
JustifySpace,
JustifyKashida
};
uint type :2;
uint nKashidas : 6; // more do not make sense...
uint space_18d6 : 24;
};
Q_DECLARE_TYPEINFO(QGlyphJustification, Q_PRIMITIVE_TYPE);
struct QGlyphAttributes {
uchar clusterStart : 1;
uchar dontPrint : 1;
uchar justification : 4;
uchar reserved : 2;
};
Q_STATIC_ASSERT(sizeof(QGlyphAttributes) == 1);
Q_DECLARE_TYPEINFO(QGlyphAttributes, Q_PRIMITIVE_TYPE);
struct QGlyphLayout
{
enum {
SpaceNeeded = sizeof(glyph_t) + sizeof(QFixed) + sizeof(QFixedPoint)
+ sizeof(QGlyphAttributes) + sizeof(QGlyphJustification)
};
// init to 0 not needed, done when shaping
QFixedPoint *offsets; // 8 bytes per element
glyph_t *glyphs; // 4 bytes per element
QFixed *advances; // 4 bytes per element
QGlyphJustification *justifications; // 4 bytes per element
QGlyphAttributes *attributes; // 1 byte per element
int numGlyphs;
inline QGlyphLayout() : numGlyphs(0) {}
inline explicit QGlyphLayout(char *address, int totalGlyphs)
{
offsets = reinterpret_cast<QFixedPoint *>(address);
int offset = totalGlyphs * sizeof(QFixedPoint);
glyphs = reinterpret_cast<glyph_t *>(address + offset);
offset += totalGlyphs * sizeof(glyph_t);
advances = reinterpret_cast<QFixed *>(address + offset);
offset += totalGlyphs * sizeof(QFixed);
justifications = reinterpret_cast<QGlyphJustification *>(address + offset);
offset += totalGlyphs * sizeof(QGlyphJustification);
attributes = reinterpret_cast<QGlyphAttributes *>(address + offset);
numGlyphs = totalGlyphs;
}
inline QGlyphLayout mid(int position, int n = -1) const {
QGlyphLayout copy = *this;
copy.glyphs += position;
copy.advances += position;
copy.offsets += position;
copy.justifications += position;
copy.attributes += position;
if (n == -1)
copy.numGlyphs -= position;
else
copy.numGlyphs = n;
return copy;
}
inline QFixed effectiveAdvance(int item) const
{ return (advances[item] + QFixed::fromFixed(justifications[item].space_18d6)) * !attributes[item].dontPrint; }
inline void clear(int first = 0, int last = -1) {
if (last == -1)
last = numGlyphs;
if (first == 0 && last == numGlyphs
&& reinterpret_cast<char *>(offsets + numGlyphs) == reinterpret_cast<char *>(glyphs)) {
memset(offsets, 0, (numGlyphs * SpaceNeeded));
} else {
const int num = last - first;
memset(offsets + first, 0, num * sizeof(QFixedPoint));
memset(glyphs + first, 0, num * sizeof(glyph_t));
memset(advances + first, 0, num * sizeof(QFixed));
memset(justifications + first, 0, num * sizeof(QGlyphJustification));
memset(attributes + first, 0, num * sizeof(QGlyphAttributes));
}
}
inline char *data() {
return reinterpret_cast<char *>(offsets);
}
void grow(char *address, int totalGlyphs);
};
class QVarLengthGlyphLayoutArray : private QVarLengthArray<void *>, public QGlyphLayout
{
private:
typedef QVarLengthArray<void *> Array;
public:
QVarLengthGlyphLayoutArray(int totalGlyphs)
: Array((totalGlyphs * SpaceNeeded) / sizeof(void *) + 1)
, QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs)
{
memset(Array::data(), 0, Array::size() * sizeof(void *));
}
void resize(int totalGlyphs)
{
Array::resize((totalGlyphs * SpaceNeeded) / sizeof(void *) + 1);
*((QGlyphLayout *)this) = QGlyphLayout(reinterpret_cast<char *>(Array::data()), totalGlyphs);
memset(Array::data(), 0, Array::size() * sizeof(void *));
}
};
template <int N> struct QGlyphLayoutArray : public QGlyphLayout
{
public:
QGlyphLayoutArray()
: QGlyphLayout(reinterpret_cast<char *>(buffer), N)
{
memset(buffer, 0, sizeof(buffer));
}
private:
void *buffer[(N * SpaceNeeded) / sizeof(void *) + 1];
};
struct QScriptItem;
/// Internal QTextItem
class QTextItemInt : public QTextItem
{
public:
inline QTextItemInt()
: justified(false), underlineStyle(QTextCharFormat::NoUnderline), num_chars(0), chars(0),
logClusters(0), f(0), fontEngine(0)
{}
QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
QTextItemInt(const QGlyphLayout &g, QFont *font, const QChar *chars, int numChars, QFontEngine *fe,
const QTextCharFormat &format = QTextCharFormat());
/// copy the structure items, adjusting the glyphs arrays to the right subarrays.
/// the width of the returned QTextItemInt is not adjusted, for speed reasons
QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const;
void initWithScriptItem(const QScriptItem &si);
QFixed descent;
QFixed ascent;
QFixed width;
RenderFlags flags;
bool justified;
QTextCharFormat::UnderlineStyle underlineStyle;
const QTextCharFormat charFormat;
int num_chars;
const QChar *chars;
const unsigned short *logClusters;
const QFont *f;
QGlyphLayout glyphs;
QFontEngine *fontEngine;
};
struct Q_AUTOTEST_EXPORT QScriptItem
{
inline QScriptItem()
: position(0),
num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
inline QScriptItem(int p, const QScriptAnalysis &a)
: position(p), analysis(a),
num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
int position;
QScriptAnalysis analysis;
unsigned short num_glyphs;
QFixed descent;
QFixed ascent;
QFixed leading;
QFixed width;
int glyph_data_offset;
QFixed height() const { return ascent + descent; }
};
Q_DECLARE_TYPEINFO(QScriptItem, Q_MOVABLE_TYPE);
typedef QVector<QScriptItem> QScriptItemArray;
struct Q_AUTOTEST_EXPORT QScriptLine
{
// created and filled in QTextLine::layout_helper
QScriptLine()
: from(0), trailingSpaces(0), length(0),
justified(0), gridfitted(0),
hasTrailingSpaces(0), leadingIncluded(0) {}
QFixed descent;
QFixed ascent;
QFixed leading;
QFixed x;
QFixed y;
QFixed width;
QFixed textWidth;
QFixed textAdvance;
int from;
unsigned short trailingSpaces;
signed int length : 28;
mutable uint justified : 1;
mutable uint gridfitted : 1;
uint hasTrailingSpaces : 1;
uint leadingIncluded : 1;
QFixed height() const { return ascent + descent
+ (leadingIncluded? qMax(QFixed(),leading) : QFixed()); }
QFixed base() const { return ascent; }
void setDefaultHeight(QTextEngine *eng);
void operator+=(const QScriptLine &other);
};
Q_DECLARE_TYPEINFO(QScriptLine, Q_PRIMITIVE_TYPE);
inline void QScriptLine::operator+=(const QScriptLine &other)
{
leading= qMax(leading + ascent, other.leading + other.ascent) - qMax(ascent, other.ascent);
descent = qMax(descent, other.descent);
ascent = qMax(ascent, other.ascent);
textWidth += other.textWidth;
length += other.length;
}
typedef QVector<QScriptLine> QScriptLineArray;
class QFontPrivate;
class QTextFormatCollection;
class Q_GUI_EXPORT QTextEngine {
public:
enum LayoutState {
LayoutEmpty,
InLayout,
LayoutFailed
};
struct Q_GUI_EXPORT LayoutData {
LayoutData(const QString &str, void **stack_memory, int mem_size);
LayoutData();
~LayoutData();
mutable QScriptItemArray items;
int allocated;
int available_glyphs;
void **memory;
unsigned short *logClustersPtr;
QGlyphLayout glyphLayout;
mutable int used;
uint hasBidi : 1;
uint layoutState : 2;
uint memory_on_stack : 1;
uint haveCharAttributes : 1;
QString string;
bool reallocate(int totalGlyphs);
};
struct ItemDecoration {
ItemDecoration() {} // for QVector, don't use
ItemDecoration(qreal x1, qreal x2, qreal y, const QPen &pen):
x1(x1), x2(x2), y(y), pen(pen) {}
qreal x1;
qreal x2;
qreal y;
QPen pen;
};
typedef QVector<ItemDecoration> ItemDecorationList;
QTextEngine();
QTextEngine(const QString &str, const QFont &f);
~QTextEngine();
enum Mode {
WidthOnly = 0x07
};
void invalidate();
void clearLineData();
void validate() const;
void itemize() const;
bool isRightToLeft() const;
static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder);
const QCharAttributes *attributes() const;
void shape(int item) const;
void justify(const QScriptLine &si);
QFixed alignLine(const QScriptLine &line);
QFixed width(int charFrom, int numChars) const;
glyph_metrics_t boundingBox(int from, int len) const;
glyph_metrics_t tightBoundingBox(int from, int len) const;
int length(int item) const {
const QScriptItem &si = layoutData->items[item];
int from = si.position;
item++;
return (item < layoutData->items.size() ? layoutData->items[item].position : layoutData->string.length()) - from;
}
int length(const QScriptItem *si) const {
int end;
if (si + 1 < layoutData->items.constData()+ layoutData->items.size())
end = (si+1)->position;
else
end = layoutData->string.length();
return end - si->position;
}
QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0, QFixed *leading = 0) const;
QFont font(const QScriptItem &si) const;
inline QFont font() const { return fnt; }
/**
* Returns a pointer to an array of log clusters, offset at the script item.
* Each item in the array is a unsigned short. For each character in the original string there is an entry in the table
* so there is a one to one correlation in indexes between the original text and the index in the logcluster.
* The value of each item is the position in the glyphs array. Multiple similar pointers in the logclusters array imply
* that one glyph is used for more than one character.
* \sa glyphs()
*/
inline unsigned short *logClusters(const QScriptItem *si) const
{ return layoutData->logClustersPtr+si->position; }
/**
* Returns an array of QGlyphLayout items, offset at the script item.
* Each item in the array matches one glyph in the text, storing the advance, position etc.
* The returned item's length equals to the number of available glyphs. This may be more
* than what was actually shaped.
* \sa logClusters()
*/
inline QGlyphLayout availableGlyphs(const QScriptItem *si) const {
return layoutData->glyphLayout.mid(si->glyph_data_offset);
}
/**
* Returns an array of QGlyphLayout items, offset at the script item.
* Each item in the array matches one glyph in the text, storing the advance, position etc.
* The returned item's length equals to the number of shaped glyphs.
* \sa logClusters()
*/
inline QGlyphLayout shapedGlyphs(const QScriptItem *si) const {
return layoutData->glyphLayout.mid(si->glyph_data_offset, si->num_glyphs);
}
inline bool ensureSpace(int nGlyphs) const {
if (layoutData->glyphLayout.numGlyphs - layoutData->used < nGlyphs)
return layoutData->reallocate((((layoutData->used + nGlyphs)*3/2 + 15) >> 4) << 4);
return true;
}
void freeMemory();
int findItem(int strPos, int firstItem = 0) const;
inline QTextFormatCollection *formatCollection() const {
if (block.docHandle())
return block.docHandle()->formatCollection();
return specialData ? specialData->formatCollection.data() : 0;
}
QTextCharFormat format(const QScriptItem *si) const;
inline QAbstractTextDocumentLayout *docLayout() const {
Q_ASSERT(block.docHandle());
return block.docHandle()->document()->documentLayout();
}
int formatIndex(const QScriptItem *si) const;
/// returns the width of tab at index (in the tabs array) with the tab-start at position x
QFixed calculateTabWidth(int index, QFixed x) const;
mutable QScriptLineArray lines;
private:
struct FontEngineCache {
FontEngineCache();
mutable QFontEngine *prevFontEngine;
mutable QFontEngine *prevScaledFontEngine;
mutable int prevScript;
mutable int prevPosition;
mutable int prevLength;
inline void reset() {
prevFontEngine = 0;
prevScaledFontEngine = 0;
prevScript = -1;
prevPosition = -1;
prevLength = -1;
}
};
mutable FontEngineCache feCache;
public:
QString text;
mutable QFont fnt;
#ifndef QT_NO_RAWFONT
QRawFont rawFont;
#endif
QTextBlock block;
QTextOption option;
QFixed minWidth;
QFixed maxWidth;
QPointF position;
uint ignoreBidi : 1;
uint cacheGlyphs : 1;
uint stackEngine : 1;
uint forceJustification : 1;
uint visualMovement : 1;
uint delayDecorations: 1;
#ifndef QT_NO_RAWFONT
uint useRawFont : 1;
#endif
mutable LayoutData *layoutData;
ItemDecorationList underlineList;
ItemDecorationList strikeOutList;
ItemDecorationList overlineList;
inline bool visualCursorMovement() const
{ return visualMovement || (block.docHandle() && block.docHandle()->defaultCursorMoveStyle == Qt::VisualMoveStyle); }
inline int preeditAreaPosition() const { return specialData ? specialData->preeditPosition : -1; }
inline QString preeditAreaText() const { return specialData ? specialData->preeditText : QString(); }
void setPreeditArea(int position, const QString &text);
inline bool hasFormats() const
{ return block.docHandle() || (specialData && !specialData->formats.isEmpty()); }
inline QVector<QTextLayout::FormatRange> formats() const
{ return specialData ? specialData->formats : QVector<QTextLayout::FormatRange>(); }
void setFormats(const QVector<QTextLayout::FormatRange> &formats);
private:
static void init(QTextEngine *e);
struct SpecialData {
int preeditPosition;
QString preeditText;
QVector<QTextLayout::FormatRange> formats;
QVector<QTextCharFormat> resolvedFormats;
// only used when no docHandle is available
QScopedPointer<QTextFormatCollection> formatCollection;
};
SpecialData *specialData;
void indexFormats();
void resolveFormats() const;
public:
bool atWordSeparator(int position) const;
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0, int from = 0, int count = -1) const;
void shapeLine(const QScriptLine &line);
QFixed leadingSpaceWidth(const QScriptLine &line);
QFixed offsetInLigature(const QScriptItem *si, int pos, int max, int glyph_pos);
int positionInLigature(const QScriptItem *si, int end, QFixed x, QFixed edge, int glyph_pos, bool cursorOnCharacter);
int previousLogicalPosition(int oldPos) const;
int nextLogicalPosition(int oldPos) const;
int lineNumberForTextPosition(int pos);
int positionAfterVisualMovement(int oldPos, QTextCursor::MoveOperation op);
void insertionPointsForLine(int lineNum, QVector<int> &insertionPoints);
void resetFontEngineCache();
void enableDelayDecorations(bool enable = true) { delayDecorations = enable; }
void addUnderline(QPainter *painter, const QLineF &line);
void addStrikeOut(QPainter *painter, const QLineF &line);
void addOverline(QPainter *painter, const QLineF &line);
void drawDecorations(QPainter *painter);
void clearDecorations();
void adjustUnderlines();
private:
void addItemDecoration(QPainter *painter, const QLineF &line, ItemDecorationList *decorationList);
void adjustUnderlines(ItemDecorationList::iterator start,
ItemDecorationList::iterator end,
qreal underlinePos, qreal penWidth);
void drawItemDecorationList(QPainter *painter, const ItemDecorationList &decorationList);
void setBoundary(int strPos) const;
void addRequiredBoundaries() const;
void shapeText(int item) const;
#ifdef QT_ENABLE_HARFBUZZ_NG
int shapeTextWithHarfbuzzNG(const QScriptItem &si,
const ushort *string,
int itemLength,
QFontEngine *fontEngine,
const QVector<uint> &itemBoundaries,
bool kerningEnabled,
bool hasLetterSpacing) const;
#endif
int shapeTextWithHarfbuzz(const QScriptItem &si, const ushort *string, int itemLength, QFontEngine *fontEngine, const QVector<uint> &itemBoundaries, bool kerningEnabled) const;
int endOfLine(int lineNum);
int beginningOfLine(int lineNum);
int getClusterLength(unsigned short *logClusters, const QCharAttributes *attributes, int from, int to, int glyph_pos, int *start);
};
class Q_GUI_EXPORT QStackTextEngine : public QTextEngine {
public:
enum { MemSize = 256*40/sizeof(void *) };
QStackTextEngine(const QString &string, const QFont &f);
LayoutData _layoutData;
void *_memory[MemSize];
};
Q_DECLARE_TYPEINFO(QTextEngine::ItemDecoration, Q_MOVABLE_TYPE);
struct QTextLineItemIterator
{
QTextLineItemIterator(QTextEngine *eng, int lineNum, const QPointF &pos = QPointF(),
const QTextLayout::FormatRange *_selection = 0);
inline bool atEnd() const { return logicalItem >= nItems - 1; }
inline bool atBeginning() const { return logicalItem <= 0; }
QScriptItem &next();
bool getSelectionBounds(QFixed *selectionX, QFixed *selectionWidth) const;
inline bool isOutsideSelection() const {
QFixed tmp1, tmp2;
return !getSelectionBounds(&tmp1, &tmp2);
}
QTextEngine *eng;
QFixed x;
const QScriptLine &line;
QScriptItem *si;
const int lineNum;
const int lineEnd;
const int firstItem;
const int lastItem;
const int nItems;
int logicalItem;
int item;
int itemLength;
int glyphsStart;
int glyphsEnd;
int itemStart;
int itemEnd;
QFixed itemWidth;
QVarLengthArray<int> visualOrder;
const QTextLayout::FormatRange *selection;
};
QT_END_NAMESPACE
#endif // QTEXTENGINE_P_H

View File

@ -0,0 +1,110 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTFORMAT_P_H
#define QTEXTFORMAT_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 "QtGui/qtextformat.h"
#include "QtCore/qvector.h"
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QTextFormatCollection
{
public:
QTextFormatCollection() {}
~QTextFormatCollection();
QTextFormatCollection(const QTextFormatCollection &rhs);
QTextFormatCollection &operator=(const QTextFormatCollection &rhs);
inline QTextFormat objectFormat(int objectIndex) const
{ return format(objectFormatIndex(objectIndex)); }
inline void setObjectFormat(int objectIndex, const QTextFormat &format)
{ setObjectFormatIndex(objectIndex, indexForFormat(format)); }
int objectFormatIndex(int objectIndex) const;
void setObjectFormatIndex(int objectIndex, int formatIndex);
int createObjectIndex(const QTextFormat &f);
int indexForFormat(const QTextFormat &f);
bool hasFormatCached(const QTextFormat &format) const;
QTextFormat format(int idx) const;
inline QTextBlockFormat blockFormat(int index) const
{ return format(index).toBlockFormat(); }
inline QTextCharFormat charFormat(int index) const
{ return format(index).toCharFormat(); }
inline QTextListFormat listFormat(int index) const
{ return format(index).toListFormat(); }
inline QTextTableFormat tableFormat(int index) const
{ return format(index).toTableFormat(); }
inline QTextImageFormat imageFormat(int index) const
{ return format(index).toImageFormat(); }
inline int numFormats() const { return formats.count(); }
typedef QVector<QTextFormat> FormatVector;
FormatVector formats;
QVector<qint32> objFormats;
QMultiHash<uint,int> hashes;
inline QFont defaultFont() const { return defaultFnt; }
void setDefaultFont(const QFont &f);
private:
QFont defaultFnt;
};
QT_END_NAMESPACE
#endif // QTEXTFORMAT_P_H

View File

@ -0,0 +1,275 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTLAYOUT_H
#define QTEXTLAYOUT_H
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qrect.h>
#include <QtCore/qvector.h>
#include <QtGui/qcolor.h>
#include <QtCore/qobject.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
#include <QtGui/qglyphrun.h>
#include <QtGui/qtextcursor.h>
QT_BEGIN_NAMESPACE
class QTextEngine;
class QFont;
#ifndef QT_NO_RAWFONT
class QRawFont;
#endif
class QRect;
class QRegion;
class QTextFormat;
class QPalette;
class QPainter;
class Q_GUI_EXPORT QTextInlineObject
{
public:
QTextInlineObject(int i, QTextEngine *e) : itm(i), eng(e) {}
inline QTextInlineObject() : itm(0), eng(Q_NULLPTR) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
qreal width() const;
qreal ascent() const;
qreal descent() const;
qreal height() const;
Qt::LayoutDirection textDirection() const;
void setWidth(qreal w);
void setAscent(qreal a);
void setDescent(qreal d);
int textPosition() const;
int formatIndex() const;
QTextFormat format() const;
private:
friend class QTextLayout;
int itm;
QTextEngine *eng;
};
class QPaintDevice;
class QTextFormat;
class QTextLine;
class QTextBlock;
class QTextOption;
class Q_GUI_EXPORT QTextLayout
{
public:
// does itemization
QTextLayout();
QTextLayout(const QString& text);
QTextLayout(const QString& text, const QFont &font, QPaintDevice *paintdevice = Q_NULLPTR);
QTextLayout(const QTextBlock &b);
~QTextLayout();
void setFont(const QFont &f);
QFont font() const;
#ifndef QT_NO_RAWFONT
void setRawFont(const QRawFont &rawFont);
#endif
void setText(const QString& string);
QString text() const;
void setTextOption(const QTextOption &option);
const QTextOption &textOption() const;
void setPreeditArea(int position, const QString &text);
int preeditAreaPosition() const;
QString preeditAreaText() const;
struct FormatRange {
int start;
int length;
QTextCharFormat format;
friend bool operator==(const FormatRange &lhs, const FormatRange &rhs)
{ return lhs.start == rhs.start && lhs.length == rhs.length && lhs.format == rhs.format; }
friend bool operator!=(const FormatRange &lhs, const FormatRange &rhs)
{ return !operator==(lhs, rhs); }
};
#if QT_DEPRECATED_SINCE(5, 6)
QT_DEPRECATED_X("Use setFormats()") void setAdditionalFormats(const QList<FormatRange> &overrides);
QT_DEPRECATED_X("Use formats()") QList<FormatRange> additionalFormats() const;
QT_DEPRECATED_X("Use clearFormats()") void clearAdditionalFormats();
#endif
void setFormats(const QVector<FormatRange> &overrides);
QVector<FormatRange> formats() const;
void clearFormats();
void setCacheEnabled(bool enable);
bool cacheEnabled() const;
void setCursorMoveStyle(Qt::CursorMoveStyle style);
Qt::CursorMoveStyle cursorMoveStyle() const;
void beginLayout();
void endLayout();
void clearLayout();
QTextLine createLine();
int lineCount() const;
QTextLine lineAt(int i) const;
QTextLine lineForTextPosition(int pos) const;
enum CursorMode {
SkipCharacters,
SkipWords
};
bool isValidCursorPosition(int pos) const;
int nextCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
int previousCursorPosition(int oldPos, CursorMode mode = SkipCharacters) const;
int leftCursorPosition(int oldPos) const;
int rightCursorPosition(int oldPos) const;
void draw(QPainter *p, const QPointF &pos, const QVector<FormatRange> &selections = QVector<FormatRange>(),
const QRectF &clip = QRectF()) const;
void drawCursor(QPainter *p, const QPointF &pos, int cursorPosition) const;
void drawCursor(QPainter *p, const QPointF &pos, int cursorPosition, int width) const;
QPointF position() const;
void setPosition(const QPointF &p);
QRectF boundingRect() const;
qreal minimumWidth() const;
qreal maximumWidth() const;
#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
QTextEngine *engine() const { return d; }
void setFlags(int flags);
QTextLayout(QTextEngine *e) : d(e) {}
private:
Q_DISABLE_COPY(QTextLayout)
friend class QPainter;
friend class QGraphicsSimpleTextItemPrivate;
friend class QGraphicsSimpleTextItem;
friend void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *, const QString& str,
QRectF *brect, int tabstops, int* tabarray, int tabarraylen,
QPainter *painter);
QTextEngine *d;
};
Q_DECLARE_TYPEINFO(QTextLayout::FormatRange, Q_RELOCATABLE_TYPE);
class Q_GUI_EXPORT QTextLine
{
public:
inline QTextLine() : index(0), eng(Q_NULLPTR) {}
inline bool isValid() const { return eng; }
QRectF rect() const;
qreal x() const;
qreal y() const;
qreal width() const;
qreal ascent() const;
qreal descent() const;
qreal height() const;
qreal leading() const;
void setLeadingIncluded(bool included);
bool leadingIncluded() const;
qreal naturalTextWidth() const;
qreal horizontalAdvance() const;
QRectF naturalTextRect() const;
enum Edge {
Leading,
Trailing
};
enum CursorPosition {
CursorBetweenCharacters,
CursorOnCharacter
};
/* cursorPos gets set to the valid position */
qreal cursorToX(int *cursorPos, Edge edge = Leading) const;
inline qreal cursorToX(int cursorPos, Edge edge = Leading) const { return cursorToX(&cursorPos, edge); }
int xToCursor(qreal x, CursorPosition = CursorBetweenCharacters) const;
void setLineWidth(qreal width);
void setNumColumns(int columns);
void setNumColumns(int columns, qreal alignmentWidth);
void setPosition(const QPointF &pos);
QPointF position() const;
int textStart() const;
int textLength() const;
int lineNumber() const { return index; }
void draw(QPainter *p, const QPointF &point, const QTextLayout::FormatRange *selection = Q_NULLPTR) const;
#if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
#endif
private:
QTextLine(int line, QTextEngine *e) : index(line), eng(e) {}
void layout_helper(int numGlyphs);
friend class QTextLayout;
friend class QTextFragment;
int index;
QTextEngine *eng;
};
QT_END_NAMESPACE
#endif // QTEXTLAYOUT_H

View File

@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTOOLS_P_H
#define QTOOLS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "QtCore/qglobal.h"
#include <limits>
QT_BEGIN_NAMESPACE
namespace QtMiscUtils {
Q_DECL_CONSTEXPR inline char toHexUpper(uint value) Q_DECL_NOTHROW
{
return "0123456789ABCDEF"[value & 0xF];
}
Q_DECL_CONSTEXPR inline char toHexLower(uint value) Q_DECL_NOTHROW
{
return "0123456789abcdef"[value & 0xF];
}
Q_DECL_CONSTEXPR inline int fromHex(uint c) Q_DECL_NOTHROW
{
return ((c >= '0') && (c <= '9')) ? int(c - '0') :
((c >= 'A') && (c <= 'F')) ? int(c - 'A' + 10) :
((c >= 'a') && (c <= 'f')) ? int(c - 'a' + 10) :
/* otherwise */ -1;
}
Q_DECL_CONSTEXPR inline char toOct(uint value) Q_DECL_NOTHROW
{
return '0' + char(value & 0x7);
}
Q_DECL_CONSTEXPR inline int fromOct(uint c) Q_DECL_NOTHROW
{
return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1;
}
}
// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.
enum {
MaxAllocSize = (1 << (std::numeric_limits<int>::digits - 1)) - 1
};
// implemented in qbytearray.cpp
int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW;
QT_END_NAMESPACE
#endif // QTOOLS_P_H

View File

@ -0,0 +1,108 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QUNICODETOOLS_P_H
#define QUNICODETOOLS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qchar.h>
QT_BEGIN_NAMESPACE
struct QCharAttributes
{
uchar graphemeBoundary : 1;
uchar wordBreak : 1;
uchar sentenceBoundary : 1;
uchar lineBreak : 1;
uchar whiteSpace : 1;
uchar wordStart : 1;
uchar wordEnd : 1;
uchar mandatoryBreak : 1;
};
Q_DECLARE_TYPEINFO(QCharAttributes, Q_PRIMITIVE_TYPE);
namespace QUnicodeTools {
// ### temporary
struct ScriptItem
{
int position;
int script;
};
} // namespace QUnicodeTools
Q_DECLARE_TYPEINFO(QUnicodeTools::ScriptItem, Q_PRIMITIVE_TYPE);
namespace QUnicodeTools {
enum CharAttributeOption {
GraphemeBreaks = 0x01,
WordBreaks = 0x02,
SentenceBreaks = 0x04,
LineBreaks = 0x08,
WhiteSpaces = 0x10,
DefaultOptionsCompat = GraphemeBreaks | LineBreaks | WhiteSpaces, // ### remove
DontClearAttributes = 0x1000
};
Q_DECLARE_FLAGS(CharAttributeOptions, CharAttributeOption)
// attributes buffer has to have a length of string length + 1
Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
const ScriptItem *items, int numItems,
QCharAttributes *attributes, CharAttributeOptions options = DefaultOptionsCompat);
Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts);
} // namespace QUnicodeTools
QT_END_NAMESPACE
#endif // QUNICODETOOLS_P_H