summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-05-19 08:45:52 (GMT)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-05-19 08:45:52 (GMT)
commit9547ade2b9cd7c792d98bf06ca8de89c9e560396 (patch)
treeaa43069092eaaa2078c21c86347c28e3ac41c574 /src/gui/painting
parentfa608f9094591c146f9170ba485ea2e4d7827dca (diff)
parentcbb28a77cb295b74d47a5a1923357dd6557bea84 (diff)
downloadQt-9547ade2b9cd7c792d98bf06ca8de89c9e560396.zip
Qt-9547ade2b9cd7c792d98bf06ca8de89c9e560396.tar.gz
Qt-9547ade2b9cd7c792d98bf06ca8de89c9e560396.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qbezier.cpp228
-rw-r--r--src/gui/painting/qbezier_p.h7
-rw-r--r--src/gui/painting/qdatabuffer_p.h19
-rw-r--r--src/gui/painting/qdrawutil.cpp14
-rw-r--r--src/gui/painting/qoutlinemapper.cpp3
-rw-r--r--src/gui/painting/qoutlinemapper_p.h11
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp52
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h3
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp2
-rw-r--r--src/gui/painting/qpaintengineex.cpp5
-rw-r--r--src/gui/painting/qpathclipper.cpp23
-rw-r--r--src/gui/painting/qpathclipper_p.h7
-rw-r--r--src/gui/painting/qpolygonclipper_p.h3
-rw-r--r--src/gui/painting/qprintengine_pdf.cpp46
-rw-r--r--src/gui/painting/qprintengine_pdf_p.h1
-rw-r--r--src/gui/painting/qrasterizer.cpp8
-rw-r--r--src/gui/painting/qstroker.cpp23
-rw-r--r--src/gui/painting/qstroker_p.h18
-rw-r--r--src/gui/painting/qtransform.cpp9
19 files changed, 177 insertions, 305 deletions
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index 7ff2a37..2a9b31a 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -93,7 +93,7 @@ QBezier QBezier::fromPoints(const QPointF &p1, const QPointF &p2,
/*!
\internal
*/
-QPolygonF QBezier::toPolygon() const
+QPolygonF QBezier::toPolygon(qreal bezier_flattening_threshold) const
{
// flattening is done by splitting the bezier until we can replace the segment by a straight
// line. We split further until the control points are close enough to the line connecting the
@@ -108,7 +108,7 @@ QPolygonF QBezier::toPolygon() const
QPolygonF polygon;
polygon.append(QPointF(x1, y1));
- addToPolygon(&polygon);
+ addToPolygon(&polygon, bezier_flattening_threshold);
return polygon;
}
@@ -117,34 +117,6 @@ QBezier QBezier::mapBy(const QTransform &transform) const
return QBezier::fromPoints(transform.map(pt1()), transform.map(pt2()), transform.map(pt3()), transform.map(pt4()));
}
-//0.05 is really low, but required for scaled-up beziers...
-static const qreal flatness = 0.05;
-
-//based on "Fast, precise flattening of cubic Bezier path and offset curves"
-// by T. F. Hain, A. L. Ahmad, S. V. R. Racherla and D. D. Langan
-static inline void flattenBezierWithoutInflections(QBezier &bez,
- QPolygonF *&p)
-{
- QBezier left;
-
- while (1) {
- qreal dx = bez.x2 - bez.x1;
- qreal dy = bez.y2 - bez.y1;
-
- qreal normalized = qSqrt(dx * dx + dy * dy);
- if (qFuzzyIsNull(normalized))
- break;
-
- qreal d = qAbs(dx * (bez.y3 - bez.y2) - dy * (bez.x3 - bez.x2));
-
- qreal t = qSqrt(4. / 3. * normalized * flatness / d);
- if (t > 1 || qFuzzyIsNull(t - (qreal)1.))
- break;
- bez.parameterSplitLeft(t, &left);
- p->append(bez.pt1());
- }
-}
-
QBezier QBezier::getSubRange(qreal t0, qreal t1) const
{
QBezier result;
@@ -223,7 +195,7 @@ static inline bool findInflections(qreal a, qreal b, qreal c,
}
-void QBezier::addToPolygon(QPolygonF *polygon) const
+void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold) const
{
QBezier beziers[32];
beziers[0] = *this;
@@ -243,7 +215,7 @@ void QBezier::addToPolygon(QPolygonF *polygon) const
qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
l = 1.;
}
- if (d < flatness*l || b == beziers + 31) {
+ if (d < bezier_flattening_threshold*l || b == beziers + 31) {
// good enough, we pop it off and add the endpoint
polygon->append(QPointF(b->x4, b->y4));
--b;
@@ -255,55 +227,6 @@ void QBezier::addToPolygon(QPolygonF *polygon) const
}
}
-void QBezier::addToPolygonMixed(QPolygonF *polygon) const
-{
- qreal ax = -x1 + 3*x2 - 3*x3 + x4;
- qreal ay = -y1 + 3*y2 - 3*y3 + y4;
- qreal bx = 3*x1 - 6*x2 + 3*x3;
- qreal by = 3*y1 - 6*y2 + 3*y3;
- qreal cx = -3*x1 + 3*x2;
- qreal cy = -3*y1 + 2*y2;
- qreal a = 6 * (ay * bx - ax * by);
- qreal b = 6 * (ay * cx - ax * cy);
- qreal c = 2 * (by * cx - bx * cy);
-
- if ((qFuzzyIsNull(a) && qFuzzyIsNull(b)) ||
- (b * b - 4 * a *c) < 0) {
- QBezier bez(*this);
- flattenBezierWithoutInflections(bez, polygon);
- polygon->append(QPointF(x4, y4));
- } else {
- QBezier beziers[32];
- beziers[0] = *this;
- QBezier *b = beziers;
-
- while (b >= beziers) {
- // check if we can pop the top bezier curve from the stack
- qreal y4y1 = b->y4 - b->y1;
- qreal x4x1 = b->x4 - b->x1;
- qreal l = qAbs(x4x1) + qAbs(y4y1);
- qreal d;
- if (l > 1.) {
- d = qAbs( (x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2) )
- + qAbs( (x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3) );
- } else {
- d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
- qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
- l = 1.;
- }
- if (d < .5*l || b == beziers + 31) {
- // good enough, we pop it off and add the endpoint
- polygon->append(QPointF(b->x4, b->y4));
- --b;
- } else {
- // split, second half of the polygon goes lower into the stack
- b->split(b+1, b);
- ++b;
- }
- }
- }
-}
-
QRectF QBezier::bounds() const
{
qreal xmin = x1;
@@ -824,147 +747,4 @@ QBezier QBezier::bezierOnInterval(qreal t0, qreal t1) const
return result;
}
-
-static inline void bindInflectionPoint(const QBezier &bez, const qreal t,
- qreal *tMinus , qreal *tPlus)
-{
- if (t <= 0) {
- *tMinus = *tPlus = -1;
- return;
- } else if (t >= 1) {
- *tMinus = *tPlus = 2;
- return;
- }
-
- QBezier left, right;
- splitBezierAt(bez, t, &left, &right);
-
- qreal ax = -right.x1 + 3*right.x2 - 3*right.x3 + right.x4;
- qreal ay = -right.y1 + 3*right.y2 - 3*right.y3 + right.y4;
- qreal ex = 3 * (right.x2 - right.x3);
- qreal ey = 3 * (right.y2 - right.y3);
-
- qreal s4 = qAbs(6 * (ey * ax - ex * ay) / qSqrt(ex * ex + ey * ey)) + 0.00001f;
- qreal tf = qPow(qreal(9 * flatness / s4), qreal(1./3.));
- *tMinus = t - (1 - t) * tf;
- *tPlus = t + (1 - t) * tf;
-}
-
-void QBezier::addToPolygonIterative(QPolygonF *p) const
-{
- qreal t1, t2, tcusp;
- qreal t1min, t1plus, t2min, t2plus;
-
- qreal ax = -x1 + 3*x2 - 3*x3 + x4;
- qreal ay = -y1 + 3*y2 - 3*y3 + y4;
- qreal bx = 3*x1 - 6*x2 + 3*x3;
- qreal by = 3*y1 - 6*y2 + 3*y3;
- qreal cx = -3*x1 + 3*x2;
- qreal cy = -3*y1 + 2*y2;
-
- if (findInflections(6 * (ay * bx - ax * by),
- 6 * (ay * cx - ax * cy),
- 2 * (by * cx - bx * cy),
- &t1, &t2, &tcusp)) {
- bindInflectionPoint(*this, t1, &t1min, &t1plus);
- bindInflectionPoint(*this, t2, &t2min, &t2plus);
-
- QBezier tmpBez = *this;
- QBezier left, right, bez1, bez2, bez3;
- if (t1min > 0) {
- if (t1min >= 1) {
- flattenBezierWithoutInflections(tmpBez, p);
- } else {
- splitBezierAt(tmpBez, t1min, &left, &right);
- flattenBezierWithoutInflections(left, p);
- p->append(tmpBez.pointAt(t1min));
-
- if (t2min < t1plus) {
- if (tcusp < 1) {
- p->append(tmpBez.pointAt(tcusp));
- }
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &right);
- flattenBezierWithoutInflections(right, p);
- }
- } else if (t1plus < 1) {
- if (t2min < 1) {
- splitBezierAt(tmpBez, t2min, &bez3, &right);
- splitBezierAt(bez3, t1plus, &left, &bez2);
-
- flattenBezierWithoutInflections(bez2, p);
- p->append(tmpBez.pointAt(t2min));
-
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- } else {
- splitBezierAt(tmpBez, t1plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- }
- }
- } else if (t1plus > 0) {
- p->append(QPointF(x1, y1));
- if (t2min < t1plus) {
- if (tcusp < 1) {
- p->append(tmpBez.pointAt(tcusp));
- }
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- } else if (t1plus < 1) {
- if (t2min < 1) {
- splitBezierAt(tmpBez, t2min, &bez3, &right);
- splitBezierAt(bez3, t1plus, &left, &bez2);
-
- flattenBezierWithoutInflections(bez2, p);
-
- p->append(tmpBez.pointAt(t2min));
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- } else {
- splitBezierAt(tmpBez, t1plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- }
- } else if (t2min > 0) {
- if (t2min < 1) {
- splitBezierAt(tmpBez, t2min, &bez1, &right);
- flattenBezierWithoutInflections(bez1, p);
- p->append(tmpBez.pointAt(t2min));
-
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- } else {
- //### in here we should check whether the area of the
- // triangle formed between pt1/pt2/pt3 is smaller
- // or equal to 0 and then do iterative flattening
- // if not we should fallback and do the recursive
- // flattening.
- flattenBezierWithoutInflections(tmpBez, p);
- }
- } else if (t2plus > 0) {
- p->append(QPointF(x1, y1));
- if (t2plus < 1) {
- splitBezierAt(tmpBez, t2plus, &left, &bez2);
- flattenBezierWithoutInflections(bez2, p);
- }
- } else {
- flattenBezierWithoutInflections(tmpBez, p);
- }
- } else {
- QBezier bez = *this;
- flattenBezierWithoutInflections(bez, p);
- }
-
- p->append(QPointF(x4, y4));
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h
index 846635f..18ec116 100644
--- a/src/gui/painting/qbezier_p.h
+++ b/src/gui/painting/qbezier_p.h
@@ -79,10 +79,9 @@ public:
inline QPointF derivedAt(qreal t) const;
inline QPointF secondDerivedAt(qreal t) const;
- QPolygonF toPolygon() const;
- void addToPolygon(QPolygonF *p) const;
- void addToPolygonIterative(QPolygonF *p) const;
- void addToPolygonMixed(QPolygonF *p) const;
+ QPolygonF toPolygon(qreal bezier_flattening_threshold = 0.5) const;
+ void addToPolygon(QPolygonF *p, qreal bezier_flattening_threshold = 0.5) const;
+
QRectF bounds() const;
qreal length(qreal error = 0.01) const;
void addIfClose(qreal *length, qreal error) const;
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index bc5f1ef..8f8544f 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -60,16 +60,20 @@ QT_BEGIN_NAMESPACE
template <typename Type> class QDataBuffer
{
public:
- QDataBuffer(int res = 64)
+ QDataBuffer(int res)
{
capacity = res;
- buffer = (Type*) qMalloc(capacity * sizeof(Type));
+ if (res)
+ buffer = (Type*) qMalloc(capacity * sizeof(Type));
+ else
+ buffer = 0;
siz = 0;
}
~QDataBuffer()
{
- qFree(buffer);
+ if (buffer)
+ qFree(buffer);
}
inline void reset() { siz = 0; }
@@ -104,6 +108,8 @@ public:
inline void reserve(int size) {
if (size > capacity) {
+ if (capacity == 0)
+ capacity = 1;
while (capacity < size)
capacity *= 2;
buffer = (Type*) qRealloc(buffer, capacity * sizeof(Type));
@@ -112,7 +118,12 @@ public:
inline void shrink(int size) {
capacity = size;
- buffer = (Type*) qRealloc(buffer, capacity * sizeof(Type));
+ if (size)
+ buffer = (Type*) qRealloc(buffer, capacity * sizeof(Type));
+ else {
+ qFree(buffer);
+ buffer = 0;
+ }
}
inline void swap(QDataBuffer<Type> &other) {
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index a62f06b..ef9b18c 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1137,6 +1137,15 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
xTarget.resize(columns + 1);
yTarget.resize(rows + 1);
+ bool oldAA = painter->testRenderHint(QPainter::Antialiasing);
+ bool oldSmooth = painter->testRenderHint(QPainter::SmoothPixmapTransform);
+ if (painter->paintEngine()->type() != QPaintEngine::OpenGL
+ && painter->paintEngine()->type() != QPaintEngine::OpenGL2
+ && (oldSmooth || oldAA) && painter->combinedTransform().type() != QTransform::TxNone) {
+ painter->setRenderHint(QPainter::Antialiasing, false);
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, false);
+ }
+
xTarget[0] = targetRect.left();
xTarget[1] = targetCenterLeft;
xTarget[columns - 1] = targetCenterRight;
@@ -1342,6 +1351,11 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
painter->drawPixmapFragments(opaqueData.data(), opaqueData.size(), pixmap, QPainter::OpaqueHint);
if (translucentData.size())
painter->drawPixmapFragments(translucentData.data(), translucentData.size(), pixmap);
+
+ if (oldAA)
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ if (oldSmooth)
+ painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index ad0c2eb..1b01960 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -154,7 +154,8 @@ QT_FT_Outline *QOutlineMapper::convertPath(const QVectorPath &path)
// ### We can kill this copying and just use the buffer straight...
m_elements.resize(count);
- memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
+ if (count)
+ memcpy(m_elements.data(), path.points(), count* sizeof(QPointF));
m_element_types.resize(0);
}
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index d0ce1a9..39b7593 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -87,8 +87,15 @@ const int QT_RASTER_COORD_LIMIT = 32767;
class QOutlineMapper
{
public:
- QOutlineMapper()
- : m_round_coords(false)
+ QOutlineMapper() :
+ m_element_types(0),
+ m_elements(0),
+ m_elements_dev(0),
+ m_points(0),
+ m_tags(0),
+ m_contours(0),
+ m_polygon_dev(0),
+ m_round_coords(false)
{
}
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 9148ac2..6f395f6 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -251,6 +251,11 @@ static void qt_debug_path(const QPainterPath &path)
}
#endif
+QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
+ QPaintEngineExPrivate(),
+ cachedLines(0)
+{
+}
/*!
@@ -336,17 +341,6 @@ void QRasterPaintEngine::init()
d->hdc = 0;
#endif
- d->rasterPoolSize = 8192;
- d->rasterPoolBase =
-#if defined(Q_WS_WIN64)
- // We make use of setjmp and longjmp in qgrayraster.c which requires
- // 16-byte alignment, hence we hardcode this requirement here..
- (unsigned char *) _aligned_malloc(d->rasterPoolSize, sizeof(void*) * 2);
-#else
- (unsigned char *) malloc(d->rasterPoolSize);
-#endif
- Q_CHECK_PTR(d->rasterPoolBase);
-
// The antialiasing raster.
d->grayRaster.reset(new QT_FT_Raster);
Q_CHECK_PTR(d->grayRaster.data());
@@ -354,8 +348,6 @@ void QRasterPaintEngine::init()
QT_THROW(std::bad_alloc()); // an error creating the raster is caused by a bad malloc
- qt_ft_grays_raster.raster_reset(*d->grayRaster.data(), d->rasterPoolBase, d->rasterPoolSize);
-
d->rasterizer.reset(new QRasterizer);
d->rasterBuffer.reset(new QRasterBuffer());
d->outlineMapper.reset(new QOutlineMapper);
@@ -437,12 +429,6 @@ QRasterPaintEngine::~QRasterPaintEngine()
{
Q_D(QRasterPaintEngine);
-#if defined(Q_WS_WIN64)
- _aligned_free(d->rasterPoolBase);
-#else
- free(d->rasterPoolBase);
-#endif
-
qt_ft_grays_raster.raster_done(*d->grayRaster.data());
}
@@ -4090,6 +4076,22 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
return;
}
+ const int rasterPoolInitialSize = 8192;
+ int rasterPoolSize = rasterPoolInitialSize;
+ unsigned char *rasterPoolBase;
+#if defined(Q_WS_WIN64)
+ rasterPoolBase =
+ // We make use of setjmp and longjmp in qgrayraster.c which requires
+ // 16-byte alignment, hence we hardcode this requirement here..
+ (unsigned char *) _aligned_malloc(rasterPoolSize, sizeof(void*) * 2);
+#else
+ unsigned char rasterPoolOnStack[rasterPoolInitialSize];
+ rasterPoolBase = rasterPoolOnStack;
+#endif
+ Q_CHECK_PTR(rasterPoolBase);
+
+ qt_ft_grays_raster.raster_reset(*grayRaster.data(), rasterPoolBase, rasterPoolSize);
+
void *data = userData;
QT_FT_BBox clip_box = { deviceRect.x(),
@@ -4122,13 +4124,14 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
int new_size = rasterPoolSize * 2;
if (new_size > 1024 * 1024) {
qWarning("QPainter: Rasterization of primitive failed");
- return;
+ break;
}
#if defined(Q_WS_WIN64)
_aligned_free(rasterPoolBase);
#else
- free(rasterPoolBase);
+ if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
+ free(rasterPoolBase);
#endif
rasterPoolSize = new_size;
@@ -4149,6 +4152,13 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
done = true;
}
}
+
+#if defined(Q_WS_WIN64)
+ _aligned_free(rasterPoolBase);
+#else
+ if (rasterPoolBase != rasterPoolOnStack) // initially on the stack
+ free(rasterPoolBase);
+#endif
}
void QRasterPaintEnginePrivate::recalculateFastImages()
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 55eb82e..1016f8d 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -300,6 +300,7 @@ QRasterPaintEnginePrivate : public QPaintEngineExPrivate
{
Q_DECLARE_PUBLIC(QRasterPaintEngine)
public:
+ QRasterPaintEnginePrivate();
void rasterizeLine_dashed(QLineF line, qreal width,
int *dashIndex, qreal *dashOffset, bool *inDash);
@@ -354,8 +355,6 @@ public:
QScopedPointer<QDashStroker> dashStroker;
QScopedPointer<QT_FT_Raster> grayRaster;
- unsigned long rasterPoolSize;
- unsigned char *rasterPoolBase;
QDataBuffer<QLineF> cachedLines;
QSpanData image_filler;
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index da48fcb..aef8b80 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -315,7 +315,7 @@ static Picture getPatternFill(int screen, const QBrush &b)
return X11->pattern_fills[i].picture;
}
// none found, replace one
- int i = rand() % 16;
+ int i = qrand() % 16;
if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) {
XRenderFreePicture (X11->display, X11->pattern_fills[i].picture);
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index a78cafb..ff82d59 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -149,6 +149,7 @@ QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
struct StrokeHandler {
+ StrokeHandler(int reserve) : pts(reserve), types(reserve) {}
QDataBuffer<qreal> pts;
QDataBuffer<QPainterPath::ElementType> types;
};
@@ -394,7 +395,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
return;
if (!d->strokeHandler) {
- d->strokeHandler = new StrokeHandler;
+ d->strokeHandler = new StrokeHandler(path.elementCount()+4);
d->stroker.setMoveToHook(qpaintengineex_moveTo);
d->stroker.setLineToHook(qpaintengineex_lineTo);
d->stroker.setCubicToHook(qpaintengineex_cubicTo);
@@ -460,6 +461,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
// change the current transform. Normal transformed,
// non-cosmetic pens will be transformed as part of fill
// later, so they are also covered here..
+ d->activeStroker->setCurveThresholdFromTransform(state()->matrix);
d->activeStroker->begin(d->strokeHandler);
if (types) {
while (points < lastPoint) {
@@ -517,6 +519,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath());
d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform());
} else {
+ d->activeStroker->setCurveThresholdFromTransform(state()->matrix);
d->activeStroker->begin(d->strokeHandler);
if (types) {
while (points < lastPoint) {
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index c910024..78553c9 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -278,7 +278,8 @@ private:
};
SegmentTree::SegmentTree(QPathSegments &segments)
- : m_segments(segments)
+ : m_segments(segments),
+ m_intersections(0)
{
m_bounds.x1 = qt_inf();
m_bounds.y1 = qt_inf();
@@ -806,7 +807,7 @@ void QWingedEdge::intersectAndAdd()
for (int i = 0; i < m_segments.points(); ++i)
addVertex(m_segments.pointAt(i));
- QDataBuffer<QPathSegments::Intersection> intersections;
+ QDataBuffer<QPathSegments::Intersection> intersections(m_segments.segments());
for (int i = 0; i < m_segments.segments(); ++i) {
intersections.reset();
@@ -857,11 +858,17 @@ void QWingedEdge::intersectAndAdd()
}
}
-QWingedEdge::QWingedEdge()
+QWingedEdge::QWingedEdge() :
+ m_edges(0),
+ m_vertices(0),
+ m_segments(0)
{
}
-QWingedEdge::QWingedEdge(const QPainterPath &subject, const QPainterPath &clip)
+QWingedEdge::QWingedEdge(const QPainterPath &subject, const QPainterPath &clip) :
+ m_edges(subject.length()),
+ m_vertices(subject.length()),
+ m_segments(subject.length())
{
m_segments.setPath(subject);
m_segments.addPath(clip);
@@ -1414,9 +1421,9 @@ bool QPathClipper::intersect()
else if (clipIsRect)
return subjectPath.intersects(r2);
- QPathSegments a;
+ QPathSegments a(subjectPath.length());
a.setPath(subjectPath);
- QPathSegments b;
+ QPathSegments b(clipPath.length());
b.setPath(clipPath);
QIntersectionFinder finder;
@@ -1459,9 +1466,9 @@ bool QPathClipper::contains()
if (clipIsRect)
return subjectPath.contains(r2);
- QPathSegments a;
+ QPathSegments a(subjectPath.length());
a.setPath(subjectPath);
- QPathSegments b;
+ QPathSegments b(clipPath.length());
b.setPath(clipPath);
QIntersectionFinder finder;
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 7962400..fab618d 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -199,7 +199,7 @@ public:
};
- QPathSegments();
+ QPathSegments(int reserve);
void setPath(const QPainterPath &path);
void addPath(const QPainterPath &path);
@@ -345,7 +345,10 @@ inline QPathVertex::operator QPointF() const
return QPointF(x, y);
}
-inline QPathSegments::QPathSegments()
+inline QPathSegments::QPathSegments(int reserve) :
+ m_points(reserve),
+ m_segments(reserve),
+ m_intersections(reserve)
{
}
diff --git a/src/gui/painting/qpolygonclipper_p.h b/src/gui/painting/qpolygonclipper_p.h
index 1b4cbb3..cdaac1c 100644
--- a/src/gui/painting/qpolygonclipper_p.h
+++ b/src/gui/painting/qpolygonclipper_p.h
@@ -62,7 +62,8 @@ QT_BEGIN_NAMESPACE
template <typename InType, typename OutType, typename CastType> class QPolygonClipper
{
public:
- QPolygonClipper()
+ QPolygonClipper() :
+ buffer1(0), buffer2(0)
{
x1 = y1 = x2 = y2 = 0;
}
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index b8bf15e..2955e39 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -931,29 +931,16 @@ void QPdfEnginePrivate::writeHeader()
void QPdfEnginePrivate::writeInfo()
{
info = addXrefEntry(-1);
-
- // The 'text string' type in PDF is encoded either as PDFDocEncoding, or
- // Unicode UTF-16 with a Unicode byte order mark as the first character
- // (0xfeff), with the high-order byte first.
- QByteArray array("<<\n/Title (\xfe\xff");
- const ushort *utf16Title = title.utf16();
- for (int i=0; i < title.size(); ++i) {
- array.append((*(utf16Title + i)) >> 8);
- array.append((*(utf16Title + i)) & 0xff);
- }
- array.append(")\n/Creator (\xfe\xff");
- const ushort *utf16Creator = creator.utf16();
- for (int i=0; i < creator.size(); ++i) {
- array.append((*(utf16Creator + i)) >> 8);
- array.append((*(utf16Creator + i)) & 0xff);
- }
- array.append(")\n/Producer (Qt " QT_VERSION_STR " (C) 2010 Nokia Corporation and/or its subsidiary(-ies))\n");
- write(array);
-
+ xprintf("<<\n/Title ");
+ printString(title);
+ xprintf("\n/Creator ");
+ printString(creator);
+ xprintf("\n/Producer ");
+ printString(QString::fromLatin1("Qt " QT_VERSION_STR " (C) 2010 Nokia Corporation and/or its subsidiary(-ies)"));
QDateTime now = QDateTime::currentDateTime().toUTC();
QTime t = now.time();
QDate d = now.date();
- xprintf("/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
+ xprintf("\n/CreationDate (D:%d%02d%02d%02d%02d%02d)\n",
d.year(),
d.month(),
d.day(),
@@ -1230,6 +1217,25 @@ int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
return object;
}
+void QPdfEnginePrivate::printString(const QString &string) {
+ // The 'text string' type in PDF is encoded either as PDFDocEncoding, or
+ // Unicode UTF-16 with a Unicode byte order mark as the first character
+ // (0xfeff), with the high-order byte first.
+ QByteArray array("(\xfe\xff");
+ const ushort *utf16 = string.utf16();
+
+ for (int i=0; i < string.size(); ++i) {
+ char part[2] = {char((*(utf16 + i)) >> 8), char((*(utf16 + i)) & 0xff)};
+ for(int j=0; j < 2; ++j) {
+ if (part[j] == '(' || part[j] == ')' || part[j] == '\\')
+ array.append('\\');
+ array.append(part[j]);
+ }
+ }
+ array.append(")");
+ write(array);
+}
+
QT_END_NAMESPACE
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprintengine_pdf_p.h b/src/gui/painting/qprintengine_pdf_p.h
index cb6c59d..e0ca56f 100644
--- a/src/gui/painting/qprintengine_pdf_p.h
+++ b/src/gui/painting/qprintengine_pdf_p.h
@@ -170,6 +170,7 @@ private:
void writePage();
int addXrefEntry(int object, bool printostr = true);
+ void printString(const QString &string);
void xprintf(const char* fmt, ...);
inline void write(const QByteArray &data) {
stream->writeRawData(data.constData(), data.size());
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index 51d01c9..f8f8afb 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -198,9 +198,11 @@ public:
};
QScanConverter::QScanConverter()
- : m_alloc(0)
+ : m_lines(0)
+ , m_alloc(0)
, m_size(0)
, m_intersections(0)
+ , m_active(0)
{
}
@@ -310,6 +312,10 @@ struct QBoolToType
template <typename T>
void qScanConvert(QScanConverter &d, T allVertical)
{
+ if (!d.m_lines.size()) {
+ d.m_active.reset();
+ return;
+ }
qSort(d.m_lines.data(), d.m_lines.data() + d.m_lines.size(), QT_PREPEND_NAMESPACE(topOrder));
int line = 0;
for (int y = d.m_lines.first().top; y <= d.m_bottom; ++y) {
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index e43544c..eabbd8a 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -120,8 +120,8 @@ private:
class QSubpathFlatIterator
{
public:
- QSubpathFlatIterator(const QDataBuffer<QStrokerOps::Element> *path)
- : m_path(path), m_pos(0), m_curve_index(-1) { }
+ QSubpathFlatIterator(const QDataBuffer<QStrokerOps::Element> *path, qreal threshold)
+ : m_path(path), m_pos(0), m_curve_index(-1), m_curve_threshold(threshold) { }
inline bool hasNext() const { return m_curve_index >= 0 || m_pos < m_path->size(); }
@@ -152,7 +152,7 @@ public:
QPointF(qt_fixed_to_real(m_path->at(m_pos+1).x),
qt_fixed_to_real(m_path->at(m_pos+1).y)),
QPointF(qt_fixed_to_real(m_path->at(m_pos+2).x),
- qt_fixed_to_real(m_path->at(m_pos+2).y))).toPolygon();
+ qt_fixed_to_real(m_path->at(m_pos+2).y))).toPolygon(m_curve_threshold);
m_curve_index = 1;
e.type = QPainterPath::LineToElement;
e.x = m_curve.at(0).x();
@@ -169,6 +169,7 @@ private:
int m_pos;
QPolygonF m_curve;
int m_curve_index;
+ qreal m_curve_threshold;
};
template <class Iterator> bool qt_stroke_side(Iterator *it, QStroker *stroker,
@@ -187,7 +188,12 @@ static inline qreal adapted_angle_on_x(const QLineF &line)
}
QStrokerOps::QStrokerOps()
- : m_customData(0), m_moveTo(0), m_lineTo(0), m_cubicTo(0)
+ : m_elements(0)
+ , m_curveThreshold(qt_real_to_fixed(0.25))
+ , m_customData(0)
+ , m_moveTo(0)
+ , m_lineTo(0)
+ , m_cubicTo(0)
{
}
@@ -195,7 +201,6 @@ QStrokerOps::~QStrokerOps()
{
}
-
/*!
Prepares the stroker. Call this function once before starting a
stroke by calling moveTo, lineTo or cubicTo.
@@ -238,6 +243,7 @@ void QStrokerOps::strokePath(const QPainterPath &path, void *customData, const Q
if (path.isEmpty())
return;
+ setCurveThresholdFromTransform(matrix);
begin(customData);
int count = path.elementCount();
if (matrix.isIdentity()) {
@@ -308,6 +314,8 @@ void QStrokerOps::strokePolygon(const QPointF *points, int pointCount, bool impl
{
if (!pointCount)
return;
+
+ setCurveThresholdFromTransform(matrix);
begin(data);
if (matrix.isIdentity()) {
moveTo(qt_real_to_fixed(points[0].x()), qt_real_to_fixed(points[0].y()));
@@ -348,6 +356,7 @@ void QStrokerOps::strokeEllipse(const QRectF &rect, void *data, const QTransform
}
}
+ setCurveThresholdFromTransform(matrix);
begin(data);
moveTo(qt_real_to_fixed(start.x()), qt_real_to_fixed(start.y()));
for (int i=0; i<12; i+=3) {
@@ -366,12 +375,10 @@ QStroker::QStroker()
{
m_strokeWidth = qt_real_to_fixed(1);
m_miterLimit = qt_real_to_fixed(2);
- m_curveThreshold = qt_real_to_fixed(0.25);
}
QStroker::~QStroker()
{
-
}
Qt::PenCapStyle QStroker::capForJoinMode(LineJoinMode mode)
@@ -1135,7 +1142,7 @@ void QDashStroker::processCurrentSubpath()
QPainterPath dashPath;
- QSubpathFlatIterator it(&m_elements);
+ QSubpathFlatIterator it(&m_elements, m_curveThreshold);
qfixed2d prev = it.next();
bool clipping = !m_clip_rect.isEmpty();
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index 3e622a8..d646135 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -124,6 +124,9 @@ typedef void (*qStrokerCubicToHook)(qfixed c1x, qfixed c1y,
qfixed ex, qfixed ey,
void *data);
+// qtransform.cpp
+Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
+
class Q_GUI_EXPORT QStrokerOps
{
public:
@@ -161,6 +164,16 @@ public:
QRectF clipRect() const { return m_clip_rect; }
void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
+ void setCurveThresholdFromTransform(const QTransform &transform)
+ {
+ qreal scale;
+ qt_scaleForTransform(transform, &scale);
+ setCurveThreshold(scale == 0 ? qreal(0.5) : (qreal(0.5) / scale));
+ }
+
+ void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
+ qfixed curveThreshold() const { return m_curveThreshold; }
+
protected:
inline void emitMoveTo(qfixed x, qfixed y);
inline void emitLineTo(qfixed x, qfixed y);
@@ -170,6 +183,7 @@ protected:
QDataBuffer<Element> m_elements;
QRectF m_clip_rect;
+ qfixed m_curveThreshold;
void *m_customData;
qStrokerMoveToHook m_moveTo;
@@ -208,9 +222,6 @@ public:
void setMiterLimit(qfixed length) { m_miterLimit = length; }
qfixed miterLimit() const { return m_miterLimit; }
- void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
- qfixed curveThreshold() const { return m_curveThreshold; }
-
void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
inline void emitMoveTo(qfixed x, qfixed y);
inline void emitLineTo(qfixed x, qfixed y);
@@ -227,7 +238,6 @@ protected:
qfixed m_strokeWidth;
qfixed m_miterLimit;
- qfixed m_curveThreshold;
LineJoinMode m_capStyle;
LineJoinMode m_joinStyle;
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 80b7520..aaa241f 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1545,12 +1545,19 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor
return true;
}
+Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
{
// Convert projective xformed curves to line
// segments so they can be transformed more accurately
- QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon();
+
+ qreal scale;
+ qt_scaleForTransform(transform, &scale);
+
+ qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
+
+ QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
for (int i = 0; i < segment.size() - 1; ++i)
if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))