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