summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qdrawhelper.cpp34
-rw-r--r--src/gui/painting/qdrawhelper_p.h2
-rw-r--r--src/gui/painting/qdrawutil.cpp210
-rw-r--r--src/gui/painting/qdrawutil.h25
-rw-r--r--src/gui/painting/qpaintengineex.cpp21
-rw-r--r--src/gui/painting/qpaintengineex_p.h2
-rw-r--r--src/gui/painting/qpainter.cpp209
-rw-r--r--src/gui/painting/qpainter.h26
-rw-r--r--src/gui/painting/qpainter_p.h8
-rw-r--r--src/gui/painting/qprintengine_win.cpp3
10 files changed, 365 insertions, 175 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index c37e49a..891f4c2 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -3701,7 +3701,7 @@ template <>
Q_STATIC_TEMPLATE_SPECIALIZATION
inline quint32 alpha_4(const qargb8555 *src)
{
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint8 *src8 = reinterpret_cast<const quint8*>(src);
return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9];
}
@@ -4027,8 +4027,8 @@ template <>
inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4123,8 +4123,8 @@ template <>
inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
@@ -4219,8 +4219,8 @@ template <>
inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src,
quint32 alpha)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = eff_alpha_4(alpha, dest);
const quint32 ia = eff_ialpha_4(alpha, dest);
@@ -4292,8 +4292,8 @@ template <class DST, class SRC>
inline void interpolate_pixel_4(DST *dest, quint8 a,
const SRC *src, quint8 b)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
@@ -4304,8 +4304,8 @@ inline void interpolate_pixel_4(DST *dest, quint8 a,
template <class DST, class SRC>
inline void blend_sourceOver_4(DST *dest, const SRC *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4320,8 +4320,8 @@ inline void blend_sourceOver_4(DST *dest, const SRC *src)
template <>
inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4334,8 +4334,8 @@ inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
template <>
inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
@@ -4348,8 +4348,8 @@ inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
template <>
inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src)
{
- Q_ASSERT((long(dest) & 0x3) == 0);
- Q_ASSERT((long(src) & 0x3) == 0);
+ Q_ASSERT((quintptr(dest) & 0x3) == 0);
+ Q_ASSERT((quintptr(src) & 0x3) == 0);
const quint32 a = alpha_4(src);
if (a == 0xffffffff) {
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index df4d9c5..f5b17ea 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1640,7 +1640,7 @@ inline void qt_memconvert(qrgb666 *dest, const quint32 *src, int count)
return;
}
- const int align = (long(dest) & 3);
+ const int align = (quintptr(dest) & 3);
switch (align) {
case 1: *dest++ = qrgb666(*src++); --count;
case 2: *dest++ = qrgb666(*src++); --count;
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 5619a2e..d76c709 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1081,7 +1081,7 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
according to the \a margins structure.
*/
-typedef QVarLengthArray<QDrawPixmaps::Data, 16> QDrawPixmapsDataArray;
+typedef QVarLengthArray<QPainter::Fragment, 16> QPixmapFragmentsArray;
/*!
\since 4.6
@@ -1102,12 +1102,12 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
- QDrawPixmaps::Data d;
+ QPainter::Fragment d;
d.opacity = 1.0;
d.rotation = 0.0;
- QDrawPixmapsDataArray opaqueData;
- QDrawPixmapsDataArray translucentData;
+ QPixmapFragmentsArray opaqueData;
+ QPixmapFragmentsArray translucentData;
// source center
const int sourceCenterTop = sourceRect.top() + sourceMargins.top();
@@ -1182,44 +1182,56 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
// corners
if (targetMargins.top() > 0 && targetMargins.left() > 0 && sourceMargins.top() > 0 && sourceMargins.left() > 0) { // top left
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.source = QRectF(sourceRect.left(), sourceRect.top(), sourceMargins.left(), sourceMargins.top());
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceRect.top();
+ d.width = sourceMargins.left();
+ d.height = sourceMargins.top();
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueTopLeft)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.top() > 0 && targetMargins.right() > 0 && sourceMargins.top() > 0 && sourceMargins.right() > 0) { // top right
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.source = QRectF(sourceCenterRight, sourceRect.top(), sourceMargins.right(), sourceMargins.top());
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceRect.top();
+ d.width = sourceMargins.right();
+ d.height = sourceMargins.top();
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueTopRight)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.left() > 0 && sourceMargins.bottom() > 0 && sourceMargins.left() > 0) { // bottom left
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.source = QRectF(sourceRect.left(), sourceCenterBottom, sourceMargins.left(), sourceMargins.bottom());
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.y =(0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceMargins.left();
+ d.height = sourceMargins.bottom();
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueBottomLeft)
opaqueData.append(d);
else
translucentData.append(d);
}
if (targetMargins.bottom() > 0 && targetMargins.right() > 0 && sourceMargins.bottom() > 0 && sourceMargins.right() > 0) { // bottom right
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.source = QRectF(sourceCenterRight, sourceCenterBottom, sourceMargins.right(), sourceMargins.bottom());
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceMargins.right();
+ d.height = sourceMargins.bottom();
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
if (hints & QDrawBorderPixmap::OpaqueBottomRight)
opaqueData.append(d);
else
@@ -1229,151 +1241,107 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
// horizontal edges
if (targetCenterWidth > 0 && sourceCenterWidth > 0) {
if (targetMargins.top() > 0 && sourceMargins.top() > 0) { // top
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceRect.top(), sourceCenterWidth, sourceMargins.top());
- d.point.setY(0.5 * (yTarget[1] + yTarget[0]));
- d.scaleX = dx / d.source.width();
- d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueTop ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceRect.top();
+ d.width = sourceCenterWidth;
+ d.height = sourceMargins.top();
+ d.y = (0.5 * (yTarget[1] + yTarget[0]));
+ d.scaleX = dx / d.width;
+ d.scaleY = qreal(yTarget[1] - yTarget[0]) / d.height;
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
+ data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
if (targetMargins.bottom() > 0 && sourceMargins.bottom() > 0) { // bottom
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom());;
- d.point.setY(0.5 * (yTarget[rows] + yTarget[rows - 1]));
- d.scaleX = dx / d.source.width();
- d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueBottom ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceCenterBottom;
+ d.width = sourceCenterWidth;
+ d.height = sourceMargins.bottom();
+ d.y = (0.5 * (yTarget[rows] + yTarget[rows - 1]));
+ d.scaleX = dx / d.width;
+ d.scaleY = qreal(yTarget[rows] - yTarget[rows - 1]) / d.height;
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
+ data[data.size() - 1].width = ((xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX);
}
}
// vertical edges
if (targetCenterHeight > 0 && sourceCenterHeight > 0) {
if (targetMargins.left() > 0 && sourceMargins.left() > 0) { // left
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
- d.source = QRectF(sourceRect.left(), sourceCenterTop, sourceMargins.left(), sourceCenterHeight);
- d.point.setX(0.5 * (xTarget[1] + xTarget[0]));
- d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueLeft ? opaqueData : translucentData;
+ d.sourceLeft = sourceRect.left();
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceMargins.left();
+ d.height = sourceCenterHeight;
+ d.x = (0.5 * (xTarget[1] + xTarget[0]));
+ d.scaleX = qreal(xTarget[1] - xTarget[0]) / d.width;
+ d.scaleY = dy / d.height;
for (int i = 1; i < rows - 1; ++i) {
- d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
data.append(d);
}
if (rules.vertical == Qt::RepeatTile)
- data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
+ data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
if (targetMargins.right() > 0 && sourceMargins.right() > 0) { // right
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterRight, sourceCenterTop, sourceMargins.right(), sourceCenterHeight);
- d.point.setX(0.5 * (xTarget[columns] + xTarget[columns - 1]));
- d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueRight ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterRight;
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceMargins.right();
+ d.height = sourceCenterHeight;
+ d.x = (0.5 * (xTarget[columns] + xTarget[columns - 1]));
+ d.scaleX = qreal(xTarget[columns] - xTarget[columns - 1]) / d.width;
+ d.scaleY = dy / d.height;
for (int i = 1; i < rows - 1; ++i) {
- d.point.setY(0.5 * (yTarget[i + 1] + yTarget[i]));
+ d.y = (0.5 * (yTarget[i + 1] + yTarget[i]));
data.append(d);
}
if (rules.vertical == Qt::RepeatTile)
- data[data.size() - 1].source.setHeight((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
+ data[data.size() - 1].height = ((yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY);
}
}
// center
if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
- QDrawPixmapsDataArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
- d.source = QRectF(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
- d.scaleX = dx / d.source.width();
- d.scaleY = dy / d.source.height();
+ QPixmapFragmentsArray &data = hints & QDrawBorderPixmap::OpaqueCenter ? opaqueData : translucentData;
+ d.sourceLeft = sourceCenterLeft;
+ d.sourceTop = sourceCenterTop;
+ d.width = sourceCenterWidth;
+ d.height = sourceCenterHeight;
+ d.scaleX = dx / d.width;
+ d.scaleY = dy / d.height;
qreal repeatWidth = (xTarget[columns - 1] - xTarget[columns - 2]) / d.scaleX;
qreal repeatHeight = (yTarget[rows - 1] - yTarget[rows - 2]) / d.scaleY;
for (int j = 1; j < rows - 1; ++j) {
- d.point.setY(0.5 * (yTarget[j + 1] + yTarget[j]));
+ d.y = (0.5 * (yTarget[j + 1] + yTarget[j]));
for (int i = 1; i < columns - 1; ++i) {
- d.point.setX(0.5 * (xTarget[i + 1] + xTarget[i]));
+ d.x = (0.5 * (xTarget[i + 1] + xTarget[i]));
data.append(d);
}
if (rules.horizontal == Qt::RepeatTile)
- data[data.size() - 1].source.setWidth(repeatWidth);
+ data[data.size() - 1].width = repeatWidth;
}
if (rules.vertical == Qt::RepeatTile) {
for (int i = 1; i < columns - 1; ++i)
- data[data.size() - i].source.setHeight(repeatHeight);
+ data[data.size() - i].height = repeatHeight;
}
}
if (opaqueData.size())
- qDrawPixmaps(painter, opaqueData.data(), opaqueData.size(), pixmap, QDrawPixmaps::OpaqueHint);
+ painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
if (translucentData.size())
- qDrawPixmaps(painter, translucentData.data(), translucentData.size(), pixmap);
-}
-
-/*!
- \class QDrawPixmaps::Data
- \since 4.6
- \internal
-
- This structure is used with the qDrawPixmaps() function.
-
- QPointF point: Specifies the center of the target rectangle.
- QRectF source: Specifies the source rectangle in the pixmap passed into the qDrawPixmaps() call.
- qreal scaleX: Specifies the horizontal scale of the target rectangle.
- qreal scaleY: Specifies the vertical scale of the target rectangle.
- qreal rotation: Specifies the rotation of the target rectangle in degrees.
- The target rectangle is rotated after scaling.
- qreal opacity: Specifies the opacity of the rectangle.
-*/
-
-/*!
- \enum QDrawPixmaps::DrawingHint
- \internal
-*/
-
-/*!
- \internal
- \since 4.6
-
- This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap, at multiple positions
- with different scale, rotation and opacity on \a painter. \a drawingData is an array of \a
- dataCount elements specifying the parameters used to draw each pixmap instance.
- This can be used for example to implement a particle system.
-*/
-void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
-{
- QPaintEngine *engine = painter->paintEngine();
- if (!engine)
- return;
-
- if (engine->isExtended()) {
- static_cast<QPaintEngineEx *>(engine)->drawPixmaps(drawingData, dataCount, pixmap, hints);
- } else {
- qreal oldOpacity = painter->opacity();
- QTransform oldTransform = painter->transform();
-
- for (int i = 0; i < dataCount; ++i) {
- QTransform transform = oldTransform;
- transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
- transform.rotate(drawingData[i].rotation);
- painter->setOpacity(oldOpacity * drawingData[i].opacity);
- painter->setTransform(transform);
-
- qreal w = drawingData[i].scaleX * drawingData[i].source.width();
- qreal h = drawingData[i].scaleY * drawingData[i].source.height();
- painter->drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
- }
-
- painter->setOpacity(oldOpacity);
- painter->setTransform(oldTransform);
- }
+ painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 2801b2f..31e352f 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -188,31 +188,6 @@ inline void qDrawBorderPixmap(QPainter *painter,
qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
}
-// For internal use only.
-namespace QDrawPixmaps
-{
- struct Data
- {
- QPointF point;
- QRectF source;
- qreal scaleX;
- qreal scaleY;
- qreal rotation;
- qreal opacity;
- };
-
- enum DrawingHint
- {
- OpaqueHint = 0x01
- };
-
- Q_DECLARE_FLAGS(DrawingHints, DrawingHint)
-}
-
-// This function is private and may change without notice. Do not use outside Qt!!!
-Q_GUI_EXPORT void qDrawPixmaps(QPainter *painter, const QDrawPixmaps::Data *drawingData,
- int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints = 0);
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 4f2fffa..98762f0 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -893,7 +893,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
for (int i=0; i<count; ++i) {
pts[++oset] = points[i].x();
pts[++oset] = points[i].y();
- pts[++oset] = points[i].x() + 1/63;
+ pts[++oset] = points[i].x() + 1/63.;
pts[++oset] = points[i].y();
}
QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint);
@@ -970,23 +970,26 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
fill(path, brush);
}
-void QPaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints /*hints*/)
+void QPaintEngineEx::drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, QPainter::FragmentHints /*hints*/)
{
qreal oldOpacity = state()->opacity;
QTransform oldTransform = state()->matrix;
- for (int i = 0; i < dataCount; ++i) {
+ for (int i = 0; i < fragmentCount; ++i) {
QTransform transform = oldTransform;
- transform.translate(drawingData[i].point.x(), drawingData[i].point.y());
- transform.rotate(drawingData[i].rotation);
- state()->opacity = oldOpacity * drawingData[i].opacity;
+ transform.translate(fragments[i].x, fragments[i].y);
+ transform.rotate(fragments[i].rotation);
+ state()->opacity = oldOpacity * fragments[i].opacity;
state()->matrix = transform;
opacityChanged();
transformChanged();
- qreal w = drawingData[i].scaleX * drawingData[i].source.width();
- qreal h = drawingData[i].scaleY * drawingData[i].source.height();
- drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, drawingData[i].source);
+ qreal w = fragments[i].scaleX * fragments[i].width;
+ qreal h = fragments[i].scaleY * fragments[i].height;
+ QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
+ fragments[i].width, fragments[i].height);
+ drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
}
state()->opacity = oldOpacity;
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 90c4f9f..2401b94 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -197,7 +197,7 @@ public:
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s);
- virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QFlags<QDrawPixmaps::DrawingHint> hints);
+ virtual void drawPixmapFragments(const QPainter::Fragment *fragments, int fragmentCount, const QPixmap &pixmap, QFlags<QPainter::FragmentHint> hints);
virtual void updateState(const QPaintEngineState &state);
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 4f532c0..dc96c17 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5700,6 +5700,61 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(sx, sy, sw, sh), flags);
}
+
+void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray, const QPointF *positionArray,
+ int glyphCount)
+{
+ QPainterPrivate *painter_d = QPainterPrivate::get(painter);
+ painter_d->drawGlyphs(glyphArray, positionArray, glyphCount);
+}
+
+void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray,
+ int glyphCount)
+{
+ updateState(state);
+
+ QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
+
+ QVarLengthArray<QFixedPoint, 128> positions;
+ for (int i=0; i<glyphCount; ++i) {
+ QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
+ positions.append(fp);
+ }
+
+ if (extended != 0) {
+ QStaticTextItem staticTextItem;
+ staticTextItem.color = state->pen.color();
+ staticTextItem.font = state->font;
+ staticTextItem.fontEngine = fontEngine;
+ staticTextItem.numGlyphs = glyphCount;
+ staticTextItem.glyphs = reinterpret_cast<glyph_t *>(const_cast<glyph_t *>(glyphArray));
+ staticTextItem.glyphPositions = positions.data();
+
+ extended->drawStaticTextItem(&staticTextItem);
+ } else {
+ QTextItemInt textItem;
+ textItem.f = &state->font;
+ textItem.fontEngine = fontEngine;
+
+ QVarLengthArray<QFixed, 128> advances(glyphCount);
+ QVarLengthArray<QGlyphJustification, 128> glyphJustifications(glyphCount);
+ QVarLengthArray<HB_GlyphAttributes, 128> glyphAttributes(glyphCount);
+ qMemSet(glyphAttributes.data(), 0, glyphAttributes.size() * sizeof(HB_GlyphAttributes));
+ qMemSet(advances.data(), 0, advances.size() * sizeof(QFixed));
+ qMemSet(glyphJustifications.data(), 0, glyphJustifications.size() * sizeof(QGlyphJustification));
+
+ textItem.glyphs.numGlyphs = glyphCount;
+ textItem.glyphs.glyphs = reinterpret_cast<HB_Glyph *>(const_cast<quint32 *>(glyphArray));
+ textItem.glyphs.offsets = positions.data();
+ textItem.glyphs.advances_x = advances.data();
+ textItem.glyphs.advances_y = advances.data();
+ textItem.glyphs.justifications = glyphJustifications.data();
+ textItem.glyphs.attributes = glyphAttributes.data();
+
+ engine->drawTextItem(QPointF(0, 0), textItem);
+ }
+}
+
/*!
\fn void QPainter::drawStaticText(const QPoint &position, const QStaticText &staticText)
@@ -8847,6 +8902,160 @@ QTransform QPainter::combinedTransform() const
return d->state->worldMatrix * d->viewTransform();
}
+/*!
+ \since 4.7
+
+ This function is used to draw \a pixmap, or a sub-rectangle of \a pixmap,
+ at multiple positions with different scale, rotation and opacity. \a
+ fragments is an array of \a fragmentCount elements specifying the
+ parameters used to draw each pixmap fragment. The \a hints
+ parameter can be used to pass in drawing hints.
+
+ This function is potentially faster than multiple calls to drawPixmap(),
+ since the backend can optimize state changes.
+
+ \sa QPainter::Fragment, QPainter::FragmentHint
+*/
+
+void QPainter::drawPixmapFragments(const Fragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, FragmentHints hints)
+{
+ Q_D(QPainter);
+
+ if (!d->engine)
+ return;
+
+ if (d->engine->isExtended()) {
+ d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
+ } else {
+ qreal oldOpacity = opacity();
+ QTransform oldTransform = transform();
+
+ for (int i = 0; i < fragmentCount; ++i) {
+ QTransform transform = oldTransform;
+ transform.translate(fragments[i].x, fragments[i].y);
+ transform.rotate(fragments[i].rotation);
+ setOpacity(oldOpacity * fragments[i].opacity);
+ setTransform(transform);
+
+ qreal w = fragments[i].scaleX * fragments[i].width;
+ qreal h = fragments[i].scaleY * fragments[i].height;
+ QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop,
+ fragments[i].width, fragments[i].height);
+ drawPixmap(QRectF(-0.5 * w, -0.5 * h, w, h), pixmap, sourceRect);
+ }
+
+ setOpacity(oldOpacity);
+ setTransform(oldTransform);
+ }
+}
+
+/*!
+ \since 4.7
+ \class QPainter::Fragment
+
+ \brief This class is used in conjunction with the
+ QPainter::drawPixmapFragments() function to specify how a pixmap, or
+ sub-rect of a pixmap, is drawn.
+
+ The \a sourceLeft, \a sourceTop, \a width and \a height variables are used
+ as a source rectangle within the pixmap passed into the
+ QPainter::drawPixmapFragments() function. The variables \a x, \a y, \a
+ width and \a height are used to calculate the target rectangle that is
+ drawn. \a x and \a y denotes the center of the target rectangle. The \a
+ width and \a heigth in the target rectangle is scaled by the \a scaleX and
+ \a scaleY values. The resulting target rectangle is then rotated \a
+ rotation degrees around the \a x, \a y center point.
+
+ \sa QPainter::drawPixmapFragments()
+*/
+
+/*!
+ \since 4.7
+
+ This is a convenience function that returns a QPainter::Fragment that is
+ initialized with the \a pos, \a sourceRect, \a scaleX, \a scaleY, \a
+ rotation, \a opacity parameters.
+*/
+
+QPainter::Fragment QPainter::Fragment::create(const QPointF &pos, const QRectF &sourceRect,
+ qreal scaleX, qreal scaleY, qreal rotation,
+ qreal opacity)
+{
+ Fragment fragment = {pos.x(), pos.y(), sourceRect.x(), sourceRect.y(), sourceRect.width(),
+ sourceRect.height(), scaleX, scaleY, rotation, opacity};
+ return fragment;
+}
+
+/*!
+ \variable QPainter::Fragment::x
+ \brief the x coordinate of center point in the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::y
+ \brief the y coordinate of the center point in the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::sourceLeft
+ \brief the left coordinate of the source rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::sourceTop
+ \brief the top coordinate of the source rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::width
+
+ \brief the width of the source rectangle and is used to calculate the width
+ of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::height
+
+ \brief the height of the source rectangle and is used to calculate the
+ height of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::scaleX
+ \brief the horizontal scale of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::scaleY
+ \brief the vertical scale of the target rectangle.
+*/
+
+/*!
+ \variable QPainter::Fragment::rotation
+
+ \brief the rotation of the target rectangle in degrees. The target
+ rectangle is rotated after it has been scaled.
+*/
+
+/*!
+ \variable QPainter::Fragment::opacity
+
+ \brief the opacity of the target rectangle, where 0.0 is fully transparent
+ and 1.0 is fully opaque.
+*/
+
+/*!
+ \since 4.7
+
+ \enum QPainter::FragmentHint
+
+ \value OpaqueHint Indicates that the pixmap fragments to be drawn are
+ opaque. Opaque fragments are potentially faster to draw.
+
+ \sa QPainter::drawPixmapFragments(), QPainter::Fragment
+*/
+
void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation)
{
p->draw_helper(path, operation);
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index e9fd532..bcb0b50 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -99,6 +99,29 @@ public:
Q_DECLARE_FLAGS(RenderHints, RenderHint)
+ class Fragment {
+ public:
+ qreal x;
+ qreal y;
+ qreal sourceLeft;
+ qreal sourceTop;
+ qreal width;
+ qreal height;
+ qreal scaleX;
+ qreal scaleY;
+ qreal rotation;
+ qreal opacity;
+ static Fragment Q_GUI_EXPORT create(const QPointF &pos, const QRectF &sourceRect,
+ qreal scaleX = 1, qreal scaleY = 1,
+ qreal rotation = 0, qreal opacity = 1);
+ };
+
+ enum FragmentHint {
+ OpaqueHint = 0x01
+ };
+
+ Q_DECLARE_FLAGS(FragmentHints, FragmentHint)
+
QPainter();
explicit QPainter(QPaintDevice *);
~QPainter();
@@ -352,6 +375,9 @@ public:
inline void drawPixmap(const QRect &r, const QPixmap &pm);
inline void drawPixmap(int x, int y, int w, int h, const QPixmap &pm);
+ void drawPixmapFragments(const Fragment *fragments, int fragmentCount,
+ const QPixmap &pixmap, FragmentHints hints = 0);
+
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
Qt::ImageConversionFlags flags = Qt::AutoColor);
inline void drawImage(const QRect &targetRect, const QImage &image, const QRect &sourceRect,
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 02a91aa..9362dbe 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -228,6 +228,7 @@ public:
void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw);
void drawStretchedGradient(const QPainterPath &path, DrawOperation operation);
void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation);
+ void drawGlyphs(const quint32 *glyphArray, const QPointF *positionArray, int glyphCount);
void updateMatrix();
void updateInvMatrix();
@@ -238,6 +239,11 @@ public:
void checkEmulation();
+ static QPainterPrivate *get(QPainter *painter)
+ {
+ return painter->d_ptr.data();
+ }
+
QTransform viewTransform() const;
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
void detachPainterPrivate(QPainter *q);
@@ -252,6 +258,8 @@ public:
};
Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
+Q_GUI_EXPORT void qt_draw_glyphs(QPainter *painter, const quint32 *glyphArray,
+ const QPointF *positionArray, int glyphCount);
QString qt_generate_brush_key(const QBrush &brush);
diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp
index d029b1e..ea9dc5d 100644
--- a/src/gui/painting/qprintengine_win.cpp
+++ b/src/gui/painting/qprintengine_win.cpp
@@ -368,7 +368,8 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
}
// We only want to convert the glyphs to text if the entire string is compatible with ASCII
- bool convertToText = true;
+ // and if we actually have access to the chars.
+ bool convertToText = ti.chars != 0;
for (int i=0; i < ti.num_chars; ++i) {
if (ti.chars[i].unicode() >= 0x80) {
convertToText = false;