31class CapabilitiesToStateMask
34 CapabilitiesToStateMask(QBlittable::Capabilities capabilities)
35 : m_capabilities(capabilities)
39 , alphaFillRectMask(0)
40 , opacityPixmapMask(0)
41 , capabillitiesState(0)
43 if (capabilities & QBlittable::SolidRectCapability)
45 if (capabilities & QBlittable::SourcePixmapCapability)
46 setSourcePixmapMask();
47 if (capabilities & QBlittable::SourceOverPixmapCapability)
48 setSourceOverPixmapMask();
49 if (capabilities & QBlittable::SourceOverScaledPixmapCapability)
50 setSourceOverScaledPixmapMask();
51 if (capabilities & QBlittable::AlphaFillRectCapability)
52 setAlphaFillRectMask();
53 if (capabilities & QBlittable::OpacityPixmapCapability)
54 setOpacityPixmapMask();
57 inline bool canBlitterFillRect()
const
59 return checkStateAgainstMask(capabillitiesState, fillRectMask);
62 inline bool canBlitterAlphaFillRect()
const
64 return checkStateAgainstMask(capabillitiesState, alphaFillRectMask);
67 inline bool canBlitterDrawRectMask()
const
69 return checkStateAgainstMask(capabillitiesState, drawRectMask);
72 bool canBlitterDrawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
const
74 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
76 if (checkStateAgainstMask(capabillitiesState, drawPixmapMask)) {
77 if (m_capabilities & (QBlittable::SourceOverPixmapCapability
78 | QBlittable::SourceOverScaledPixmapCapability)) {
79 if (r.size() != sr.size())
80 return m_capabilities & QBlittable::SourceOverScaledPixmapCapability;
82 return m_capabilities & QBlittable::SourceOverPixmapCapability;
84 if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel())
85 return m_capabilities & QBlittable::SourcePixmapCapability;
90 bool canBlitterDrawPixmapOpacity(
const QPixmap &pm)
const
92 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
95 return checkStateAgainstMask(capabillitiesState, opacityPixmapMask);
98 bool canBlitterDrawCachedGlyphs(
const QTransform &transform, QFontEngine::GlyphFormat requestedGlyphFormat,
bool complexClip)
const
100 if (transform.type() > QTransform::TxScale)
102 if (!(m_capabilities & QBlittable::DrawScaledCachedGlyphsCapability))
104 if (requestedGlyphFormat == QFontEngine::Format_ARGB && !(m_capabilities & QBlittable::SubPixelGlyphsCapability))
106 if (complexClip && !(m_capabilities & QBlittable::ComplexClipCapability))
111 inline void updateState(uint mask,
bool on) {
112 updateStateBits(&capabillitiesState, mask, on);
117 static inline void updateStateBits(uint *state, uint mask,
bool on)
119 *state = on ? (*state | mask) : (*state & ~mask);
122 static inline bool checkStateAgainstMask(uint state, uint mask)
124 return !state || (state & mask && !(state & ~mask));
127 void setFillRectMask() {
138 updateStateBits(&fillRectMask,
STATE_ALPHA,
false);
145 void setAlphaFillRectMask() {
156 updateStateBits(&alphaFillRectMask,
STATE_ALPHA,
false);
163 void setSourcePixmapMask() {
173 updateStateBits(&drawPixmapMask,
STATE_ALPHA,
false);
180 void setSourceOverPixmapMask() {
181 setSourcePixmapMask();
184 void setSourceOverScaledPixmapMask() {
185 setSourceOverPixmapMask();
189 void setOpacityPixmapMask() {
199 updateStateBits(&opacityPixmapMask,
STATE_ALPHA,
true);
206 QBlittable::Capabilities m_capabilities;
210 uint alphaFillRectMask;
211 uint opacityPixmapMask;
212 uint capabillitiesState;
328 Q_Q(QBlitterPaintEngine);
329 pmData->unmarkRasterOverlay(rect);
330 QRectF targetRect = rect;
332 targetRect = q->state()->matrix.mapRect(rect);
333 const QClipData *clipData = clip();
335 if (clipData->hasRectClip) {
338 pmData->blittable()->alphaFillRect(targetRect & clipData->clipRect, color, q->state()->compositionMode());
340 pmData->blittable()->fillRect(targetRect & clipData->clipRect, color);
341 }
else if (clipData->hasRegionClip) {
342 for (
const QRect &rect : clipData->clipRegion) {
343 QRect intersectRect = rect.intersected(targetRect.toRect());
344 if (!intersectRect.isEmpty()) {
347 pmData->blittable()->alphaFillRect(intersectRect, color, q->state()->compositionMode());
349 pmData->blittable()->fillRect(intersectRect, color);
354 if (targetRect.x() >= 0 && targetRect.y() >= 0
355 && targetRect.width() <= q->paintDevice()->width()
356 && targetRect.height() <= q->paintDevice()->height()) {
359 pmData->blittable()->alphaFillRect(targetRect, color, q->state()->compositionMode());
361 pmData->blittable()->fillRect(targetRect, color);
363 QRectF deviceRect(0, 0, q->paintDevice()->width(), q->paintDevice()->height());
366 pmData->blittable()->alphaFillRect(deviceRect & targetRect, color, q->state()->compositionMode());
368 pmData->blittable()->fillRect(deviceRect & targetRect, color);
374 const QRectF &target,
379 Q_Q(QBlitterPaintEngine);
380 QRectF intersectedRect = clip.intersected(target);
381 if (intersectedRect.isEmpty())
384 if (intersectedRect.size() != target.size()) {
385 if (sr.size() == target.size()) {
387 qreal deltaTop = target.top() - intersectedRect.top();
388 qreal deltaLeft = target.left() - intersectedRect.left();
389 qreal deltaBottom = target.bottom() - intersectedRect.bottom();
390 qreal deltaRight = target.right() - intersectedRect.right();
391 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
394 qreal hFactor = sr.size().width() / target.size().width();
395 qreal vFactor = sr.size().height() / target.size().height();
396 qreal deltaTop = (target.top() - intersectedRect.top()) * vFactor;
397 qreal deltaLeft = (target.left() - intersectedRect.left()) * hFactor;
398 qreal deltaBottom = (target.bottom() - intersectedRect.bottom()) * vFactor;
399 qreal deltaRight = (target.right() - intersectedRect.right()) * hFactor;
400 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
403 pmData->unmarkRasterOverlay(intersectedRect);
405 pmData->blittable()->drawPixmapOpacity(intersectedRect, pm, source, q->state()->compositionMode(), q->state()->opacity);
407 pmData->blittable()->drawPixmap(intersectedRect, pm, source);
527void QBlitterPaintEngine::fillRect(
const QRectF &rect,
const QBrush &brush)
529 if (rect.size().isEmpty())
532 Q_D(QBlitterPaintEngine);
534 if (qbrush_style(brush) == Qt::SolidPattern
535 && d->caps.canBlitterAlphaFillRect()) {
536 d->fillRect(rect, qbrush_color(brush),
true);
537 }
else if (qbrush_style(brush) == Qt::SolidPattern
538 && qbrush_color(brush).alpha() == 0xff
539 && d->caps.canBlitterFillRect()) {
540 d->fillRect(rect, qbrush_color(brush),
false);
541 }
else if ((brush.style() == Qt::TexturePattern) &&
542 (brush.transform().type() <= QTransform::TxTranslate) &&
543 ((d->caps.canBlitterDrawPixmapOpacity(brush.texture())) ||
544 (d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)))) {
545 bool rectIsFilled =
false;
546 QRectF transformedRect = state()->matrix.mapRect(rect);
547 qreal x = transformedRect.x();
548 qreal y = transformedRect.y();
549 QPixmap pm = brush.texture();
551 int srcX =
int(rect.x() - state()->brushOrigin.x() - brush.transform().dx()) % pm.width();
553 srcX = pm.width() + srcX;
554 const int startX = srcX;
555 int srcY =
int(rect.y() - state()->brushOrigin.y() - brush.transform().dy()) % pm.height();
557 srcY = pm.height() + srcY;
558 while (!rectIsFilled) {
559 qreal blitWidth = (pm.width() ) - srcX;
560 qreal blitHeight = (pm.height() ) - srcY;
561 if (x + blitWidth > transformedRect.right())
562 blitWidth = transformedRect.right() -x;
563 if (y + blitHeight > transformedRect.bottom())
564 blitHeight = transformedRect.bottom() - y;
565 const QClipData *clipData = d->clip();
566 if (clipData->hasRectClip) {
567 QRect targetRect = QRect(x, y, blitWidth, blitHeight).intersected(clipData->clipRect);
568 if (targetRect.isValid()) {
569 int tmpSrcX = srcX + (targetRect.x() - x);
570 int tmpSrcY = srcY + (targetRect.y() - y);
571 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
572 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
574 }
else if (clipData->hasRegionClip) {
575 QRect unclippedTargetRect(x, y, blitWidth, blitHeight);
576 const QRegion targetRegion = clipData->clipRegion.intersected(unclippedTargetRect);
577 for (
const QRect &targetRect : targetRegion) {
578 if (!targetRect.isValid() || targetRect.isEmpty())
580 int tmpSrcX = srcX + (targetRect.x() - x);
581 int tmpSrcY = srcY + (targetRect.y() - y);
582 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
583 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
587 if (qFuzzyCompare(x, transformedRect.right())) {
588 x = transformedRect.x();
592 if (qFuzzyCompare(y, transformedRect.bottom()))
599 d->pmData->markRasterOverlay(rect);
600 QRasterPaintEngine::fillRect(rect, brush);
617void QBlitterPaintEngine::drawRects(
const QRectF *rects,
int rectCount)
619 Q_D(QBlitterPaintEngine);
620 if (d->caps.canBlitterDrawRectMask()) {
621 for (
int i = 0; i < rectCount; ++i)
622 d->fillRect(rects[i], qbrush_color(state()->brush),
false);
624 d->pmData->markRasterOverlay(rects, rectCount);
625 QRasterPaintEngine::drawRects(rects, rectCount);
634void QBlitterPaintEngine::drawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
636 Q_D(QBlitterPaintEngine);
639 canDrawOpacity = d->caps.canBlitterDrawPixmapOpacity(pm);
640 if (canDrawOpacity || (d->caps.canBlitterDrawPixmap(r, pm, sr))) {
643 QRectF targetRect = r;
645 targetRect = state()->matrix.mapRect(r);
646 const QClipData *clipData = d->clip();
648 if (clipData->hasRectClip) {
649 d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity);
650 }
else if (clipData->hasRegionClip) {
651 for (
const QRect &rect : clipData->clipRegion)
652 d->clipAndDrawPixmap(rect, targetRect, pm, sr, canDrawOpacity);
655 QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height());
656 d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr, canDrawOpacity);
660 d->pmData->markRasterOverlay(r);
661 QRasterPaintEngine::drawPixmap(r, pm, sr);
772bool QBlitterPaintEngine::drawCachedGlyphs(
int numGlyphs,
const glyph_t *glyphs,
const QFixedPoint *positions, QFontEngine *fontEngine)
774 Q_D(QBlitterPaintEngine);
775 QFontEngine::GlyphFormat glyphFormat = d->glyphCacheFormat;
776 if (fontEngine->glyphFormat != QFontEngine::Format_None)
777 glyphFormat = fontEngine->glyphFormat;
779 const QClipData *clipData = d->clip();
780 const bool complexClip = clipData && !clipData->hasRectClip;
782 const QPainterState *s = state();
783 if (d->caps.canBlitterDrawCachedGlyphs(s->transform(), glyphFormat, complexClip)) {
785 const bool result = d->pmData->blittable()->drawCachedGlyphs(s, glyphFormat, numGlyphs, glyphs, positions, fontEngine);
790 return QRasterPaintEngine::drawCachedGlyphs(numGlyphs, glyphs, positions, fontEngine);