summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qevent.cpp144
-rw-r--r--src/gui/kernel/qevent.h77
-rw-r--r--src/gui/kernel/qevent_p.h25
-rw-r--r--src/gui/painting/qbrush.cpp14
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp25
-rw-r--r--src/gui/painting/qmatrix.cpp2
-rw-r--r--src/gui/painting/qoutlinemapper.cpp9
-rw-r--r--src/gui/painting/qoutlinemapper_p.h8
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp248
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h5
-rw-r--r--src/gui/painting/qpainter.cpp47
-rw-r--r--src/gui/painting/qpainterpath.cpp8
-rw-r--r--src/gui/painting/qpen.cpp6
-rw-r--r--src/gui/painting/qrasterizer.cpp4
-rw-r--r--src/gui/painting/qtransform.cpp4
-rw-r--r--src/gui/text/qfont.cpp5
-rw-r--r--src/gui/text/qfont_p.h2
-rw-r--r--src/gui/text/qfontdatabase.cpp42
-rw-r--r--src/gui/text/qfontenginedirectwrite.cpp146
-rw-r--r--src/gui/text/qfontenginedirectwrite_p.h6
-rw-r--r--src/gui/text/qglyphrun.cpp3
-rw-r--r--src/gui/text/qharfbuzz_copy_p.h7
-rw-r--r--src/gui/text/qplatformfontdatabase_qpa.cpp37
-rw-r--r--src/gui/text/qrawfont.cpp27
-rw-r--r--src/gui/text/qrawfont.h3
-rw-r--r--src/gui/text/qstatictext.cpp10
-rw-r--r--src/gui/text/qtextlayout.cpp210
27 files changed, 746 insertions, 378 deletions
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 9e6a8d6e52..fff27cd908 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -48,6 +48,7 @@
#include "qmime.h"
#include "private/qdnd_p.h"
#include "qevent_p.h"
+#include "qmath.h"
#ifdef Q_OS_SYMBIAN
#include "private/qcore_symbian_p.h"
@@ -161,7 +162,7 @@ QInputEvent::~QInputEvent()
position explicitly.
*/
-QMouseEvent::QMouseEvent(Type type, const QPoint &position, Qt::MouseButton button,
+QMouseEvent::QMouseEvent(Type type, const QPointF &position, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
: QInputEvent(type, modifiers), p(position), b(button), mouseState(buttons)
{
@@ -193,28 +194,20 @@ QMouseEvent::~QMouseEvent()
modifiers.
*/
-QMouseEvent::QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+QMouseEvent::QMouseEvent(Type type, const QPointF &pos, const QPointF &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers)
: QInputEvent(type, modifiers), p(pos), g(globalPos), b(button), mouseState(buttons)
{}
/*!
- \internal
-*/
-QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos,
- const QPoint &globalPos, Qt::MouseButton button,
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
-{
- return new QMouseEventEx(type, pos, globalPos, button, buttons, modifiers);
-}
-
-/*!
\fn bool QMouseEvent::hasExtendedInfo() const
\internal
*/
/*!
+ \fn QPointF QMouseEvent::posF() const
+
\since 4.4
Returns the position of the mouse cursor as a QPointF, relative to the
@@ -226,28 +219,6 @@ QMouseEvent *QMouseEvent::createExtendedMouseEvent(Type type, const QPointF &pos
\sa x() y() pos() globalPos()
*/
-QPointF QMouseEvent::posF() const
-{
- return hasExtendedInfo() ? reinterpret_cast<const QMouseEventEx *>(this)->posF : QPointF(pos());
-}
-
-/*!
- \internal
-*/
-QMouseEventEx::QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
- Qt::MouseButton button, Qt::MouseButtons buttons,
- Qt::KeyboardModifiers modifiers)
- : QMouseEvent(type, pos.toPoint(), globalPos, button, buttons, modifiers), posF(pos)
-{
- d = reinterpret_cast<QEventPrivate *>(this);
-}
-
-/*!
- \internal
-*/
-QMouseEventEx::~QMouseEventEx()
-{
-}
/*!
\fn const QPoint &QMouseEvent::pos() const
@@ -440,8 +411,8 @@ QMouseEventEx::~QMouseEventEx()
receiving widget, while \a oldPos is the previous mouse cursor's
position relative to the receiving widget.
*/
-QHoverEvent::QHoverEvent(Type type, const QPoint &pos, const QPoint &oldPos)
- : QEvent(type), p(pos), op(oldPos)
+QHoverEvent::QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos, Qt::KeyboardModifiers modifiers)
+ : QInputEvent(type, modifiers), p(pos), op(oldPos)
{
}
@@ -507,7 +478,7 @@ QHoverEvent::~QHoverEvent()
\sa pos() delta() state()
*/
#ifndef QT_NO_WHEELEVENT
-QWheelEvent::QWheelEvent(const QPoint &pos, int delta,
+QWheelEvent::QWheelEvent(const QPointF &pos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), d(delta), mouseState(buttons), o(orient)
@@ -533,7 +504,7 @@ QWheelEvent::~QWheelEvent()
\sa pos() globalPos() delta() state()
*/
-QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta,
+QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient)
: QInputEvent(Wheel, modifiers), p(pos), g(globalPos), d(delta), mouseState(buttons), o(orient)
@@ -4355,4 +4326,101 @@ const QScrollEventPrivate *QScrollEvent::d_func() const
return reinterpret_cast<const QScrollEventPrivate *>(d);
}
+/*!
+ \enum QScreenOrientationChangeEvent::Orientation
+
+ This enum describes the orientations that a device can have.
+
+ \value Portrait The device is in a position where its top edge is pointing up.
+
+ \value Landscape The device is rotated clockwise 90 degrees, so that its left edge is pointing up.
+
+ \value PortraitInverted The device is rotated 180 degrees, so that its bottom edge is pointing up.
+
+ \value LandscapeInverted The device is counterclockwise 90 degrees, so that its right edge is pointing up.
+
+ \sa QScreenOrientationChangeEvent::orientation()
+ \sa QScreenOrientationChangeEvent::orientationInDegrees()
+*/
+
+/*!
+ Creates a new QScreenOrientationChangeEvent
+ \a screenOrientationInDegrees is the new screen orientation, expressed in degrees.
+ The orientation must be expressed in steps of 90 degrees.
+*/
+QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(qint32 screenOrientationInDegrees)
+ : QEvent(QEvent::OrientationChange)
+{
+ d = reinterpret_cast<QEventPrivate *>(new QScreenOrientationChangeEventPrivate());
+ d_func()->orientationInDegrees = screenOrientationInDegrees;
+
+ qint32 orientationIndex = (qAbs(screenOrientationInDegrees) % 360) / 90;
+ // flip around the negative coords to correct order.
+ if (screenOrientationInDegrees < 0) {
+ if (orientationIndex == 1)
+ orientationIndex = 3;
+ else if (orientationIndex == 3)
+ orientationIndex = 1;
+ }
+
+ orientationIndex = qPow(2, orientationIndex);
+ d_func()->orientation = (QScreenOrientationChangeEvent::Orientation)(orientationIndex);
+ d_func()->isValid = (screenOrientationInDegrees % 90 == 0);
+}
+
+/*!
+ Creates a new QScreenOrientationChangeEvent
+ \a orientation is the new orientation of the screen.
+*/
+QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(QScreenOrientationChangeEvent::Orientation screenOrientation)
+ : QEvent(QEvent::OrientationChange)
+{
+ d = reinterpret_cast<QEventPrivate *>(new QScreenOrientationChangeEventPrivate());
+ d_func()->orientation = screenOrientation;
+ d_func()->orientationInDegrees = 90 * ((uint)screenOrientation);
+ d_func()->isValid = true;
+}
+
+/*!
+ Destroys QScreenOrientationChangeEvent.
+*/
+QScreenOrientationChangeEvent::~QScreenOrientationChangeEvent()
+{
+ delete reinterpret_cast<QScrollEventPrivate *>(d);
+}
+
+/*!
+ Returns the orientation of the screen.
+*/
+QScreenOrientationChangeEvent::Orientation QScreenOrientationChangeEvent::orientation() const
+{
+ return d_func()->orientation;
+}
+
+/*!
+ Returns the screen orientation in degrees.
+ The orientation is expressed in steps of 90 degrees and depends on the previous value of the orientation.
+ This is intended to allow for smooth animations from one orientation to the other.
+*/
+qint32 QScreenOrientationChangeEvent::orientationInDegrees() const
+{
+ return d_func()->orientationInDegrees;
+}
+
+/*!
+ \internal
+*/
+QScreenOrientationChangeEventPrivate *QScreenOrientationChangeEvent::d_func()
+{
+ return reinterpret_cast<QScreenOrientationChangeEventPrivate *>(d);
+}
+
+/*!
+ \internal
+*/
+const QScreenOrientationChangeEventPrivate *QScreenOrientationChangeEvent::d_func() const
+{
+ return reinterpret_cast<const QScreenOrientationChangeEventPrivate *>(d);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 59d50df268..de0d6b3793 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -84,62 +84,62 @@ protected:
class Q_GUI_EXPORT QMouseEvent : public QInputEvent
{
public:
- QMouseEvent(Type type, const QPoint &pos, Qt::MouseButton button,
+ QMouseEvent(Type type, const QPointF &pos, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
- QMouseEvent(Type type, const QPoint &pos, const QPoint &globalPos,
+ QMouseEvent(Type type, const QPointF &pos, const QPointF &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers);
~QMouseEvent();
- inline const QPoint &pos() const { return p; }
- inline const QPoint &globalPos() const { return g; }
- inline int x() const { return p.x(); }
- inline int y() const { return p.y(); }
- inline int globalX() const { return g.x(); }
- inline int globalY() const { return g.y(); }
+ inline QPoint pos() const { return p.toPoint(); }
+ inline QPoint globalPos() const { return g.toPoint(); }
+ inline int x() const { return qRound(p.x()); }
+ inline int y() const { return qRound(p.y()); }
+ inline int globalX() const { return qRound(g.x()); }
+ inline int globalY() const { return qRound(g.y()); }
inline Qt::MouseButton button() const { return b; }
inline Qt::MouseButtons buttons() const { return mouseState; }
- static QMouseEvent *createExtendedMouseEvent(Type type, const QPointF &pos,
- const QPoint &globalPos, Qt::MouseButton button,
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
- inline bool hasExtendedInfo() const { return reinterpret_cast<const QMouseEvent *>(d) == this; }
- QPointF posF() const;
+ const QPointF &posF() const { return p; }
+ const QPointF &globalPosF() const { return g; }
protected:
- QPoint p, g;
+ QPointF p, g;
Qt::MouseButton b;
Qt::MouseButtons mouseState;
};
-class Q_GUI_EXPORT QHoverEvent : public QEvent
+class Q_GUI_EXPORT QHoverEvent : public QInputEvent
{
public:
- QHoverEvent(Type type, const QPoint &pos, const QPoint &oldPos);
+ QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
~QHoverEvent();
- inline const QPoint &pos() const { return p; }
- inline const QPoint &oldPos() const { return op; }
+ inline QPoint pos() const { return p.toPoint(); }
+ inline QPoint oldPos() const { return op.toPoint(); }
+
+ inline const QPointF &posF() const { return p; }
+ inline const QPointF &oldPosF() const { return op; }
protected:
- QPoint p, op;
+ QPointF p, op;
};
#ifndef QT_NO_WHEELEVENT
class Q_GUI_EXPORT QWheelEvent : public QInputEvent
{
public:
- QWheelEvent(const QPoint &pos, int delta,
+ QWheelEvent(const QPointF &pos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient = Qt::Vertical);
- QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta,
+ QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
Qt::Orientation orient = Qt::Vertical);
~QWheelEvent();
inline int delta() const { return d; }
- inline const QPoint &pos() const { return p; }
- inline const QPoint &globalPos() const { return g; }
+ inline QPoint pos() const { return p.toPoint(); }
+ inline QPoint globalPos() const { return g.toPoint(); }
inline int x() const { return p.x(); }
inline int y() const { return p.y(); }
inline int globalX() const { return g.x(); }
@@ -148,9 +148,12 @@ public:
inline Qt::MouseButtons buttons() const { return mouseState; }
Qt::Orientation orientation() const { return o; }
+ inline const QPointF &posF() const { return p; }
+ inline const QPointF &globalPosF() const { return g; }
+
protected:
- QPoint p;
- QPoint g;
+ QPointF p;
+ QPointF g;
int d;
Qt::MouseButtons mouseState;
Qt::Orientation o;
@@ -819,6 +822,30 @@ private:
const QScrollEventPrivate *d_func() const;
};
+class QScreenOrientationChangeEventPrivate;
+class Q_GUI_EXPORT QScreenOrientationChangeEvent : public QEvent
+{
+public:
+ enum Orientation {
+ Portrait = 1,
+ Landscape = 2,
+ PortraitInverted = 4,
+ LandscapeInverted = 8
+ };
+ QScreenOrientationChangeEvent(qint32 screenOrientationInDegrees);
+ QScreenOrientationChangeEvent(Orientation screenOrientation);
+ ~QScreenOrientationChangeEvent();
+
+ bool isValid() const;
+ qint32 orientationInDegrees() const;
+ Orientation orientation() const;
+
+private:
+ QScreenOrientationChangeEventPrivate *d_func();
+ const QScreenOrientationChangeEventPrivate *d_func() const;
+
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 731cfc97f2..59eb270230 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -81,20 +81,6 @@ protected:
friend class QKeyEvent;
};
-// ### Qt 5: remove
-class QMouseEventEx : public QMouseEvent
-{
-public:
- QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
- Qt::MouseButton button, Qt::MouseButtons buttons,
- Qt::KeyboardModifiers modifiers);
- ~QMouseEventEx();
-
-protected:
- QPointF posF;
- friend class QMouseEvent;
-};
-
class QTouchEventTouchPointPrivate
{
public:
@@ -167,6 +153,17 @@ public:
QScrollEvent::ScrollState state;
};
+class QScreenOrientationChangeEventPrivate
+{
+public:
+ inline QScreenOrientationChangeEventPrivate()
+ {
+ }
+ QScreenOrientationChangeEvent::Orientation orientation;
+ qint32 orientationInDegrees;
+ bool isValid;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 98ed02879a..d644bbace1 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -1277,7 +1277,7 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
{coordinate mode} use coordinateMode().
- \sa {demos/gradients}{The Gradients Demo}, QBrush
+ \sa {painting/gradients}{The Gradients Example}, QBrush
*/
/*!
@@ -1587,8 +1587,8 @@ bool QGradient::operator==(const QGradient &gradient)
returns the final stop point of the gradient, and the start()
function returning the start point of the gradient.
- \sa QRadialGradient, QConicalGradient, {demos/gradients}{The
- Gradients Demo}
+ \sa QRadialGradient, QConicalGradient, {painting/gradients}{The
+ Gradients Example}
*/
@@ -1773,8 +1773,8 @@ void QLinearGradient::setFinalStop(const QPointF &stop)
radius() functions returning the gradient's center, focal point
and radius respectively.
- \sa QLinearGradient, QConicalGradient, {demos/gradients}{The
- Gradients Demo}
+ \sa QLinearGradient, QConicalGradient, {painting/gradients}{The
+ Gradients Example}
*/
static QPointF qt_radial_gradient_adapt_focal_point(const QPointF &center,
@@ -2143,8 +2143,8 @@ void QRadialGradient::setFocalPoint(const QPointF &focalPoint)
gradient can be specified through its radius or final stop points,
respectively.
- \sa QLinearGradient, QRadialGradient, {demos/gradients}{The
- Gradients Demo}
+ \sa QLinearGradient, QRadialGradient, {painting/gradients}{The
+ Gradients Example}
*/
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index d694b4b9a8..cdc0978ed7 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -409,10 +409,11 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
if (clipLine(rx1, ry1, rx2, ry2))
return;
- int x1 = toF26Dot6(rx1);
- int y1 = toF26Dot6(ry1);
- int x2 = toF26Dot6(rx2);
- int y2 = toF26Dot6(ry2);
+ const int half = 32;
+ int x1 = toF26Dot6(rx1) + half;
+ int y1 = toF26Dot6(ry1) + half;
+ int x2 = toF26Dot6(rx2) + half;
+ int y2 = toF26Dot6(ry2) + half;
int dx = qAbs(x2 - x1);
int dy = qAbs(y2 - y1);
@@ -424,6 +425,7 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
swapped = true;
qSwap(y1, y2);
qSwap(x1, x2);
+ --x1; --x2; --y1; --y2;
}
int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
int x = x1 << 10;
@@ -455,6 +457,7 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
swapped = true;
qSwap(x1, x2);
qSwap(y1, y2);
+ --x1; --x2; --y1; --y2;
}
int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
int y = y1 << 10;
@@ -525,7 +528,9 @@ void QCosmeticStroker::drawPath(const QVectorPath &path)
const QPainterPath::ElementType *e = subPath(type, end, points, &closed);
if (closed) {
const qreal *p = points + 2*(e-type);
- calculateLastPoint(p[-4], p[-3], p[-2], p[-1]);
+ QPointF p1 = QPointF(p[-4], p[-3]) * state->matrix;
+ QPointF p2 = QPointF(p[-2], p[-1]) * state->matrix;
+ calculateLastPoint(p1.x(), p1.y(), p2.x(), p2.y());
}
int caps = (!closed & drawCaps) ? CapBegin : NoCaps;
// qDebug() << "closed =" << closed << capString(caps);
@@ -577,8 +582,10 @@ void QCosmeticStroker::drawPath(const QVectorPath &path)
// handle closed path case
bool closed = path.hasImplicitClose() || (points[0] == end[-2] && points[1] == end[-1]);
int caps = (!closed & drawCaps) ? CapBegin : NoCaps;
- if (closed)
- calculateLastPoint(end[-2], end[-1], points[0], points[1]);
+ if (closed) {
+ QPointF p2 = QPointF(end[-2], end[-1]) * state->matrix;
+ calculateLastPoint(p2.x(), p2.y(), p.x(), p.y());
+ }
points += 2;
while (points < end) {
@@ -656,8 +663,8 @@ void QCosmeticStroker::renderCubicSubdivision(QCosmeticStroker::PointF *points,
qreal dy = points[3].y - points[0].y;
qreal len = ((qreal).25) * (qAbs(dx) + qAbs(dy));
- if (qAbs(dx * (points[0].y - points[2].y) - dy * (points[0].x - points[2].x)) > len ||
- qAbs(dx * (points[0].y - points[1].y) - dy * (points[0].x - points[1].x)) > len) {
+ if (qAbs(dx * (points[0].y - points[2].y) - dy * (points[0].x - points[2].x)) >= len ||
+ qAbs(dx * (points[0].y - points[1].y) - dy * (points[0].x - points[1].x)) >= len) {
splitCubic(points);
--level;
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index d2c84f0485..767706a5bc 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -177,7 +177,7 @@ QT_BEGIN_NAMESPACE
\endtable
\sa QPainter, QTransform, {Coordinate System},
- {demos/affine}{Affine Transformations Demo}, {Transformations Example}
+ {painting/affine}{Affine Transformations Example}, {Transformations Example}
*/
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index 7c17c1b46e..8b607b28b8 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -47,6 +47,8 @@
QT_BEGIN_NAMESPACE
+static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
+
#define qreal_to_fixed_26_6(f) (int(f * 64))
@@ -214,6 +216,13 @@ void QOutlineMapper::endOutline()
elements = m_elements_dev.data();
}
+ if (m_round_coords) {
+ // round coordinates to match outlines drawn with drawLine_midpoint_i
+ for (int i = 0; i < m_elements.size(); ++i)
+ elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta),
+ qFloor(elements[i].y() + aliasedCoordinateDelta));
+ }
+
controlPointRect = boundingRect(elements, element_count);
#ifdef QT_DEBUG_CONVERT
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index 1432d6fc4b..388858ca44 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -95,7 +95,8 @@ public:
m_tags(0),
m_contours(0),
m_polygon_dev(0),
- m_in_clip_elements(false)
+ m_in_clip_elements(false),
+ m_round_coords(false)
{
}
@@ -201,6 +202,8 @@ public:
QT_FT_Outline *convertPath(const QPainterPath &path);
QT_FT_Outline *convertPath(const QVectorPath &path);
+ void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; }
+
inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); }
public:
@@ -234,6 +237,9 @@ public:
bool m_valid;
bool m_in_clip_elements;
+
+private:
+ bool m_round_coords;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index c93cb88135..09ffc8ec59 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -118,6 +118,8 @@ void dumpClip(int width, int height, const QClipData *clip);
// 4 pixels.
#define int_dim(pos, dim) (int(pos+dim) - int(pos))
+static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
+
#ifdef Q_OS_WIN
static inline bool winClearTypeFontsEnabled()
@@ -165,6 +167,10 @@ enum LineDrawMode {
LineDrawIncludeLastPixel
};
+static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
+ ProcessSpans pen_func, ProcessSpans brush_func,
+ QSpanData *pen_data, QSpanData *brush_data);
+
struct QRasterFloatPoint {
qreal x;
qreal y;
@@ -479,10 +485,6 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
}
#endif
-#if defined(Q_OS_WIN)
- d->isPlain45DegreeRotation = true;
-#endif
-
if (d->mono_surface)
d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono;
#if defined(Q_OS_WIN)
@@ -586,33 +588,6 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale);
ensureOutlineMapper();
-
-#ifdef Q_OS_WIN
- Q_D(QRasterPaintEngine);
- d->isPlain45DegreeRotation = false;
- if (txop >= QTransform::TxRotate) {
- d->isPlain45DegreeRotation =
- (qFuzzyIsNull(matrix.m11())
- && qFuzzyIsNull(matrix.m12() - qreal(1))
- && qFuzzyIsNull(matrix.m21() + qreal(1))
- && qFuzzyIsNull(matrix.m22())
- )
- ||
- (qFuzzyIsNull(matrix.m11() + qreal(1))
- && qFuzzyIsNull(matrix.m12())
- && qFuzzyIsNull(matrix.m21())
- && qFuzzyIsNull(matrix.m22() + qreal(1))
- )
- ||
- (qFuzzyIsNull(matrix.m11())
- && qFuzzyIsNull(matrix.m12() + qreal(1))
- && qFuzzyIsNull(matrix.m21() - qreal(1))
- && qFuzzyIsNull(matrix.m22())
- )
- ;
- }
-#endif
-
}
@@ -1182,8 +1157,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
const QPainterPath::ElementType *types = path.elements();
// There are some cases that are not supported by clip(QRect)
- if (op != Qt::UniteClip && (op != Qt::IntersectClip || !s->clip
- || s->clip->hasRectClip || s->clip->hasRegionClip)) {
+ if (op != Qt::IntersectClip || !s->clip || s->clip->hasRectClip || s->clip->hasRegionClip) {
if (s->matrix.type() <= QTransform::TxScale
&& ((path.shape() == QVectorPath::RectangleHint)
|| (isRect(points, path.elementCount())
@@ -1226,18 +1200,6 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
newClip->fixup();
- if (op == Qt::UniteClip) {
- // merge clips
- QClipData *result = new QClipData(d->rasterBuffer->height());
- QClipData *current = s->clip ? s->clip : new QClipData(d->rasterBuffer->height());
- qt_merge_clip(current, newClip, result);
- result->fixup();
- delete newClip;
- if (!s->clip)
- delete current;
- newClip = result;
- }
-
if (s->flags.has_clip_ownership)
delete s->clip;
@@ -1263,7 +1225,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
if (op == Qt::NoClip) {
qrasterpaintengine_state_setNoClip(s);
- } else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
+ } else if (s->matrix.type() > QTransform::TxScale) {
QPaintEngineEx::clip(rect, op);
return;
@@ -1348,7 +1310,6 @@ void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
if (op == Qt::NoClip) {
qrasterpaintengine_state_setNoClip(s);
} else if (s->matrix.type() > QTransform::TxScale
- || op == Qt::UniteClip
|| (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
|| (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
QPaintEngineEx::clip(region, op);
@@ -1662,10 +1623,10 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- int x1 = qRound(rect.x());
- int y1 = qRound(rect.y());
- int x2 = qRound(rect.right());
- int y2 = qRound(rect.bottom());
+ int x1 = qRound(rect.x() + aliasedCoordinateDelta);
+ int y1 = qRound(rect.y() + aliasedCoordinateDelta);
+ int x2 = qRound(rect.right() + aliasedCoordinateDelta);
+ int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
if (x2 < x1)
qSwap(x1, x2);
@@ -1935,7 +1896,9 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
// Do the fill...
ensureBrush();
if (s->brushData.blend) {
+ d->outlineMapper->setCoordinateRounding(s->penData.blend && s->flags.fast_pen && s->lastPen.brush().isOpaque());
fillPolygon(points, pointCount, mode);
+ d->outlineMapper->setCoordinateRounding(false);
}
}
@@ -1982,6 +1945,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
if (s->brushData.blend) {
// Compose polygon fill..,
ensureOutlineMapper();
+ d->outlineMapper->setCoordinateRounding(s->penData.blend != 0);
d->outlineMapper->beginOutline(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
d->outlineMapper->moveTo(*points);
const QPoint *p = points;
@@ -1995,6 +1959,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
ProcessSpans brushBlend = d->getBrushFunc(d->outlineMapper->controlPointRect,
&s->brushData);
d->rasterize(d->outlineMapper->outline(), brushBlend, &s->brushData, d->rasterBuffer.data());
+ d->outlineMapper->setCoordinateRounding(false);
}
}
@@ -2244,7 +2209,10 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
int sr_b = qCeil(sr.bottom()) - 1;
if (s->matrix.type() <= QTransform::TxScale && !s->flags.antialiased && sr_l == sr_r && sr_t == sr_b) {
+ // as fillRect will apply the aliased coordinate delta we need to
+ // subtract it here as we don't use it for image drawing
QTransform old = s->matrix;
+ s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta);
// Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied.
QRgb color = img.pixel(sr_l, sr_t);
@@ -2388,9 +2356,11 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
d->initializeRasterizer(&d->image_filler_xform);
d->rasterizer->setAntialiased(s->flags.antialiased);
+ const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta);
+
const QRectF &rect = r.normalized();
- const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f);
- const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f);
+ const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs;
+ const QPointF b = s->matrix.map((rect.topRight() + rect.bottomRight()) * 0.5f) - offs;
if (s->flags.tx_noshear)
d->rasterizer->rasterizeLine(a, b, rect.height() / rect.width());
@@ -2399,12 +2369,13 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
return;
}
#endif
+ const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta;
QPainterPath path;
path.addRect(r);
QTransform m = s->matrix;
s->matrix = QTransform(m.m11(), m.m12(), m.m13(),
m.m21(), m.m22(), m.m23(),
- m.m31(), m.m32(), m.m33());
+ m.m31() - offs, m.m32() - offs, m.m33());
fillPath(path, &d->image_filler_xform);
s->matrix = m;
} else {
@@ -2856,6 +2827,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
rightShift = 3; // divide by 8
int margin = cache->glyphMargin();
+ const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
const uchar *bits = image.bits();
for (int i=0; i<numGlyphs; ++i) {
@@ -2865,8 +2837,8 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
if (c.isNull())
continue;
- int x = qFloor(positions[i].x) + c.baseLineX - margin;
- int y = qFloor(positions[i].y) - c.baseLineY - margin;
+ int x = qFloor(positions[i].x + offs) + c.baseLineX - margin;
+ int y = qFloor(positions[i].y + offs) - c.baseLineY - margin;
// printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
// c.x, c.y,
@@ -2904,13 +2876,15 @@ void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti)
fe->setFontScale(matrix.m11());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+ const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta);
+
for (int i=0; i<glyphs.size(); ++i) {
TOpenFontCharMetrics tmetrics;
const TUint8 *glyphBitmapBytes;
TSize glyphBitmapSize;
fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize);
- const int x = qFloor(positions[i].x + tmetrics.HorizBearingX());
- const int y = qFloor(positions[i].y - tmetrics.HorizBearingY());
+ const int x = qFloor(positions[i].x + tmetrics.HorizBearingX() + aliasDelta);
+ const int y = qFloor(positions[i].y - tmetrics.HorizBearingY() + aliasDelta);
alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight);
}
@@ -3010,6 +2984,19 @@ QRasterPaintEnginePrivate::getBrushFunc(const QRectF &rect,
return isUnclipped(rect, 0) ? data->unclipped_blend : data->blend;
}
+inline ProcessSpans
+QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
+ const QSpanData *data) const
+{
+ Q_Q(const QRasterPaintEngine);
+ const QRasterPaintEngineState *s = q->state();
+
+ if (!s->flags.fast_pen && s->matrix.type() > QTransform::TxTranslate)
+ return data->blend;
+ const int penWidth = s->flags.fast_pen ? 1 : qCeil(s->lastPen.widthF());
+ return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
+}
+
/*!
\reimp
*/
@@ -3089,6 +3076,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
for(int i = 0; i < glyphs.size(); i++) {
QImage img = fontEngine->alphaMapForGlyph(glyphs[i]);
glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
+ // ### hm, perhaps an QFixed offs = QFixed::fromReal(aliasedCoordinateDelta) is needed here?
alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(),
qRound(positions[i].x + metrics.x),
qRound(positions[i].y + metrics.y),
@@ -3269,6 +3257,30 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount)
*/
void QRasterPaintEngine::drawEllipse(const QRectF &rect)
{
+ Q_D(QRasterPaintEngine);
+ QRasterPaintEngineState *s = state();
+
+ ensurePen();
+ if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen)
+ || (qpen_style(s->lastPen) == Qt::NoPen))
+ && !s->flags.antialiased
+ && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT
+ && !rect.isEmpty()
+ && s->matrix.type() <= QTransform::TxScale) // no shear
+ {
+ ensureBrush();
+ const QRectF r = s->matrix.mapRect(rect);
+ ProcessSpans penBlend = d->getPenFunc(r, &s->penData);
+ ProcessSpans brushBlend = d->getBrushFunc(r, &s->brushData);
+ const QRect brect = QRect(int(r.x()), int(r.y()),
+ int_dim(r.x(), r.width()),
+ int_dim(r.y(), r.height()));
+ if (brect == r) {
+ drawEllipse_midpoint_i(brect, d->deviceRect, penBlend, brushBlend,
+ &s->penData, &s->brushData);
+ return;
+ }
+ }
QPaintEngineEx::drawEllipse(rect);
}
@@ -4221,7 +4233,6 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
}
break;
- case Qt::UniteClip:
case Qt::ReplaceClip:
clipData->newClip->appendSpans(spans, count);
break;
@@ -4767,6 +4778,125 @@ void QSpanData::initTexture(const QImage *image, int alpha, QTextureData::Type _
adjustSpanMethods();
}
+/*!
+ \internal
+ \a x and \a y is relative to the midpoint of \a rect.
+*/
+static inline void drawEllipsePoints(int x, int y, int length,
+ const QRect &rect,
+ const QRect &clip,
+ ProcessSpans pen_func, ProcessSpans brush_func,
+ QSpanData *pen_data, QSpanData *brush_data)
+{
+ if (length == 0)
+ return;
+
+ QT_FT_Span outline[4];
+ const int midx = rect.x() + (rect.width() + 1) / 2;
+ const int midy = rect.y() + (rect.height() + 1) / 2;
+
+ x = x + midx;
+ y = midy - y;
+
+ // topleft
+ outline[0].x = midx + (midx - x) - (length - 1) - (rect.width() & 0x1);
+ outline[0].len = qMin(length, x - outline[0].x);
+ outline[0].y = y;
+ outline[0].coverage = 255;
+
+ // topright
+ outline[1].x = x;
+ outline[1].len = length;
+ outline[1].y = y;
+ outline[1].coverage = 255;
+
+ // bottomleft
+ outline[2].x = outline[0].x;
+ outline[2].len = outline[0].len;
+ outline[2].y = midy + (midy - y) - (rect.height() & 0x1);
+ outline[2].coverage = 255;
+
+ // bottomright
+ outline[3].x = x;
+ outline[3].len = length;
+ outline[3].y = outline[2].y;
+ outline[3].coverage = 255;
+
+ if (brush_func && outline[0].x + outline[0].len < outline[1].x) {
+ QT_FT_Span fill[2];
+
+ // top fill
+ fill[0].x = outline[0].x + outline[0].len - 1;
+ fill[0].len = qMax(0, outline[1].x - fill[0].x);
+ fill[0].y = outline[1].y;
+ fill[0].coverage = 255;
+
+ // bottom fill
+ fill[1].x = outline[2].x + outline[2].len - 1;
+ fill[1].len = qMax(0, outline[3].x - fill[1].x);
+ fill[1].y = outline[3].y;
+ fill[1].coverage = 255;
+
+ int n = (fill[0].y >= fill[1].y ? 1 : 2);
+ n = qt_intersect_spans(fill, n, clip);
+ if (n > 0)
+ brush_func(n, fill, brush_data);
+ }
+ if (pen_func) {
+ int n = (outline[1].y >= outline[2].y ? 2 : 4);
+ n = qt_intersect_spans(outline, n, clip);
+ if (n > 0)
+ pen_func(n, outline, pen_data);
+ }
+}
+
+/*!
+ \internal
+ Draws an ellipse using the integer point midpoint algorithm.
+*/
+static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip,
+ ProcessSpans pen_func, ProcessSpans brush_func,
+ QSpanData *pen_data, QSpanData *brush_data)
+{
+ const qreal a = qreal(rect.width()) / 2;
+ const qreal b = qreal(rect.height()) / 2;
+ qreal d = b*b - (a*a*b) + 0.25*a*a;
+
+ int x = 0;
+ int y = (rect.height() + 1) / 2;
+ int startx = x;
+
+ // region 1
+ while (a*a*(2*y - 1) > 2*b*b*(x + 1)) {
+ if (d < 0) { // select E
+ d += b*b*(2*x + 3);
+ ++x;
+ } else { // select SE
+ d += b*b*(2*x + 3) + a*a*(-2*y + 2);
+ drawEllipsePoints(startx, y, x - startx + 1, rect, clip,
+ pen_func, brush_func, pen_data, brush_data);
+ startx = ++x;
+ --y;
+ }
+ }
+ drawEllipsePoints(startx, y, x - startx + 1, rect, clip,
+ pen_func, brush_func, pen_data, brush_data);
+
+ // region 2
+ d = b*b*(x + 0.5)*(x + 0.5) + a*a*((y - 1)*(y - 1) - b*b);
+ const int miny = rect.height() & 0x1;
+ while (y > miny) {
+ if (d < 0) { // select SE
+ d += b*b*(2*x + 2) + a*a*(-2*y + 3);
+ ++x;
+ } else { // select S
+ d += a*a*(-2*y + 3);
+ }
+ --y;
+ drawEllipsePoints(x, y, 1, rect, clip,
+ pen_func, brush_func, pen_data, brush_data);
+ }
+}
/*!
\fn void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount)
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 9bdfbff9f6..d387e1312a 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -314,6 +314,7 @@ public:
bool isUnclipped_normalized(const QRect &rect) const;
bool isUnclipped(const QRect &rect, int penWidth) const;
bool isUnclipped(const QRectF &rect, int penWidth) const;
+ ProcessSpans getPenFunc(const QRectF &rect, const QSpanData *data) const;
ProcessSpans getBrushFunc(const QRect &rect, const QSpanData *data) const;
ProcessSpans getBrushFunc(const QRectF &rect, const QSpanData *data) const;
@@ -356,10 +357,6 @@ public:
uint mono_surface : 1;
uint outlinemapper_xform_dirty : 1;
-#ifdef Q_OS_WIN
- uint isPlain45DegreeRotation : 1;
-#endif
-
QScopedPointer<QRasterizer> rasterizer;
};
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index d46b30b6e2..be5c41ce76 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1092,19 +1092,19 @@ void QPainterPrivate::updateState(QPainterState *newState)
function that draws the outline of the given path (i.e. strokes
the path).
- See also the \l {demos/deform}{Vector Deformation} demo which
+ See also the \l {painting/deform}{Vector Deformation} example which
shows how to use advanced vector techniques to draw text using a
- QPainterPath, the \l {demos/gradients}{Gradients} demo which shows
+ QPainterPath, the \l {painting/gradients}{Gradients} example which shows
the different types of gradients that are available in Qt, and the \l
- {demos/pathstroke}{Path Stroking} demo which shows Qt's built-in
+ {painting/pathstroke}{Path Stroking} example which shows Qt's built-in
dash patterns and shows how custom patterns can be used to extend
the range of available patterns.
\table
\header
- \o \l {demos/deform}{Vector Deformation}
- \o \l {demos/gradients}{Gradients}
- \o \l {demos/pathstroke}{Path Stroking}
+ \o \l {painting/deform}{Vector Deformation}
+ \o \l {painting/gradients}{Gradients}
+ \o \l {painting/pathstroke}{Path Stroking}
\row
\o \inlineimage qpainter-vectordeformation.png
\o \inlineimage qpainter-gradients.png
@@ -1196,7 +1196,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
rotate it clockwise and translate() to translate it (i.e. adding a
given offset to the points). You can also twist the coordinate
system around the origin using the shear() function. See the \l
- {demos/affine}{Affine Transformations} demo for a visualization of
+ {painting/affine}{Affine Transformations} example for a visualization of
a sheared coordinate system.
See also the \l {painting/transformations}{Transformations}
@@ -1207,9 +1207,9 @@ void QPainterPrivate::updateState(QPainterState *newState)
\table 100%
\row
\o
- \bold {Affine Transformations Demo}
+ \bold {Affine Transformations Example}
- The \l {demos/affine}{Affine Transformations} demo show Qt's
+ The \l {painting/affine}{Affine Transformations} example shows Qt's
ability to perform affine transformations on painting
operations. The demo also allows the user to experiment with the
transformation operations and see the results immediately.
@@ -1293,8 +1293,8 @@ void QPainterPrivate::updateState(QPainterState *newState)
\o
\bold {Composition Modes Demo}
- The \l {demos/composition}{Composition Modes} demo, available in
- Qt's demo directory, allows you to experiment with the various
+ The \l {painting/composition}{Composition Modes} example, available in
+ Qt's examples directory, allows you to experiment with the various
composition modes and see the results immediately.
\endtable
@@ -2526,8 +2526,6 @@ QRegion QPainter::clipRegion() const
}
if (info.operation == Qt::IntersectClip)
region &= info.region * matrix;
- else if (info.operation == Qt::UniteClip)
- region |= info.region * matrix;
else if (info.operation == Qt::NoClip) {
lastWasNothing = true;
region = QRegion();
@@ -2547,9 +2545,6 @@ QRegion QPainter::clipRegion() const
if (info.operation == Qt::IntersectClip) {
region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
info.path.fillRule());
- } else if (info.operation == Qt::UniteClip) {
- region |= QRegion((info.path * matrix).toFillPolygon().toPolygon(),
- info.path.fillRule());
} else if (info.operation == Qt::NoClip) {
lastWasNothing = true;
region = QRegion();
@@ -2573,8 +2568,6 @@ QRegion QPainter::clipRegion() const
region &= matrix.mapRect(info.rect);
else
region &= matrix.map(QRegion(info.rect));
- } else if (info.operation == Qt::UniteClip) {
- region |= QRegion(info.rect) * matrix;
} else if (info.operation == Qt::NoClip) {
lastWasNothing = true;
region = QRegion();
@@ -2597,8 +2590,6 @@ QRegion QPainter::clipRegion() const
region &= matrix.mapRect(info.rectf.toRect());
else
region &= matrix.map(QRegion(info.rectf.toRect()));
- } else if (info.operation == Qt::UniteClip) {
- region |= QRegion(info.rectf.toRect()) * matrix;
} else if (info.operation == Qt::NoClip) {
lastWasNothing = true;
region = QRegion();
@@ -2687,7 +2678,7 @@ QRectF QPainter::clipBoundingRect() const
}
// Accumulate the bounding box in device space. This is not 100%
- // precise, but it fits within the guarantee and it is resonably
+ // precise, but it fits within the guarantee and it is reasonably
// fast.
QRectF bounds;
for (int i=0; i<d->state->clipInfo.size(); ++i) {
@@ -2709,8 +2700,6 @@ QRectF QPainter::clipBoundingRect() const
bounds = r;
else if (info.operation == Qt::IntersectClip)
bounds &= r;
- else if (info.operation == Qt::UniteClip)
- bounds |= r;
}
@@ -2739,7 +2728,7 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
Q_D(QPainter);
if (d->extended) {
- if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
+ if ((!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (!d->engine) {
@@ -2797,7 +2786,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
return;
}
- if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
+ if ((!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (d->extended) {
@@ -2852,7 +2841,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
return;
}
- if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
+ if ((!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (d->extended) {
@@ -3257,7 +3246,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
return;
}
- if ((!d->state->clipEnabled && op != Qt::NoClip) || (d->state->clipOperation == Qt::NoClip && op == Qt::UniteClip))
+ if ((!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (d->extended) {
@@ -3374,7 +3363,7 @@ void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
\endtable
\sa {painting/painterpaths}{the Painter Paths
- example},{demos/deform}{the Vector Deformation demo}
+ example},{painting/deform}{the Vector Deformation example}
*/
void QPainter::drawPath(const QPainterPath &path)
{
@@ -5658,6 +5647,8 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
}
/*!
+ \fn void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphs)
+
Draws the glyphs represented by \a glyphs at \a position. The \a position gives the
edge of the baseline for the string of glyphs. The glyphs will be retrieved from the font
selected on \a glyphs and at offsets given by the positions in \a glyphs.
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index c238578199..8bb599f9f0 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -305,19 +305,19 @@ static void qt_debug_path(const QPainterPath &path)
\section1 Examples
Qt provides the \l {painting/painterpaths}{Painter Paths Example}
- and the \l {demos/deform}{Vector Deformation Demo} which are
- located in Qt's example and demo directories respectively.
+ and the \l {painting/deform}{Vector Deformation example} which are
+ located in Qt's example directory.
The \l {painting/painterpaths}{Painter Paths Example} shows how
painter paths can be used to build complex shapes for rendering
and lets the user experiment with the filling and stroking. The
- \l {demos/deform}{Vector Deformation Demo} shows how to use
+ \l {painting/deform}{Vector Deformation Example} shows how to use
QPainterPath to draw text.
\table
\header
\o \l {painting/painterpaths}{Painter Paths Example}
- \o \l {demos/deform}{Vector Deformation Demo}
+ \o \l {painting/deform}{Vector Deformation Example}
\row
\o \inlineimage qpainterpath-example.png
\o \inlineimage qpainterpath-demo.png
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index cc652d84f2..7185f0d346 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -214,14 +214,14 @@ typedef QPenPrivate QPenData;
\table 100%
\row
\o \inlineimage qpen-demo.png
- \o \bold {\l {demos/pathstroke}{The Path Stroking Demo}}
+ \o \bold {\l {painting/pathstroke}{The Path Stroking Example}}
- The Path Stroking demo shows Qt's built-in dash patterns and shows
+ The Path Stroking example shows Qt's built-in dash patterns and shows
how custom patterns can be used to extend the range of available
patterns.
\endtable
- \sa QPainter, QBrush, {demos/pathstroke}{Path Stroking Demo},
+ \sa QPainter, QBrush, {painting/pathstroke}{Path Stroking Example},
{Scribble Example}
*/
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index 6c5edbc44d..1d3f581b88 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -62,8 +62,8 @@ typedef int Q16Dot16;
#define SPAN_BUFFER_SIZE 256
-#define COORD_ROUNDING 0 // 0: round up, 1: round down
-#define COORD_OFFSET 0 // 26.6, 32 is half a pixel
+#define COORD_ROUNDING 1 // 0: round up, 1: round down
+#define COORD_OFFSET 32 // 26.6, 32 is half a pixel
static inline QT_FT_Vector PointToVector(const QPointF &p)
{
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 4d7b3391a6..e42eec6f96 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -223,8 +223,8 @@ QT_BEGIN_NAMESPACE
\snippet doc/src/snippets/transform/main.cpp 2
\endtable
- \sa QPainter, {Coordinate System}, {demos/affine}{Affine
- Transformations Demo}, {Transformations Example}
+ \sa QPainter, {Coordinate System}, {painting/affine}{Affine
+ Transformations Example}, {Transformations Example}
*/
/*!
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 846d5a3814..b85c045064 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -73,7 +73,8 @@
#include <QtGui/private/qguiapplication_p.h>
#endif
-#include <QMutexLocker>
+#include <QtCore/QMutexLocker>
+#include <QtCore/QMutex>
// #define QFONTCACHE_DEBUG
#ifdef QFONTCACHE_DEBUG
@@ -140,7 +141,7 @@ bool QFontDef::exactMatch(const QFontDef &other) const
&& weight == other.weight
&& style == other.style
&& this_family == other_family
- && styleName == other.styleName
+ && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
&& (this_foundry.isEmpty()
|| other_foundry.isEmpty()
|| this_foundry == other_foundry)
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index 4ae31c38d6..ebc842c794 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -113,7 +113,7 @@ struct QFontDef
&& styleStrategy == other.styleStrategy
&& ignorePitch == other.ignorePitch && fixedPitch == other.fixedPitch
&& family == other.family
- && styleName == other.styleName
+ && (styleName.isEmpty() || other.styleName.isEmpty() || styleName == other.styleName)
&& hintingPreference == other.hintingPreference
#ifdef Q_WS_X11
&& addStyle == other.addStyle
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 5369ac52f3..98b43d5b5e 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -218,16 +218,17 @@ struct QtFontStyle
Key(const QString &styleString);
Key() : style(QFont::StyleNormal),
weight(QFont::Normal), stretch(0) { }
- Key(const Key &o) : style(o.style),
+ Key(const Key &o) : styleName(o.styleName), style(o.style),
weight(o.weight), stretch(o.stretch) { }
+ QString styleName;
uint style : 2;
signed int weight : 8;
signed int stretch : 12;
bool operator==(const Key & other) {
- return (style == other.style &&
+ return styleName == other.styleName && style == other.style &&
weight == other.weight &&
- (stretch == 0 || other.stretch == 0 || stretch == other.stretch));
+ (stretch == 0 || other.stretch == 0 || stretch == other.stretch);
}
bool operator!=(const Key &other) {
return !operator==(other);
@@ -292,7 +293,7 @@ struct QtFontStyle
};
QtFontStyle::Key::Key(const QString &styleString)
- : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
+ : styleName(styleString), style(QFont::StyleNormal), weight(QFont::Normal), stretch(0)
{
weight = getFontWeight(styleString);
@@ -1139,6 +1140,12 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
for ( int i = 0; i < foundry->count; i++ ) {
QtFontStyle *style = foundry->styles[i];
+ if (!styleKey.styleName.isEmpty() && styleKey.styleName == style->key.styleName) {
+ dist = 0;
+ best = i;
+ break;
+ }
+
int d = qAbs( styleKey.weight - style->key.weight );
if ( styleKey.stretch != 0 && style->key.stretch != 0 ) {
@@ -1532,7 +1539,8 @@ static QString styleStringHelper(int weight, QFont::Style style)
*/
QString QFontDatabase::styleString(const QFont &font)
{
- return styleStringHelper(font.weight(), font.style());
+ return font.styleName().isEmpty() ? styleStringHelper(font.weight(), font.style())
+ : font.styleName();
}
/*!
@@ -1542,7 +1550,8 @@ QString QFontDatabase::styleString(const QFont &font)
*/
QString QFontDatabase::styleString(const QFontInfo &fontInfo)
{
- return styleStringHelper(fontInfo.weight(), fontInfo.style());
+ return fontInfo.styleName().isEmpty() ? styleStringHelper(fontInfo.weight(), fontInfo.style())
+ : fontInfo.styleName();
}
@@ -1793,8 +1802,12 @@ QStringList QFontDatabase::styles(const QString &family) const
}
}
- for (int i = 0; i < allStyles.count; i++)
- l.append(styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style));
+ for (int i = 0; i < allStyles.count; i++) {
+ l.append(allStyles.styles[i]->key.styleName.isEmpty() ?
+ styleStringHelper(allStyles.styles[i]->key.weight,
+ (QFont::Style)allStyles.styles[i]->key.style) :
+ allStyles.styles[i]->key.styleName);
+ }
return l;
}
@@ -2017,9 +2030,16 @@ QFont QFontDatabase::font(const QString &family, const QString &style,
if (!s) // no styles found?
return QGuiApplication::font();
- QFont fnt(family, pointSize, s->key.weight);
- fnt.setStyle((QFont::Style)s->key.style);
- return fnt;
+ if (s->key.styleName.isEmpty()) {
+ QFont fnt(family, pointSize, s->key.weight);
+ fnt.setStyle((QFont::Style)s->key.style);
+ return fnt;
+ } else {
+ // found a perfect match
+ QFont fnt(family, pointSize);
+ fnt.setStyleName(s->key.styleName);
+ return fnt;
+ }
}
diff --git a/src/gui/text/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp
index 890cad9824..d6932738f5 100644
--- a/src/gui/text/qfontenginedirectwrite.cpp
+++ b/src/gui/text/qfontenginedirectwrite.cpp
@@ -390,6 +390,60 @@ glyph_metrics_t QFontEngineDirectWrite::boundingBox(const QGlyphLayout &glyphs)
return glyph_metrics_t(0, -m_ascent, w - lastRightBearing(glyphs), m_ascent + m_descent, w, 0);
}
+glyph_metrics_t QFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition,
+ const QTransform &matrix,
+ GlyphFormat /*format*/)
+{
+ glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance
+
+ UINT16 glyphIndex = glyph;
+ FLOAT glyphAdvance = 0;
+
+ DWRITE_GLYPH_OFFSET glyphOffset;
+ glyphOffset.advanceOffset = 0;
+ glyphOffset.ascenderOffset = 0;
+
+ DWRITE_GLYPH_RUN glyphRun;
+ glyphRun.fontFace = m_directWriteFontFace;
+ glyphRun.fontEmSize = fontDef.pixelSize;
+ glyphRun.glyphCount = 1;
+ glyphRun.glyphIndices = &glyphIndex;
+ glyphRun.glyphAdvances = &glyphAdvance;
+ glyphRun.isSideways = false;
+ glyphRun.bidiLevel = 0;
+ glyphRun.glyphOffsets = &glyphOffset;
+
+ DWRITE_MATRIX transform;
+ transform.dx = subPixelPosition.toReal();
+ transform.dy = 0;
+ transform.m11 = matrix.m11();
+ transform.m12 = matrix.m12();
+ transform.m21 = matrix.m21();
+ transform.m22 = matrix.m22();
+
+ IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
+ HRESULT hr = m_directWriteFactory->CreateGlyphRunAnalysis(
+ &glyphRun,
+ 1.0f,
+ &transform,
+ DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
+ DWRITE_MEASURING_MODE_NATURAL,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
+
+ if (SUCCEEDED(hr)) {
+ RECT rect;
+ glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->Release();
+
+ return glyph_metrics_t(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
+ bbox.xoff, bbox.yoff);
+ } else {
+ return glyph_metrics_t();
+ }
+}
+
glyph_metrics_t QFontEngineDirectWrite::boundingBox(glyph_t g)
{
if (m_directWriteFontFace == 0)
@@ -459,9 +513,10 @@ qreal QFontEngineDirectWrite::maxCharWidth() const
extern uint qt_pow_gamma[256];
-QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition,
+ const QTransform &xform)
{
- QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform());
+ QImage im = imageForGlyph(glyph, subPixelPosition, 0, xform);
QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
QVector<QRgb> colors(256);
@@ -492,12 +547,8 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t,
int margin,
const QTransform &xform)
{
- glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform);
- int width = (metrics.width + margin * 2 + 4).ceil().toInt() ;
- int height = (metrics.height + margin * 2 + 4).ceil().toInt();
-
UINT16 glyphIndex = t;
- FLOAT glyphAdvance = metrics.xoff.toReal();
+ FLOAT glyphAdvance = 0;
DWRITE_GLYPH_OFFSET glyphOffset;
glyphOffset.advanceOffset = 0;
@@ -513,12 +564,9 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t,
glyphRun.bidiLevel = 0;
glyphRun.glyphOffsets = &glyphOffset;
- QFixed x = margin - metrics.x.round() + subPixelPosition;
- QFixed y = margin - metrics.y.floor();
-
DWRITE_MATRIX transform;
- transform.dx = x.toReal();
- transform.dy = y.toReal();
+ transform.dx = subPixelPosition.toReal();
+ transform.dy = 0;
transform.m11 = xform.m11();
transform.m12 = xform.m12();
transform.m21 = xform.m21();
@@ -537,48 +585,54 @@ QImage QFontEngineDirectWrite::imageForGlyph(glyph_t t,
if (SUCCEEDED(hr)) {
RECT rect;
- rect.left = 0;
- rect.top = 0;
- rect.right = width;
- rect.bottom = height;
-
- int size = width * height * 3;
- BYTE *alphaValues = new BYTE[size];
- qMemSet(alphaValues, size, 0);
-
- hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
- &rect,
- alphaValues,
- size);
-
- if (SUCCEEDED(hr)) {
- QImage img(width, height, QImage::Format_RGB32);
- img.fill(0xffffffff);
+ glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
- for (int y=0; y<height; ++y) {
- uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
- BYTE *src = alphaValues + width * 3 * y;
+ rect.left -= margin;
+ rect.top -= margin;
+ rect.right += margin;
+ rect.bottom += margin;
- for (int x=0; x<width; ++x) {
- dest[x] = *(src) << 16
- | *(src + 1) << 8
- | *(src + 2);
+ int width = rect.right - rect.left;
+ int height = rect.bottom - rect.top;
- src += 3;
+ int size = width * height * 3;
+ if (size > 0) {
+ BYTE *alphaValues = new BYTE[size];
+ qMemSet(alphaValues, size, 0);
+
+ hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
+ &rect,
+ alphaValues,
+ size);
+
+ if (SUCCEEDED(hr)) {
+ QImage img(width, height, QImage::Format_RGB32);
+ img.fill(0xffffffff);
+
+ for (int y=0; y<height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(img.scanLine(y));
+ BYTE *src = alphaValues + width * 3 * y;
+
+ for (int x=0; x<width; ++x) {
+ dest[x] = *(src) << 16
+ | *(src + 1) << 8
+ | *(src + 2);
+
+ src += 3;
+ }
}
- }
- delete[] alphaValues;
- glyphAnalysis->Release();
+ delete[] alphaValues;
+ glyphAnalysis->Release();
- return img;
- } else {
- delete[] alphaValues;
- glyphAnalysis->Release();
+ return img;
+ } else {
+ delete[] alphaValues;
+ glyphAnalysis->Release();
- qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed");
+ qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateAlphaTexture failed");
+ }
}
-
} else {
qErrnoWarning("QFontEngineDirectWrite::imageForGlyph: CreateGlyphRunAnalysis failed");
}
diff --git a/src/gui/text/qfontenginedirectwrite_p.h b/src/gui/text/qfontenginedirectwrite_p.h
index d0086fc49b..edf1e6a182 100644
--- a/src/gui/text/qfontenginedirectwrite_p.h
+++ b/src/gui/text/qfontenginedirectwrite_p.h
@@ -86,6 +86,10 @@ public:
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
glyph_metrics_t boundingBox(glyph_t g);
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
+ QFixed subPixelPosition,
+ const QTransform &matrix,
+ GlyphFormat format);
QFixed ascent() const;
QFixed descent() const;
@@ -97,7 +101,7 @@ public:
bool supportsSubPixelPositions() const;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
+ QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin,
const QTransform &xform);
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index 18b6357863..cc825525c4 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -175,7 +175,8 @@ QRawFont QGlyphRun::rawFont() const
}
/*!
- Sets the font in which to look up the glyph indexes to \a font.
+ Sets the font in which to look up the glyph indexes to the \a rawFont
+ specified.
\sa rawFont(), setGlyphIndexes()
*/
diff --git a/src/gui/text/qharfbuzz_copy_p.h b/src/gui/text/qharfbuzz_copy_p.h
index 835d8fb1a6..10356e4aea 100644
--- a/src/gui/text/qharfbuzz_copy_p.h
+++ b/src/gui/text/qharfbuzz_copy_p.h
@@ -66,6 +66,13 @@ typedef enum {
HB_Err_Out_Of_Memory = 0xDEAD
} HB_Error;
+typedef enum {
+ HB_NoBreak,
+ HB_SoftHyphen,
+ HB_Break,
+ HB_ForcedBreak
+} HB_LineBreakType;
+
typedef QT_PREPEND_NAMESPACE(quint32) HB_Glyph;
typedef void * HB_Font;
typedef void * HB_Face;
diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp
index 7e829dbd3f..059dc3e188 100644
--- a/src/gui/text/qplatformfontdatabase_qpa.cpp
+++ b/src/gui/text/qplatformfontdatabase_qpa.cpp
@@ -52,7 +52,7 @@ extern void qt_registerFont(const QString &familyname, const QString &foundrynam
const QSupportedWritingSystems &writingSystems, void *hanlde);
/*!
- \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *)
+ \fn void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle)
Registers the pre-rendered QPF2 font contained in the given \a dataArray.
@@ -149,17 +149,26 @@ public:
QVector<bool> vector;
};
+/*!
+ Constructs a new object to handle supported writing systems.
+*/
QSupportedWritingSystems::QSupportedWritingSystems()
{
d = new QWritingSystemsPrivate;
}
+/*!
+ Constructs a copy of the \a other writing systems object.
+*/
QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other)
{
d = other.d;
d->ref.ref();
}
+/*!
+ Constructs a copy of the \a other writing systems object.
+*/
QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other)
{
if (d != other.d) {
@@ -171,12 +180,18 @@ QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWr
return *this;
}
+/*!
+ Destroys the supported writing systems object.
+*/
QSupportedWritingSystems::~QSupportedWritingSystems()
{
if (!d->ref.deref())
delete d;
}
+/*!
+ \internal
+*/
void QSupportedWritingSystems::detach()
{
if (d->ref != 1) {
@@ -187,12 +202,20 @@ void QSupportedWritingSystems::detach()
}
}
+/*!
+ Sets or clears support for the specified \a writingSystem based on the
+ value given by \a support.
+*/
void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support)
{
detach();
d->vector[writingSystem] = support;
}
+/*!
+ Returns true if the writing system specified by \a writingSystem is
+ supported; otherwise returns false.
+*/
bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const
{
return d->vector.at(writingSystem);
@@ -210,10 +233,12 @@ bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSys
*/
/*!
- This function is called once at startup by Qts internal fontdatabase. Reimplement this function
- in a subclass for a convenient place to initialise the internal fontdatabase.
+ This function is called once at startup by Qt's internal font database.
+ Reimplement this function in a subclass for a convenient place to initialize
+ the internal font database.
- The default implementation looks in the fontDir() location and registers all qpf2 fonts.
+ The default implementation looks in the fontDir() location and registers all
+ QPF2 fonts.
*/
void QPlatformFontDatabase::populateFontDatabase()
{
@@ -294,7 +319,7 @@ QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData
}
/*!
-
+ Releases the specified font \a handle.
*/
void QPlatformFontDatabase::releaseHandle(void *handle)
{
@@ -303,7 +328,7 @@ void QPlatformFontDatabase::releaseHandle(void *handle)
}
/*!
-
+ Returns the directory containing the fonts used by the database.
*/
QString QPlatformFontDatabase::fontDir() const
{
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 71762df09f..4c65ad5de0 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -393,6 +393,30 @@ qreal QRawFont::unitsPerEm() const
}
/*!
+ Returns the thickness for drawing lines (underline, overline, etc.)
+ along with text drawn in this font.
+ */
+qreal QRawFont::lineThickness() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->lineThickness().toReal();
+}
+
+/*!
+ Returns the position from baseline for drawing underlines below the text
+ rendered with this font.
+ */
+qreal QRawFont::underlinePosition() const
+{
+ if (!isValid())
+ return 0.0;
+
+ return d->fontEngine->underlinePosition().toReal();
+}
+
+/*!
Returns the family name of this QRawFont.
*/
QString QRawFont::familyName() const
@@ -652,6 +676,9 @@ extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSyst
/*!
Fetches the physical representation based on a \a font query. The physical font returned is
the font that will be preferred by Qt in order to display text in the selected \a writingSystem.
+
+ \warning This function is potentially expensive and should not be called in performance
+ sensitive code.
*/
QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem)
{
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index aca33af127..e94bd99b8c 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -111,6 +111,8 @@ public:
qreal xHeight() const;
qreal averageCharWidth() const;
qreal maxCharWidth() const;
+ qreal lineThickness() const;
+ qreal underlinePosition() const;
qreal unitsPerEm() const;
@@ -133,6 +135,7 @@ public:
private:
friend class QRawFontPrivate;
+ friend class QTextLayout;
void detach();
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index baa9eebb79..10c494dec9 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -425,14 +425,17 @@ namespace {
public:
DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
: m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
- m_untransformedCoordinates(untransformedCoordinates)
+ m_untransformedCoordinates(untransformedCoordinates), m_currentColor(Qt::black)
{
}
virtual void updateState(const QPaintEngineState &newState)
{
- if (newState.state() & QPaintEngine::DirtyPen)
+ if (newState.state() & QPaintEngine::DirtyPen
+ && newState.pen().color() != m_currentColor) {
m_dirtyPen = true;
+ m_currentColor = newState.pen().color();
+ }
}
virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
@@ -448,7 +451,7 @@ namespace {
currentItem.positionOffset = m_glyphs.size(); // Offset into position pool
currentItem.useBackendOptimizations = m_useBackendOptimizations;
if (m_dirtyPen)
- currentItem.color = state->pen().color();
+ currentItem.color = m_currentColor;
QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
matrix.translate(position.x(), position.y());
@@ -519,6 +522,7 @@ namespace {
bool m_dirtyPen;
bool m_useBackendOptimizations;
bool m_untransformedCoordinates;
+ QColor m_currentColor;
};
class DrawTextItemDevice: public QPaintDevice
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 03e00ed0df..918ddcc280 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1002,15 +1002,46 @@ QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
if (length < 0)
length = text().length();
- QList<QGlyphRun> glyphs;
+ QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash;
for (int i=0; i<d->lines.size(); ++i) {
if (d->lines[i].from > from + length)
break;
- else if (d->lines[i].from + d->lines[i].length >= from)
- glyphs += QTextLine(i, d).glyphRuns(from, length);
+ else if (d->lines[i].from + d->lines[i].length >= from) {
+ QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);
+
+ for (int j = 0; j < glyphRuns.size(); j++) {
+ const QGlyphRun &glyphRun = glyphRuns.at(j);
+ QRawFont rawFont = glyphRun.rawFont();
+
+ QFontEngine *fontEngine = rawFont.d->fontEngine;
+ QTextItem::RenderFlags flags;
+ if (glyphRun.underline())
+ flags |= QTextItem::Underline;
+ if (glyphRun.overline())
+ flags |= QTextItem::Overline;
+ if (glyphRun.strikeOut())
+ flags |= QTextItem::StrikeOut;
+ QPair<QFontEngine *, int> key(fontEngine, int(flags));
+ // merge the glyph runs using the same font
+ if (glyphRunHash.contains(key)) {
+ QGlyphRun &oldGlyphRun = glyphRunHash[key];
+
+ QVector<quint32> indexes = oldGlyphRun.glyphIndexes();
+ QVector<QPointF> positions = oldGlyphRun.positions();
+
+ indexes += glyphRun.glyphIndexes();
+ positions += glyphRun.positions();
+
+ oldGlyphRun.setGlyphIndexes(indexes);
+ oldGlyphRun.setPositions(positions);
+ } else {
+ glyphRunHash[key] = glyphRun;
+ }
+ }
+ }
}
- return glyphs;
+ return glyphRunHash.values();
}
#endif // QT_NO_RAWFONT
@@ -2075,19 +2106,65 @@ static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const Q
}
-namespace {
- struct GlyphInfo
- {
- GlyphInfo(const QGlyphLayout &layout, const QPointF &position,
- const QTextItemInt::RenderFlags &renderFlags)
- : glyphLayout(layout), itemPosition(position), flags(renderFlags)
- {
- }
+static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine, const QGlyphLayout &glyphLayout,
+ const QPointF &pos, const QTextItem::RenderFlags &flags)
+{
+ QGlyphRun glyphRun;
- QGlyphLayout glyphLayout;
- QPointF itemPosition;
- QTextItem::RenderFlags flags;
- };
+ // Make a font for this particular engine
+ QRawFont font;
+ QRawFontPrivate *fontD = QRawFontPrivate::get(font);
+ fontD->fontEngine = fontEngine;
+ fontD->fontEngine->ref.ref();
+
+#if defined(Q_WS_WIN)
+ if (fontEngine->supportsSubPixelPositions())
+ fontD->hintingPreference = QFont::PreferVerticalHinting;
+ else
+ fontD->hintingPreference = QFont::PreferFullHinting;
+#elif defined(Q_WS_MAC)
+ fontD->hintingPreference = QFont::PreferNoHinting;
+#elif !defined(QT_NO_FREETYPE)
+ if (fontEngine->type() == QFontEngine::Freetype) {
+ QFontEngineFT *freeTypeEngine = static_cast<QFontEngineFT *>(fontEngine);
+ switch (freeTypeEngine->defaultHintStyle()) {
+ case QFontEngineFT::HintNone:
+ fontD->hintingPreference = QFont::PreferNoHinting;
+ break;
+ case QFontEngineFT::HintLight:
+ fontD->hintingPreference = QFont::PreferVerticalHinting;
+ break;
+ case QFontEngineFT::HintMedium:
+ case QFontEngineFT::HintFull:
+ fontD->hintingPreference = QFont::PreferFullHinting;
+ break;
+ };
+ }
+#endif
+
+ QVarLengthArray<glyph_t> glyphsArray;
+ QVarLengthArray<QFixedPoint> positionsArray;
+
+ fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray,
+ positionsArray);
+ Q_ASSERT(glyphsArray.size() == positionsArray.size());
+
+ QVector<quint32> glyphs;
+ QVector<QPointF> positions;
+ for (int i=0; i<glyphsArray.size(); ++i) {
+ glyphs.append(glyphsArray.at(i) & 0xffffff);
+ positions.append(positionsArray.at(i).toPointF() + pos);
+ }
+
+ glyphRun.setGlyphIndexes(glyphs);
+ glyphRun.setPositions(positions);
+
+ glyphRun.setOverline(flags.testFlag(QTextItem::Overline));
+ glyphRun.setUnderline(flags.testFlag(QTextItem::Underline));
+ glyphRun.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
+ glyphRun.setRawFont(font);
+
+ return glyphRun;
}
/*!
@@ -2117,10 +2194,9 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (length < 0)
length = textLength();
- QHash<QFontEngine *, GlyphInfo> glyphLayoutHash;
-
QTextLineItemIterator iterator(eng, i);
qreal y = line.y.toReal() + line.base().toReal();
+ QList<QGlyphRun> glyphRuns;
while (!iterator.atEnd()) {
QScriptItem &si = iterator.next();
if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
@@ -2191,8 +2267,8 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
continue;
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
- glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
- GlyphInfo(subLayout, pos, flags));
+ glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
+ subLayout, pos, flags));
for (int i = 0; i < subLayout.numGlyphs; i++) {
pos += QPointF(subLayout.advances_x[i].toReal(),
subLayout.advances_y[i].toReal());
@@ -2203,101 +2279,15 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
- glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
- GlyphInfo(subLayout, pos, flags));
-
+ glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
+ subLayout, pos, flags));
} else {
- glyphLayoutHash.insertMulti(mainFontEngine,
- GlyphInfo(glyphLayout, pos, flags));
- }
- }
- }
-
- QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphsHash;
-
- QList<QFontEngine *> keys = glyphLayoutHash.uniqueKeys();
- for (int i=0; i<keys.size(); ++i) {
- QFontEngine *fontEngine = keys.at(i);
-
- // Make a font for this particular engine
- QRawFont font;
- QRawFontPrivate *fontD = QRawFontPrivate::get(font);
- fontD->fontEngine = fontEngine;
- fontD->fontEngine->ref.ref();
-
-#if defined(Q_WS_WIN)
- if (fontEngine->supportsSubPixelPositions())
- fontD->hintingPreference = QFont::PreferVerticalHinting;
- else
- fontD->hintingPreference = QFont::PreferFullHinting;
-#elif defined(Q_WS_MAC)
- fontD->hintingPreference = QFont::PreferNoHinting;
-#elif !defined(QT_NO_FREETYPE)
- if (fontEngine->type() == QFontEngine::Freetype) {
- QFontEngineFT *freeTypeEngine = static_cast<QFontEngineFT *>(fontEngine);
- switch (freeTypeEngine->defaultHintStyle()) {
- case QFontEngineFT::HintNone:
- fontD->hintingPreference = QFont::PreferNoHinting;
- break;
- case QFontEngineFT::HintLight:
- fontD->hintingPreference = QFont::PreferVerticalHinting;
- break;
- case QFontEngineFT::HintMedium:
- case QFontEngineFT::HintFull:
- fontD->hintingPreference = QFont::PreferFullHinting;
- break;
- };
- }
-#endif
-
- QList<GlyphInfo> glyphLayouts = glyphLayoutHash.values(fontEngine);
- for (int j=0; j<glyphLayouts.size(); ++j) {
- const QPointF &pos = glyphLayouts.at(j).itemPosition;
- const QGlyphLayout &glyphLayout = glyphLayouts.at(j).glyphLayout;
- const QTextItem::RenderFlags &flags = glyphLayouts.at(j).flags;
-
- QVarLengthArray<glyph_t> glyphsArray;
- QVarLengthArray<QFixedPoint> positionsArray;
-
- fontEngine->getGlyphPositions(glyphLayout, QTransform(), flags, glyphsArray,
- positionsArray);
- Q_ASSERT(glyphsArray.size() == positionsArray.size());
-
- QVector<quint32> glyphs;
- QVector<QPointF> positions;
- for (int i=0; i<glyphsArray.size(); ++i) {
- glyphs.append(glyphsArray.at(i) & 0xffffff);
- positions.append(positionsArray.at(i).toPointF() + pos);
- }
-
- QGlyphRun glyphIndexes;
- glyphIndexes.setGlyphIndexes(glyphs);
- glyphIndexes.setPositions(positions);
-
- glyphIndexes.setOverline(flags.testFlag(QTextItem::Overline));
- glyphIndexes.setUnderline(flags.testFlag(QTextItem::Underline));
- glyphIndexes.setStrikeOut(flags.testFlag(QTextItem::StrikeOut));
- glyphIndexes.setRawFont(font);
-
- QPair<QFontEngine *, int> key(fontEngine, int(flags));
- if (!glyphsHash.contains(key)) {
- glyphsHash.insert(key, glyphIndexes);
- } else {
- QGlyphRun &glyphRun = glyphsHash[key];
-
- QVector<quint32> indexes = glyphRun.glyphIndexes();
- QVector<QPointF> positions = glyphRun.positions();
-
- indexes += glyphIndexes.glyphIndexes();
- positions += glyphIndexes.positions();
-
- glyphRun.setGlyphIndexes(indexes);
- glyphRun.setPositions(positions);
+ glyphRuns.append(glyphRunWithInfo(mainFontEngine, glyphLayout, pos, flags));
}
}
}
- return glyphsHash.values();
+ return glyphRuns;
}
#endif // QT_NO_RAWFONT