summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting')
-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
12 files changed, 260 insertions, 120 deletions
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}
*/
/*!