30class CapabilitiesToStateMask
33 CapabilitiesToStateMask(QBlittable::Capabilities capabilities)
34 : m_capabilities(capabilities)
38 , alphaFillRectMask(0)
39 , opacityPixmapMask(0)
40 , capabillitiesState(0)
42 if (capabilities & QBlittable::SolidRectCapability)
44 if (capabilities & QBlittable::SourcePixmapCapability)
45 setSourcePixmapMask();
46 if (capabilities & QBlittable::SourceOverPixmapCapability)
47 setSourceOverPixmapMask();
48 if (capabilities & QBlittable::SourceOverScaledPixmapCapability)
49 setSourceOverScaledPixmapMask();
50 if (capabilities & QBlittable::AlphaFillRectCapability)
51 setAlphaFillRectMask();
52 if (capabilities & QBlittable::OpacityPixmapCapability)
53 setOpacityPixmapMask();
56 inline bool canBlitterFillRect()
const
58 return checkStateAgainstMask(capabillitiesState, fillRectMask);
61 inline bool canBlitterAlphaFillRect()
const
63 return checkStateAgainstMask(capabillitiesState, alphaFillRectMask);
66 inline bool canBlitterDrawRectMask()
const
68 return checkStateAgainstMask(capabillitiesState, drawRectMask);
71 bool canBlitterDrawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
const
73 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
75 if (checkStateAgainstMask(capabillitiesState, drawPixmapMask)) {
76 if (m_capabilities & (QBlittable::SourceOverPixmapCapability
77 | QBlittable::SourceOverScaledPixmapCapability)) {
78 if (r.size() != sr.size())
79 return m_capabilities & QBlittable::SourceOverScaledPixmapCapability;
81 return m_capabilities & QBlittable::SourceOverPixmapCapability;
83 if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel())
84 return m_capabilities & QBlittable::SourcePixmapCapability;
89 bool canBlitterDrawPixmapOpacity(
const QPixmap &pm)
const
91 if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
94 return checkStateAgainstMask(capabillitiesState, opacityPixmapMask);
97 bool canBlitterDrawCachedGlyphs(
const QTransform &transform, QFontEngine::GlyphFormat requestedGlyphFormat,
bool complexClip)
const
99 if (transform.type() > QTransform::TxScale)
101 if (!(m_capabilities & QBlittable::DrawScaledCachedGlyphsCapability))
103 if (requestedGlyphFormat == QFontEngine::Format_ARGB && !(m_capabilities & QBlittable::SubPixelGlyphsCapability))
105 if (complexClip && !(m_capabilities & QBlittable::ComplexClipCapability))
110 inline void updateState(uint mask,
bool on) {
111 updateStateBits(&capabillitiesState, mask, on);
116 static inline void updateStateBits(uint *state, uint mask,
bool on)
118 *state = on ? (*state | mask) : (*state & ~mask);
121 static inline bool checkStateAgainstMask(uint state, uint mask)
123 return !state || (state & mask && !(state & ~mask));
126 void setFillRectMask() {
137 updateStateBits(&fillRectMask,
STATE_ALPHA,
false);
144 void setAlphaFillRectMask() {
155 updateStateBits(&alphaFillRectMask,
STATE_ALPHA,
false);
162 void setSourcePixmapMask() {
172 updateStateBits(&drawPixmapMask,
STATE_ALPHA,
false);
179 void setSourceOverPixmapMask() {
180 setSourcePixmapMask();
183 void setSourceOverScaledPixmapMask() {
184 setSourceOverPixmapMask();
188 void setOpacityPixmapMask() {
198 updateStateBits(&opacityPixmapMask,
STATE_ALPHA,
true);
205 QBlittable::Capabilities m_capabilities;
209 uint alphaFillRectMask;
210 uint opacityPixmapMask;
211 uint capabillitiesState;
327 Q_Q(QBlitterPaintEngine);
328 pmData->unmarkRasterOverlay(rect);
329 QRectF targetRect = rect;
331 targetRect = q->state()->matrix.mapRect(rect);
332 const QClipData *clipData = clip();
334 if (clipData->hasRectClip) {
337 pmData->blittable()->alphaFillRect(targetRect & clipData->clipRect, color, q->state()->compositionMode());
339 pmData->blittable()->fillRect(targetRect & clipData->clipRect, color);
340 }
else if (clipData->hasRegionClip) {
341 for (
const QRect &rect : clipData->clipRegion) {
342 QRect intersectRect = rect.intersected(targetRect.toRect());
343 if (!intersectRect.isEmpty()) {
346 pmData->blittable()->alphaFillRect(intersectRect, color, q->state()->compositionMode());
348 pmData->blittable()->fillRect(intersectRect, color);
353 if (targetRect.x() >= 0 && targetRect.y() >= 0
354 && targetRect.width() <= q->paintDevice()->width()
355 && targetRect.height() <= q->paintDevice()->height()) {
358 pmData->blittable()->alphaFillRect(targetRect, color, q->state()->compositionMode());
360 pmData->blittable()->fillRect(targetRect, color);
362 QRectF deviceRect(0, 0, q->paintDevice()->width(), q->paintDevice()->height());
365 pmData->blittable()->alphaFillRect(deviceRect & targetRect, color, q->state()->compositionMode());
367 pmData->blittable()->fillRect(deviceRect & targetRect, color);
373 const QRectF &target,
378 Q_Q(QBlitterPaintEngine);
379 QRectF intersectedRect = clip.intersected(target);
380 if (intersectedRect.isEmpty())
383 if (intersectedRect.size() != target.size()) {
384 if (sr.size() == target.size()) {
386 qreal deltaTop = target.top() - intersectedRect.top();
387 qreal deltaLeft = target.left() - intersectedRect.left();
388 qreal deltaBottom = target.bottom() - intersectedRect.bottom();
389 qreal deltaRight = target.right() - intersectedRect.right();
390 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
393 qreal hFactor = sr.size().width() / target.size().width();
394 qreal vFactor = sr.size().height() / target.size().height();
395 qreal deltaTop = (target.top() - intersectedRect.top()) * vFactor;
396 qreal deltaLeft = (target.left() - intersectedRect.left()) * hFactor;
397 qreal deltaBottom = (target.bottom() - intersectedRect.bottom()) * vFactor;
398 qreal deltaRight = (target.right() - intersectedRect.right()) * hFactor;
399 source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
402 pmData->unmarkRasterOverlay(intersectedRect);
404 pmData->blittable()->drawPixmapOpacity(intersectedRect, pm, source, q->state()->compositionMode(), q->state()->opacity);
406 pmData->blittable()->drawPixmap(intersectedRect, pm, source);
526void QBlitterPaintEngine::fillRect(
const QRectF &rect,
const QBrush &brush)
528 if (rect.size().isEmpty())
531 Q_D(QBlitterPaintEngine);
533 if (qbrush_style(brush) == Qt::SolidPattern
534 && d->caps.canBlitterAlphaFillRect()) {
535 d->fillRect(rect, qbrush_color(brush),
true);
536 }
else if (qbrush_style(brush) == Qt::SolidPattern
537 && qbrush_color(brush).alpha() == 0xff
538 && d->caps.canBlitterFillRect()) {
539 d->fillRect(rect, qbrush_color(brush),
false);
540 }
else if ((brush.style() == Qt::TexturePattern) &&
541 (brush.transform().type() <= QTransform::TxTranslate) &&
542 ((d->caps.canBlitterDrawPixmapOpacity(brush.texture())) ||
543 (d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)))) {
544 bool rectIsFilled =
false;
545 QRectF transformedRect = state()->matrix.mapRect(rect);
546 qreal x = transformedRect.x();
547 qreal y = transformedRect.y();
548 QPixmap pm = brush.texture();
550 int srcX =
int(rect.x() - state()->brushOrigin.x() - brush.transform().dx()) % pm.width();
552 srcX = pm.width() + srcX;
553 const int startX = srcX;
554 int srcY =
int(rect.y() - state()->brushOrigin.y() - brush.transform().dy()) % pm.height();
556 srcY = pm.height() + srcY;
557 while (!rectIsFilled) {
558 qreal blitWidth = (pm.width() ) - srcX;
559 qreal blitHeight = (pm.height() ) - srcY;
560 if (x + blitWidth > transformedRect.right())
561 blitWidth = transformedRect.right() -x;
562 if (y + blitHeight > transformedRect.bottom())
563 blitHeight = transformedRect.bottom() - y;
564 const QClipData *clipData = d->clip();
565 if (clipData->hasRectClip) {
566 QRect targetRect = QRect(x, y, blitWidth, blitHeight).intersected(clipData->clipRect);
567 if (targetRect.isValid()) {
568 int tmpSrcX = srcX + (targetRect.x() - x);
569 int tmpSrcY = srcY + (targetRect.y() - y);
570 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
571 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
573 }
else if (clipData->hasRegionClip) {
574 QRect unclippedTargetRect(x, y, blitWidth, blitHeight);
575 const QRegion targetRegion = clipData->clipRegion.intersected(unclippedTargetRect);
576 for (
const QRect &targetRect : targetRegion) {
577 if (!targetRect.isValid() || targetRect.isEmpty())
579 int tmpSrcX = srcX + (targetRect.x() - x);
580 int tmpSrcY = srcY + (targetRect.y() - y);
581 QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
582 d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
586 if (qFuzzyCompare(x, transformedRect.right())) {
587 x = transformedRect.x();
591 if (qFuzzyCompare(y, transformedRect.bottom()))
598 d->pmData->markRasterOverlay(rect);
599 QRasterPaintEngine::fillRect(rect, brush);
616void QBlitterPaintEngine::drawRects(
const QRectF *rects,
int rectCount)
618 Q_D(QBlitterPaintEngine);
619 if (d->caps.canBlitterDrawRectMask()) {
620 for (
int i = 0; i < rectCount; ++i)
621 d->fillRect(rects[i], qbrush_color(state()->brush),
false);
623 d->pmData->markRasterOverlay(rects, rectCount);
624 QRasterPaintEngine::drawRects(rects, rectCount);
633void QBlitterPaintEngine::drawPixmap(
const QRectF &r,
const QPixmap &pm,
const QRectF &sr)
635 Q_D(QBlitterPaintEngine);
638 canDrawOpacity = d->caps.canBlitterDrawPixmapOpacity(pm);
639 if (canDrawOpacity || (d->caps.canBlitterDrawPixmap(r, pm, sr))) {
642 QRectF targetRect = r;
644 targetRect = state()->matrix.mapRect(r);
645 const QClipData *clipData = d->clip();
647 if (clipData->hasRectClip) {
648 d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity);
649 }
else if (clipData->hasRegionClip) {
650 for (
const QRect &rect : clipData->clipRegion)
651 d->clipAndDrawPixmap(rect, targetRect, pm, sr, canDrawOpacity);
654 QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height());
655 d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr, canDrawOpacity);
659 d->pmData->markRasterOverlay(r);
660 QRasterPaintEngine::drawPixmap(r, pm, sr);
771bool QBlitterPaintEngine::drawCachedGlyphs(
int numGlyphs,
const glyph_t *glyphs,
const QFixedPoint *positions, QFontEngine *fontEngine)
773 Q_D(QBlitterPaintEngine);
774 QFontEngine::GlyphFormat glyphFormat = d->glyphCacheFormat;
775 if (fontEngine->glyphFormat != QFontEngine::Format_None)
776 glyphFormat = fontEngine->glyphFormat;
778 const QClipData *clipData = d->clip();
779 const bool complexClip = clipData && !clipData->hasRectClip;
781 const QPainterState *s = state();
782 if (d->caps.canBlitterDrawCachedGlyphs(s->transform(), glyphFormat, complexClip)) {
784 const bool result = d->pmData->blittable()->drawCachedGlyphs(s, glyphFormat, numGlyphs, glyphs, positions, fontEngine);
789 return QRasterPaintEngine::drawCachedGlyphs(numGlyphs, glyphs, positions, fontEngine);