mirror of https://github.com/procxx/kepka.git
[temp] add private Qt headers
This commit is contained in:
parent
60c77e0738
commit
9da39b0b56
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 █
|
||||
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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue