diff options
Diffstat (limited to 'src/gui/painting/qpaintengine_raster.cpp')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 485 |
1 files changed, 170 insertions, 315 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 069c350..74456dd 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -110,10 +110,6 @@ extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // #define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; } #define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; } -#ifdef Q_WS_WIN -static bool qt_enable_16bit_colors = false; -#endif - // #define QT_DEBUG_DRAW #ifdef QT_DEBUG_DRAW void dumpClip(int width, int height, QClipData *clip); @@ -139,7 +135,6 @@ extern bool qt_cleartype_enabled; * Span functions */ static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData); -static void qt_span_fill_clipRegion(int count, const QSpan *spans, void *userData); static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData); static void qt_span_clip(int count, const QSpan *spans, void *userData); static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result); @@ -363,7 +358,8 @@ void QRasterPaintEngine::init() d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to); d->dashStroker = 0; - d->baseClip = 0; + d->baseClip = new QClipData(d->device->height()); + d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height())); d->image_filler.init(d->rasterBuffer, this); d->image_filler.type = QSpanData::Texture; @@ -447,6 +443,8 @@ QRasterPaintEngine::~QRasterPaintEngine() delete d->outlineMapper; delete d->rasterizer; delete d->dashStroker; + + delete d->baseClip; } /*! @@ -483,12 +481,12 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) d->rasterizer->setClipRect(d->deviceRect); s->penData.init(d->rasterBuffer, this); - s->penData.setup(s->pen.brush(), s->intOpacity); + s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode); s->stroker = &d->basicStroker; d->basicStroker.setClipRect(d->deviceRect); s->brushData.init(d->rasterBuffer, this); - s->brushData.setup(s->brush, s->intOpacity); + s->brushData.setup(s->brush, s->intOpacity, s->composition_mode); d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver; @@ -509,16 +507,20 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) if (d->mono_surface) d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono; -#ifdef Q_WS_WIN - else if (qt_cleartype_enabled) { +#if defined(Q_WS_WIN) + else if (qt_cleartype_enabled) +#elif defined (Q_WS_MAC) + else if (true) +#else + else if (false) +#endif + { QImage::Format format = static_cast<QImage *>(d->device)->format(); if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32) d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; else d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; - } -#endif - else + } else d->glyphCacheType = QFontEngineGlyphCache::Raster_A8; setActive(true); @@ -530,19 +532,14 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) */ bool QRasterPaintEngine::end() { - Q_D(QRasterPaintEngine); #ifdef QT_DEBUG_DRAW + Q_D(QRasterPaintEngine); qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect; if (d->baseClip) { dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip); } #endif - if (d->baseClip) { - delete d->baseClip; - d->baseClip = 0; - } - return true; } @@ -618,22 +615,22 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix) d->isPlain45DegreeRotation = false; if (txop >= QTransform::TxRotate) { d->isPlain45DegreeRotation = - (qFuzzyCompare(matrix.m11() + 1, qreal(1)) - && qFuzzyCompare(matrix.m12(), qreal(1)) - && qFuzzyCompare(matrix.m21(), qreal(-1)) - && qFuzzyCompare(matrix.m22() + 1, qreal(1)) + (qFuzzyIsNull(matrix.m11()) + && qFuzzyIsNull(matrix.m12() - qreal(1)) + && qFuzzyIsNull(matrix.m21() + qreal(1)) + && qFuzzyIsNull(matrix.m22()) ) || - (qFuzzyCompare(matrix.m11(), qreal(-1)) - && qFuzzyCompare(matrix.m12() + 1, qreal(1)) - && qFuzzyCompare(matrix.m21() + 1, qreal(1)) - && qFuzzyCompare(matrix.m22(), qreal(-1)) + (qFuzzyIsNull(matrix.m11() + qreal(1)) + && qFuzzyIsNull(matrix.m12()) + && qFuzzyIsNull(matrix.m21()) + && qFuzzyIsNull(matrix.m22() + qreal(1)) ) || - (qFuzzyCompare(matrix.m11() + 1, qreal(1)) - && qFuzzyCompare(matrix.m12(), qreal(-1)) - && qFuzzyCompare(matrix.m21(), qreal(1)) - && qFuzzyCompare(matrix.m22() + 1, qreal(1)) + (qFuzzyIsNull(matrix.m11()) + && qFuzzyIsNull(matrix.m12() + qreal(1)) + && qFuzzyIsNull(matrix.m21() - qreal(1)) + && qFuzzyIsNull(matrix.m22()) ) ; } @@ -769,7 +766,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) s->strokeFlags = 0; s->penData.clip = d->clip(); - s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity); + s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode); if (s->strokeFlags & QRasterPaintEngine::DirtyTransform || pen.brush().transform().type() >= QTransform::TxNone) { @@ -869,7 +866,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush) QRasterPaintEngineState *s = state(); // must set clip prior to setup, as setup uses it... s->brushData.clip = d->clip(); - s->brushData.setup(brush, s->intOpacity); + s->brushData.setup(brush, s->intOpacity, s->composition_mode); if (s->fillFlags & DirtyTransform || brush.transform().type() >= QTransform::TxNone) d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix()); @@ -1024,6 +1021,10 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, { if (alpha == 0 || !clip.isValid()) return; + + if (alpha ==0) + return; + Q_ASSERT(img.depth() >= 8); int srcBPL = img.bytesPerLine(); @@ -1092,11 +1093,10 @@ void QRasterPaintEnginePrivate::systemStateChanged() if (!systemClip.isEmpty()) { QRegion clippedDeviceRgn = systemClip & clipRect; deviceRect = clippedDeviceRgn.boundingRect(); - delete baseClip; - baseClip = new QClipData(device->height()); baseClip->setClipRegion(clippedDeviceRgn); } else { deviceRect = clipRect; + baseClip->setClipRect(deviceRect); } #ifdef QT_DEBUG_DRAW qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip; @@ -1171,6 +1171,25 @@ static void checkClipRatios(QRasterPaintEnginePrivate *d) } #endif +static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s) +{ + if (s->flags.has_clip_ownership) + delete s->clip; + s->clip = 0; + s->flags.has_clip_ownership = false; +} + +static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s) +{ + s->fillFlags |= QPaintEngine::DirtyClipPath; + s->strokeFlags |= QPaintEngine::DirtyClipPath; + s->pixmapFlags |= QPaintEngine::DirtyClipPath; + + d->solid_color_filler.clip = d->clip(); + d->solid_color_filler.adjustSpanMethods(); +} + + /*! \internal */ @@ -1182,12 +1201,12 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) if (path.elements()) { for (int i=0; i<path.elementCount(); ++i) { qDebug() << " - " << path.elements()[i] - << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")"; + << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; } } else { for (int i=0; i<path.elementCount(); ++i) { qDebug() << " ---- " - << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")"; + << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')'; } } #endif @@ -1219,10 +1238,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) } if (op == Qt::NoClip) { - if (s->flags.has_clip_ownership) - delete s->clip; - s->clip = 0; - s->flags.has_clip_ownership = false; + qrasterpaintengine_state_setNoClip(s); } else { QClipData *base = d->baseClip; @@ -1264,17 +1280,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) s->clip = newClip; s->flags.has_clip_ownership = true; } - - s->fillFlags |= DirtyClipPath; - s->strokeFlags |= DirtyClipPath; - s->pixmapFlags |= DirtyClipPath; - - d->solid_color_filler.clip = d->clip(); - d->solid_color_filler.adjustSpanMethods(); - -#ifdef QT_CLIPPING_RATIOS - checkClipRatios(d); -#endif + qrasterpaintengine_dirty_clip(d, s); } @@ -1292,10 +1298,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) QRasterPaintEngineState *s = state(); if (op == Qt::NoClip) { - if (s->flags.has_clip_ownership) - delete s->clip; - s->clip = d->baseClip; - s->flags.has_clip_ownership = false; + qrasterpaintengine_state_setNoClip(s); } else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) { QPaintEngineEx::clip(rect, op); @@ -1341,37 +1344,63 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) return; } } - - s->brushData.clip = d->clip(); - s->penData.clip = d->clip(); - - s->fillFlags |= DirtyClipPath; - s->strokeFlags |= DirtyClipPath; - s->pixmapFlags |= DirtyClipPath; - - d->solid_color_filler.clip = d->clip(); - d->solid_color_filler.adjustSpanMethods(); - - -#ifdef QT_CLIPPING_RATIOS - checkClipRatios(d); -#endif + qrasterpaintengine_dirty_clip(d, s); } + /*! \internal */ void QRasterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) { - QPaintEngineEx::clip(region, op); -} +#ifdef QT_DEBUG_DRAW + qDebug() << "QRasterPaintEngine::clip(): " << region << op; +#endif -/*! - \internal -*/ -void QRasterPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) -{ - QPaintEngineEx::clip(path, op); + Q_D(QRasterPaintEngine); + + if (region.numRects() == 1) { + clip(region.boundingRect(), op); + return; + } + + QRasterPaintEngineState *s = state(); + const QClipData *clip = d->clip(); + const QClipData *baseClip = d->baseClip; + + 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); + } else { + const QClipData *curClip; + QClipData *newClip; + + if (op == Qt::IntersectClip) + curClip = clip; + else + curClip = baseClip; + + if (s->flags.has_clip_ownership) { + newClip = s->clip; + Q_ASSERT(newClip); + } else { + newClip = new QClipData(d->rasterBuffer->height()); + s->clip = newClip; + s->flags.has_clip_ownership = true; + } + + QRegion r = s->matrix.map(region); + if (curClip->hasRectClip) + newClip->setClipRegion(r & curClip->clipRect); + else if (curClip->hasRegionClip) + newClip->setClipRegion(r & clip->clipRegion); + + qrasterpaintengine_dirty_clip(d, s); + } } /*! @@ -1413,7 +1442,7 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, { int x1, x2, y1, y2; - bool rectClipped = false; + bool rectClipped = true; if (data->clip) { x1 = qMax(r.x(), data->clip->xmin); @@ -1643,34 +1672,6 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) QPaintEngineEx::drawRects(rects, rectCount); } -void QRasterPaintEnginePrivate::strokeProjective(const QPainterPath &path) -{ - Q_Q(QRasterPaintEngine); - QRasterPaintEngineState *s = q->state(); - - const QPen &pen = s->lastPen; - QPainterPathStroker pathStroker; - pathStroker.setWidth(pen.width() == 0 ? qreal(1) : pen.width()); - pathStroker.setCapStyle(pen.capStyle()); - pathStroker.setJoinStyle(pen.joinStyle()); - pathStroker.setMiterLimit(pen.miterLimit()); - pathStroker.setDashOffset(pen.dashOffset()); - - if (qpen_style(pen) == Qt::CustomDashLine) - pathStroker.setDashPattern(pen.dashPattern()); - else - pathStroker.setDashPattern(qpen_style(pen)); - - outlineMapper->setMatrix(QTransform()); - const QPainterPath stroke = pen.isCosmetic() - ? pathStroker.createStroke(s->matrix.map(path)) - : s->matrix.map(pathStroker.createStroke(path)); - - rasterize(outlineMapper->convertPath(stroke), s->penData.blend, &s->penData, rasterBuffer); - outlinemapper_xform_dirty = true; -} - - /*! \internal @@ -1735,6 +1736,8 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { + if (path.shape() == QVectorPath::LinesHint) + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -1762,12 +1765,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) static inline QRect toNormalizedFillRect(const QRectF &rect) { - const int x1 = qRound(rect.x() + aliasedCoordinateDelta); - const int y1 = qRound(rect.y() + aliasedCoordinateDelta); - const int x2 = qRound(rect.right() + aliasedCoordinateDelta); - const int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + int x1 = qRound(rect.x() + aliasedCoordinateDelta); + int y1 = qRound(rect.y() + aliasedCoordinateDelta); + int x2 = qRound(rect.right() + aliasedCoordinateDelta); + int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); - return QRect(x1, y1, x2 - x1, y2 - y1).normalized(); + if (x2 < x1) + qSwap(x1, x2); + if (y2 < y1) + qSwap(y1, y2); + + return QRect(x1, y1, x2 - x1, y2 - y1); } /*! @@ -1838,8 +1846,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) } // ### Optimize for non transformed ellipses and rectangles... - QRealRect r = path.controlPointRect(); - QRectF cpRect(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1); + QRectF cpRect = path.controlPointRect(); const QRect deviceRect = s->matrix.mapRect(cpRect).toRect(); ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData); @@ -1927,73 +1934,15 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) QRasterPaintEngineState *s = state(); d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); + if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + && s->composition_mode == QPainter::CompositionMode_SourceOver) { + return; + } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); - fillRect(r, &d->solid_color_filler); } -/*! - \reimp -*/ -void QRasterPaintEngine::drawPath(const QPainterPath &path) -{ -#ifdef QT_DEBUG_DRAW - QRectF bounds = path.boundingRect(); - qDebug(" - QRasterPaintEngine::drawPath(), [%.2f, %.2f, %.2f, %.2f]", - bounds.x(), bounds.y(), bounds.width(), bounds.height()); -#endif - - if (path.isEmpty()) - return; - - // Filling.., - Q_D(QRasterPaintEngine); - QRasterPaintEngineState *s = state(); - - ensureBrush(); - if (s->brushData.blend) { - ensureOutlineMapper(); - fillPath(path, &s->brushData); - } - - // Stroking... - ensurePen(); - if (!s->penData.blend) - return; - { - if (s->matrix.type() >= QTransform::TxProject) { - d->strokeProjective(path); - } else { - Q_ASSERT(s->stroker); - d->outlineMapper->beginOutline(Qt::WindingFill); - qreal txscale = 1; - if (s->pen.isCosmetic() || (qt_scaleForTransform(s->matrix, &txscale) && txscale != 1)) { - const qreal strokeWidth = d->basicStroker.strokeWidth(); - const QRectF clipRect = d->dashStroker ? d->dashStroker->clipRect() : QRectF(); - if (d->dashStroker) - d->dashStroker->setClipRect(d->deviceRect); - d->basicStroker.setStrokeWidth(strokeWidth * txscale); - d->outlineMapper->setMatrix(QTransform()); - s->stroker->strokePath(path, d->outlineMapper, s->matrix); - d->outlinemapper_xform_dirty = true; - d->basicStroker.setStrokeWidth(strokeWidth); - if (d->dashStroker) - d->dashStroker->setClipRect(clipRect); - } else { - ensureOutlineMapper(); - s->stroker->strokePath(path, d->outlineMapper, QTransform()); - } - d->outlineMapper->endOutline(); - - ProcessSpans blend = d->getPenFunc(d->outlineMapper->controlPointRect, - &s->penData); - d->rasterize(d->outlineMapper->outline(), blend, &s->penData, d->rasterBuffer); - } - } - -} - static inline bool isAbove(const QPointF *a, const QPointF *b) { return a->y() < b->y(); @@ -3096,7 +3045,7 @@ bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const if (cl->clipRect == deviceRect) return true; - if (cl->hasRegionClip) { + if (cl->hasRectClip) { // inline contains() for performance (we know the rects are normalized) const QRect &r1 = cl->clipRect; return (r.left() >= r1.left() && r.right() <= r1.right() @@ -3225,7 +3174,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte // ### cases we should delegate painting to the font engine // ### directly... -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) QFontEngine::Type fontEngineType = ti.fontEngine->type(); // qDebug() << "type" << fontEngineType << s->matrix.type(); if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate) @@ -3335,6 +3284,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte break; default: Q_ASSERT(false); + depth = 0; }; for(int i = 0; i < glyphs.size(); i++) { @@ -3362,6 +3312,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte break; default: Q_ASSERT(false); + pitch = 0; }; alphaPenBlt(glyph->data, pitch, depth, @@ -3505,8 +3456,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m22 = int(s->matrix.m22()); int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { const QLine &l = lines[i]; int x1 = l.x1() * m11 + dx; @@ -3605,8 +3556,8 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) ? LineDrawNormal : LineDrawIncludeLastPixel; - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); @@ -4294,7 +4245,7 @@ QClipData::QClipData(int height) clipSpanHeight = height; m_clipLines = 0; - allocated = height; + allocated = 0; m_spans = 0; xmin = xmax = ymin = ymax = 0; count = 0; @@ -4316,8 +4267,11 @@ void QClipData::initialize() if (m_spans) return; - m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); + if (!m_clipLines) + m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight); + m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan)); + allocated = clipSpanHeight; if (hasRectClip) { int y = 0; @@ -4362,6 +4316,7 @@ void QClipData::initialize() int y = 0; int firstInBand = 0; + count = 0; while (firstInBand < numRects) { const int currMinY = rects.at(firstInBand).y(); const int currMaxY = currMinY + rects.at(firstInBand).height(); @@ -4422,20 +4377,37 @@ void QClipData::fixup() ymax = m_spans[count-1].y + 1; xmin = INT_MAX; xmax = 0; + + bool isRect = true; + int left = m_spans[0].x; + int right = m_spans[0].x + m_spans[0].len; + for (int i = 0; i < count; ++i) { -// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage; if (m_spans[i].y != y) { + if (m_spans[i].y != y + 1 && y != -1) { + isRect = false; + } y = m_spans[i].y; m_clipLines[y].spans = m_spans+i; m_clipLines[y].count = 0; // qDebug() << " new line: y=" << y; } ++m_clipLines[y].count; + int sl = (int) m_spans[i].x; + int sr = sl + m_spans[i].len; + xmin = qMin(xmin, (int)m_spans[i].x); xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len); + + if (sl != left || sr != right) + isRect = false; + } +// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : ""); + + if (isRect) { + hasRectClip = true; + clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin); } - ++xmax; -// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d", xmin, xmax, ymin, ymax); } /* @@ -4443,11 +4415,12 @@ void QClipData::fixup() */ void QClipData::setClipRect(const QRect &rect) { - if (rect == clipRect) + if (hasRectClip && rect == clipRect) return; // qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect; hasRectClip = true; + hasRegionClip = false; clipRect = rect; xmin = rect.x(); @@ -4456,7 +4429,7 @@ void QClipData::setClipRect(const QRect &rect) ymax = qMin(rect.y() + rect.height(), clipSpanHeight); if (m_spans) { - delete m_spans; + free(m_spans); m_spans = 0; } @@ -4474,6 +4447,7 @@ void QClipData::setClipRegion(const QRegion ®ion) } hasRegionClip = true; + hasRectClip = false; clipRegion = region; { // set bounding rect @@ -4485,7 +4459,7 @@ void QClipData::setClipRegion(const QRegion ®ion) } if (m_spans) { - delete m_spans; + free(m_spans); m_spans = 0; } @@ -4618,104 +4592,6 @@ static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, return n; } -/* - \internal - Clip spans to \a{clip}-region. - Returns number of unclipped spans -*/ -static int qt_intersect_spans(QT_FT_Span *spans, int numSpans, - int *currSpan, - QT_FT_Span *outSpans, int maxOut, - const QRegion &clip) -{ - const QVector<QRect> rects = clip.rects(); - const int numRects = rects.size(); - - int r = 0; - short miny, minx, maxx, maxy; - { - const QRect &rect = rects[0]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - } - - // TODO: better mapping of currY and startRect - - int n = 0; - int i = *currSpan; - int currY = spans[i].y; - while (i < numSpans) { - - if (spans[i].y != currY && r != 0) { - currY = spans[i].y; - r = 0; - const QRect &rect = rects[r]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - } - - if (spans[i].y < miny) { - ++i; - continue; - } - - if (spans[i].y > maxy || spans[i].x > maxx) { - if (++r >= numRects) { - ++i; - continue; - } - - const QRect &rect = rects[r]; - miny = rect.top(); - minx = rect.left(); - maxx = rect.right(); - maxy = rect.bottom(); - continue; - } - - if (spans[i].x + spans[i].len <= minx) { - ++i; - continue; - } - - outSpans[n].y = spans[i].y; - outSpans[n].coverage = spans[i].coverage; - - if (spans[i].x < minx) { - const ushort cutaway = minx - spans[i].x; - outSpans[n].len = qMin(spans[i].len - cutaway, maxx - minx + 1); - outSpans[n].x = minx; - if (outSpans[n].len == spans[i].len - cutaway) { - ++i; - } else { - // span wider than current rect - spans[i].len -= outSpans[n].len + cutaway; - spans[i].x = maxx + 1; - } - } else { // span starts inside current rect - outSpans[n].x = spans[i].x; - outSpans[n].len = qMin(spans[i].len, - ushort(maxx - spans[i].x + 1)); - if (outSpans[n].len == spans[i].len) { - ++i; - } else { - // span wider than current rect - spans[i].len -= outSpans[n].len; - spans[i].x = maxx + 1; - } - } - - if (++n >= maxOut) - break; - } - - *currSpan = i; - return n; -} static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData) @@ -4733,29 +4609,6 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans, fillData->unclipped_blend(count, spans, fillData); } -static void qt_span_fill_clipRegion(int count, const QSpan *spans, - void *userData) -{ - QSpanData *fillData = reinterpret_cast<QSpanData *>(userData); - Q_ASSERT(fillData->blend && fillData->unclipped_blend); - - Q_ASSERT(fillData->clip); - Q_ASSERT(!fillData->clip->clipRegion.isEmpty()); - - const int NSPANS = 256; - QSpan cspans[NSPANS]; - int currentClip = 0; - while (currentClip < count) { - const int unclipped = qt_intersect_spans(const_cast<QSpan*>(spans), - count, ¤tClip, - &cspans[0], NSPANS, - fillData->clip->clipRegion); - if (unclipped > 0) - fillData->unclipped_blend(unclipped, cspans, fillData); - } - -} - static void qt_span_clip(int count, const QSpan *spans, void *userData) { ClipData *clipData = reinterpret_cast<ClipData *>(userData); @@ -5028,7 +4881,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe) extern QImage qt_imageForBrush(int brushStyle, bool invert); -void QSpanData::setup(const QBrush &brush, int alpha) +void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode) { Qt::BrushStyle brushStyle = qbrush_style(brush); switch (brushStyle) { @@ -5036,6 +4889,10 @@ void QSpanData::setup(const QBrush &brush, int alpha) type = Solid; QColor c = qbrush_color(brush); solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha)); + if ((solid.color & 0xff000000) == 0 + && compositionMode == QPainter::CompositionMode_SourceOver) { + type = None; + } break; } @@ -5176,8 +5033,6 @@ void QSpanData::adjustSpanMethods() blend = unclipped_blend; } else if (clip->hasRectClip) { blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect; - } else if (clip->hasRegionClip) { - blend = clip->clipRegion.isEmpty() ? 0 : qt_span_fill_clipRegion; } else { blend = qt_span_fill_clipped; } @@ -6158,7 +6013,7 @@ void dumpClip(int width, int height, QClipData *clip) int y1 = 0; for (int i = 0; i < clip->count; ++i) { - QSpan *span = clip->spans + i; + QSpan *span = clip->spans() + i; for (int j = 0; j < span->len; ++j) clipImg.setPixel(span->x + j, span->y, 0xffffff00); x0 = qMin(x0, int(span->x)); @@ -6176,7 +6031,7 @@ void dumpClip(int width, int height, QClipData *clip) Q_ASSERT(x1 >= 0); fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1); - clipImg.save(QString(QLatin1String("clip-%0.png")).arg(counter++)); + clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++)); } #endif |