~gabriel1984sibiu/minitube/qt5.6

« back to all changes in this revision

Viewing changes to src/gui/painting/qpaintengine_blitter.cpp

  • Committer: Grevutiu Gabriel
  • Date: 2017-06-13 08:43:17 UTC
  • Revision ID: gabriel1984sibiu@gmail.com-20170613084317-ek0zqe0u9g3ocvi8
OriginalĀ upstreamĀ code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2016 The Qt Company Ltd.
 
4
** Contact: https://www.qt.io/licensing/
 
5
**
 
6
** This file is part of the QtGui module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and The Qt Company. For licensing terms
 
14
** and conditions see https://www.qt.io/terms-conditions. For further
 
15
** information use the contact form at https://www.qt.io/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 3 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL3 included in the
 
21
** packaging of this file. Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 3 requirements
 
23
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
 
24
**
 
25
** GNU General Public License Usage
 
26
** Alternatively, this file may be used under the terms of the GNU
 
27
** General Public License version 2.0 or (at your option) the GNU General
 
28
** Public license version 3 or any later version approved by the KDE Free
 
29
** Qt Foundation. The licenses are as published by the Free Software
 
30
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
 
31
** included in the packaging of this file. Please review the following
 
32
** information to ensure the GNU General Public License requirements will
 
33
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
 
34
** https://www.gnu.org/licenses/gpl-3.0.html.
 
35
**
 
36
** $QT_END_LICENSE$
 
37
**
 
38
****************************************************************************/
 
39
 
 
40
#include "private/qpaintengine_blitter_p.h"
 
41
 
 
42
#include "private/qblittable_p.h"
 
43
#include "private/qpaintengine_raster_p.h"
 
44
#include "private/qpainter_p.h"
 
45
#include "private/qpixmap_blitter_p.h"
 
46
 
 
47
#ifndef QT_NO_BLITTABLE
 
48
QT_BEGIN_NAMESPACE
 
49
 
 
50
#define STATE_XFORM_SCALE       0x00000001
 
51
#define STATE_XFORM_COMPLEX     0x00000002
 
52
 
 
53
#define STATE_BRUSH_PATTERN     0x00000010
 
54
#define STATE_BRUSH_ALPHA       0x00000020
 
55
 
 
56
#define STATE_PEN_ENABLED       0x00000100
 
57
 
 
58
#define STATE_ANTIALIASING      0x00001000
 
59
#define STATE_ALPHA             0x00002000
 
60
#define STATE_BLENDING_COMPLEX  0x00004000
 
61
 
 
62
#define STATE_CLIPSYS_COMPLEX   0x00010000
 
63
#define STATE_CLIP_COMPLEX      0x00020000
 
64
 
 
65
 
 
66
class CapabilitiesToStateMask
 
67
{
 
68
public:
 
69
    CapabilitiesToStateMask(QBlittable::Capabilities capabilities)
 
70
        : m_capabilities(capabilities)
 
71
        , fillRectMask(0)
 
72
        , drawRectMask(0)
 
73
        , drawPixmapMask(0)
 
74
        , alphaFillRectMask(0)
 
75
        , opacityPixmapMask(0)
 
76
        , capabillitiesState(0)
 
77
    {
 
78
        if (capabilities & QBlittable::SolidRectCapability)
 
79
            setFillRectMask();
 
80
        if (capabilities & QBlittable::SourcePixmapCapability)
 
81
           setSourcePixmapMask();
 
82
        if (capabilities & QBlittable::SourceOverPixmapCapability)
 
83
           setSourceOverPixmapMask();
 
84
        if (capabilities & QBlittable::SourceOverScaledPixmapCapability)
 
85
            setSourceOverScaledPixmapMask();
 
86
        if (capabilities & QBlittable::AlphaFillRectCapability)
 
87
            setAlphaFillRectMask();
 
88
        if (capabilities & QBlittable::OpacityPixmapCapability)
 
89
            setOpacityPixmapMask();
 
90
    }
 
91
 
 
92
    inline bool canBlitterFillRect() const
 
93
    {
 
94
        return checkStateAgainstMask(capabillitiesState, fillRectMask);
 
95
    }
 
96
 
 
97
    inline bool canBlitterAlphaFillRect() const
 
98
    {
 
99
        return checkStateAgainstMask(capabillitiesState, alphaFillRectMask);
 
100
    }
 
101
 
 
102
    inline bool canBlitterDrawRectMask() const
 
103
    {
 
104
        return checkStateAgainstMask(capabillitiesState, drawRectMask);
 
105
    }
 
106
 
 
107
    bool canBlitterDrawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) const
 
108
    {
 
109
        if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
 
110
            return false;
 
111
        if (checkStateAgainstMask(capabillitiesState, drawPixmapMask)) {
 
112
            if (m_capabilities & (QBlittable::SourceOverPixmapCapability
 
113
                                  | QBlittable::SourceOverScaledPixmapCapability)) {
 
114
                if (r.size() != sr.size())
 
115
                    return m_capabilities & QBlittable::SourceOverScaledPixmapCapability;
 
116
                else
 
117
                    return m_capabilities & QBlittable::SourceOverPixmapCapability;
 
118
            }
 
119
            if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel())
 
120
                return m_capabilities & QBlittable::SourcePixmapCapability;
 
121
        }
 
122
        return false;
 
123
    }
 
124
 
 
125
    bool canBlitterDrawPixmapOpacity(const QPixmap &pm) const
 
126
    {
 
127
        if (pm.handle()->classId() != QPlatformPixmap::BlitterClass)
 
128
            return false;
 
129
 
 
130
        return checkStateAgainstMask(capabillitiesState, opacityPixmapMask);
 
131
    }
 
132
 
 
133
    bool canBlitterDrawCachedGlyphs(const QTransform &transform, QFontEngine::GlyphFormat requestedGlyphFormat, bool complexClip) const
 
134
    {
 
135
        if (transform.type() > QTransform::TxScale)
 
136
            return false;
 
137
        if (!(m_capabilities & QBlittable::DrawScaledCachedGlyphsCapability))
 
138
            return false;
 
139
        if (requestedGlyphFormat == QFontEngine::Format_ARGB && !(m_capabilities & QBlittable::SubPixelGlyphsCapability))
 
140
            return false;
 
141
        if (complexClip && !(m_capabilities & QBlittable::ComplexClipCapability))
 
142
            return false;
 
143
        return true;
 
144
    }
 
145
 
 
146
    inline void updateState(uint mask, bool on) {
 
147
        updateStateBits(&capabillitiesState, mask, on);
 
148
    }
 
149
 
 
150
private:
 
151
 
 
152
    static inline void updateStateBits(uint *state, uint mask, bool on)
 
153
    {
 
154
        *state = on ? (*state | mask) : (*state & ~mask);
 
155
    }
 
156
 
 
157
    static inline bool checkStateAgainstMask(uint state, uint mask)
 
158
    {
 
159
        return !state || (state & mask && !(state & ~mask));
 
160
    }
 
161
 
 
162
    void setFillRectMask() {
 
163
        updateStateBits(&fillRectMask, STATE_XFORM_SCALE, false);
 
164
        updateStateBits(&fillRectMask, STATE_XFORM_COMPLEX, false);
 
165
 
 
166
        updateStateBits(&fillRectMask, STATE_BRUSH_PATTERN, false);
 
167
        updateStateBits(&fillRectMask, STATE_BRUSH_ALPHA, false);
 
168
 
 
169
        updateStateBits(&fillRectMask, STATE_PEN_ENABLED, true);
 
170
 
 
171
        //Sub-pixel aliasing should not be sent to the blitter
 
172
        updateStateBits(&fillRectMask, STATE_ANTIALIASING, true);
 
173
        updateStateBits(&fillRectMask, STATE_ALPHA, false);
 
174
        updateStateBits(&fillRectMask, STATE_BLENDING_COMPLEX, false);
 
175
 
 
176
        updateStateBits(&fillRectMask, STATE_CLIPSYS_COMPLEX, false);
 
177
        updateStateBits(&fillRectMask, STATE_CLIP_COMPLEX, false);
 
178
    }
 
179
 
 
180
    void setAlphaFillRectMask() {
 
181
        updateStateBits(&alphaFillRectMask, STATE_XFORM_SCALE, false);
 
182
        updateStateBits(&alphaFillRectMask, STATE_XFORM_COMPLEX, false);
 
183
 
 
184
        updateStateBits(&alphaFillRectMask, STATE_BRUSH_PATTERN, false);
 
185
        updateStateBits(&alphaFillRectMask, STATE_BRUSH_ALPHA, true);
 
186
 
 
187
        updateStateBits(&alphaFillRectMask, STATE_PEN_ENABLED, true);
 
188
 
 
189
        //Sub-pixel aliasing should not be sent to the blitter
 
190
        updateStateBits(&alphaFillRectMask, STATE_ANTIALIASING, true);
 
191
        updateStateBits(&alphaFillRectMask, STATE_ALPHA, false);
 
192
        updateStateBits(&alphaFillRectMask, STATE_BLENDING_COMPLEX, false);
 
193
 
 
194
        updateStateBits(&alphaFillRectMask, STATE_CLIPSYS_COMPLEX, false);
 
195
        updateStateBits(&alphaFillRectMask, STATE_CLIP_COMPLEX, false);
 
196
    }
 
197
 
 
198
    void setSourcePixmapMask() {
 
199
        updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, false);
 
200
        updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false);
 
201
 
 
202
        updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true);
 
203
        updateStateBits(&drawPixmapMask, STATE_BRUSH_ALPHA, false);
 
204
 
 
205
        updateStateBits(&drawPixmapMask, STATE_PEN_ENABLED, true);
 
206
 
 
207
        updateStateBits(&drawPixmapMask, STATE_ANTIALIASING, true);
 
208
        updateStateBits(&drawPixmapMask, STATE_ALPHA, false);
 
209
        updateStateBits(&drawPixmapMask, STATE_BLENDING_COMPLEX, false);
 
210
 
 
211
        updateStateBits(&drawPixmapMask, STATE_CLIPSYS_COMPLEX, false);
 
212
        updateStateBits(&drawPixmapMask, STATE_CLIP_COMPLEX, false);
 
213
    }
 
214
 
 
215
    void setSourceOverPixmapMask() {
 
216
        setSourcePixmapMask();
 
217
    }
 
218
 
 
219
    void setSourceOverScaledPixmapMask() {
 
220
        setSourceOverPixmapMask();
 
221
        updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true);
 
222
    }
 
223
 
 
224
    void setOpacityPixmapMask() {
 
225
        updateStateBits(&opacityPixmapMask, STATE_XFORM_SCALE, true);
 
226
        updateStateBits(&opacityPixmapMask, STATE_XFORM_COMPLEX, false);
 
227
 
 
228
        updateStateBits(&opacityPixmapMask, STATE_BRUSH_PATTERN, true);
 
229
        updateStateBits(&opacityPixmapMask, STATE_BRUSH_ALPHA, true);
 
230
 
 
231
        updateStateBits(&opacityPixmapMask, STATE_PEN_ENABLED, true);
 
232
 
 
233
        updateStateBits(&opacityPixmapMask, STATE_ANTIALIASING, true);
 
234
        updateStateBits(&opacityPixmapMask, STATE_ALPHA, true);
 
235
        updateStateBits(&opacityPixmapMask, STATE_BLENDING_COMPLEX, false);
 
236
 
 
237
        updateStateBits(&opacityPixmapMask, STATE_CLIPSYS_COMPLEX, false);
 
238
        updateStateBits(&opacityPixmapMask, STATE_CLIP_COMPLEX, false);
 
239
    }
 
240
 
 
241
    QBlittable::Capabilities m_capabilities;
 
242
    uint fillRectMask;
 
243
    uint drawRectMask;
 
244
    uint drawPixmapMask;
 
245
    uint alphaFillRectMask;
 
246
    uint opacityPixmapMask;
 
247
    uint capabillitiesState;
 
248
};
 
249
 
 
250
class QBlitterPaintEnginePrivate : public QRasterPaintEnginePrivate
 
251
{
 
252
    Q_DECLARE_PUBLIC(QBlitterPaintEngine)
 
253
public:
 
254
    QBlitterPaintEnginePrivate(QBlittablePlatformPixmap *p)
 
255
        : QRasterPaintEnginePrivate()
 
256
        , pmData(p)
 
257
        , caps(pmData->blittable()->capabilities())
 
258
        , hasXForm(false)
 
259
 
 
260
    {}
 
261
 
 
262
    void lock();
 
263
    void unlock();
 
264
    void fillRect(const QRectF &rect, const QColor &color, bool alpha);
 
265
    void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr, bool opacity);
 
266
 
 
267
 
 
268
    void updateCompleteState(QPainterState *s);
 
269
    void updatePenState(QPainterState *s);
 
270
    void updateBrushState(QPainterState *s);
 
271
    void updateOpacityState(QPainterState *s);
 
272
    void updateCompositionModeState(QPainterState *s);
 
273
    void updateRenderHintsState(QPainterState *s);
 
274
    void updateTransformState(QPainterState *s);
 
275
    void updateClipState(QPainterState *s);
 
276
 
 
277
    QBlittablePlatformPixmap *pmData;
 
278
    CapabilitiesToStateMask caps;
 
279
    uint hasXForm;
 
280
};
 
281
 
 
282
 
 
283
inline void QBlitterPaintEnginePrivate::lock()
 
284
{
 
285
    if (!pmData->blittable()->isLocked())
 
286
        rasterBuffer->prepare(pmData->buffer());
 
287
}
 
288
 
 
289
inline void QBlitterPaintEnginePrivate::unlock()
 
290
{
 
291
    pmData->blittable()->unlock();
 
292
}
 
293
 
 
294
// State tracking to make decisions
 
295
void QBlitterPaintEnginePrivate::updateCompleteState(QPainterState *s)
 
296
{
 
297
    updatePenState(s);
 
298
    updateBrushState(s);
 
299
    updateOpacityState(s);
 
300
    updateCompositionModeState(s);
 
301
    updateRenderHintsState(s);
 
302
    updateTransformState(s);
 
303
    updateClipState(s);
 
304
}
 
305
 
 
306
void QBlitterPaintEnginePrivate::updatePenState(QPainterState *s)
 
307
{
 
308
    caps.updateState(STATE_PEN_ENABLED, qpen_style(s->pen) != Qt::NoPen);
 
309
}
 
310
 
 
311
void QBlitterPaintEnginePrivate::updateBrushState(QPainterState *s)
 
312
{
 
313
    Qt::BrushStyle style = qbrush_style(s->brush);
 
314
 
 
315
    caps.updateState(STATE_BRUSH_PATTERN, style > Qt::SolidPattern);
 
316
    caps.updateState(STATE_BRUSH_ALPHA,
 
317
                        qbrush_color(s->brush).alpha() < 255);
 
318
}
 
319
 
 
320
void QBlitterPaintEnginePrivate::updateOpacityState(QPainterState *s)
 
321
{
 
322
    bool translucent = s->opacity < 1;
 
323
    caps.updateState(STATE_ALPHA, translucent);
 
324
}
 
325
 
 
326
void QBlitterPaintEnginePrivate::updateCompositionModeState(QPainterState *s)
 
327
{
 
328
    bool nonTrivial = s->composition_mode != QPainter::CompositionMode_SourceOver
 
329
                      && s->composition_mode != QPainter::CompositionMode_Source;
 
330
 
 
331
    caps.updateState(STATE_BLENDING_COMPLEX, nonTrivial);
 
332
}
 
333
 
 
334
void QBlitterPaintEnginePrivate::updateRenderHintsState(QPainterState *s)
 
335
{
 
336
    bool aa = s->renderHints & QPainter::Antialiasing;
 
337
    caps.updateState(STATE_ANTIALIASING, aa);
 
338
}
 
339
 
 
340
void QBlitterPaintEnginePrivate::updateTransformState(QPainterState *s)
 
341
{
 
342
    QTransform::TransformationType type = s->matrix.type();
 
343
 
 
344
    // consider scaling operations with a negative factor as "complex" for now.
 
345
    // as some blitters could handle axisymmetrical operations, we should improve blitter
 
346
    // paint engine to handle them as a capability
 
347
    caps.updateState(STATE_XFORM_COMPLEX, (type > QTransform::TxScale) ||
 
348
        ((type == QTransform::TxScale) && ((s->matrix.m11() < 0.0) || (s->matrix.m22() < 0.0))));
 
349
    caps.updateState(STATE_XFORM_SCALE, type > QTransform::TxTranslate);
 
350
 
 
351
    hasXForm = type >= QTransform::TxTranslate;
 
352
}
 
353
 
 
354
void QBlitterPaintEnginePrivate::updateClipState(QPainterState *)
 
355
{
 
356
    const QClipData *clipData = clip();
 
357
    bool complexClip = clipData && !(clipData->hasRectClip || clipData->hasRegionClip);
 
358
    caps.updateState(STATE_CLIP_COMPLEX, complexClip);
 
359
}
 
360
 
 
361
void QBlitterPaintEnginePrivate::fillRect(const QRectF &rect, const QColor &color, bool alpha)
 
362
{
 
363
    Q_Q(QBlitterPaintEngine);
 
364
    pmData->unmarkRasterOverlay(rect);
 
365
    QRectF targetRect = rect;
 
366
    if (hasXForm)
 
367
        targetRect = q->state()->matrix.mapRect(rect);
 
368
    const QClipData *clipData = clip();
 
369
    if (clipData) {
 
370
        if (clipData->hasRectClip) {
 
371
            unlock();
 
372
            if (alpha)
 
373
                pmData->blittable()->alphaFillRect(targetRect & clipData->clipRect, color, q->state()->compositionMode());
 
374
            else
 
375
                pmData->blittable()->fillRect(targetRect & clipData->clipRect, color);
 
376
        } else if (clipData->hasRegionClip) {
 
377
            QVector<QRect> rects = clipData->clipRegion.rects();
 
378
            for (int i = 0; i < rects.size(); ++i) {
 
379
                QRect intersectRect = rects.at(i).intersected(targetRect.toRect());
 
380
                if (!intersectRect.isEmpty()) {
 
381
                    unlock();
 
382
                    if (alpha)
 
383
                        pmData->blittable()->alphaFillRect(intersectRect, color, q->state()->compositionMode());
 
384
                    else
 
385
                        pmData->blittable()->fillRect(intersectRect, color);
 
386
                }
 
387
            }
 
388
        }
 
389
    } else {
 
390
        if (targetRect.x() >= 0 && targetRect.y() >= 0
 
391
            && targetRect.width() <= q->paintDevice()->width()
 
392
            && targetRect.height() <= q->paintDevice()->height()) {
 
393
            unlock();
 
394
            if (alpha)
 
395
                pmData->blittable()->alphaFillRect(targetRect, color, q->state()->compositionMode());
 
396
            else
 
397
                pmData->blittable()->fillRect(targetRect, color);
 
398
        } else {
 
399
            QRectF deviceRect(0, 0, q->paintDevice()->width(), q->paintDevice()->height());
 
400
            unlock();
 
401
            if (alpha)
 
402
                pmData->blittable()->alphaFillRect(deviceRect & targetRect, color, q->state()->compositionMode());
 
403
            else
 
404
                pmData->blittable()->fillRect(deviceRect & targetRect, color);
 
405
        }
 
406
    }
 
407
}
 
408
 
 
409
void QBlitterPaintEnginePrivate::clipAndDrawPixmap(const QRectF &clip,
 
410
                                                   const QRectF &target,
 
411
                                                   const QPixmap &pm,
 
412
                                                   const QRectF &sr,
 
413
                                                   bool  opacity)
 
414
{
 
415
    Q_Q(QBlitterPaintEngine);
 
416
    QRectF intersectedRect = clip.intersected(target);
 
417
    if (intersectedRect.isEmpty())
 
418
        return;
 
419
    QRectF source = sr;
 
420
    if (intersectedRect.size() != target.size()) {
 
421
        if (sr.size() == target.size()) {
 
422
            // no resize
 
423
            qreal deltaTop = target.top() - intersectedRect.top();
 
424
            qreal deltaLeft = target.left() - intersectedRect.left();
 
425
            qreal deltaBottom = target.bottom() - intersectedRect.bottom();
 
426
            qreal deltaRight = target.right() - intersectedRect.right();
 
427
            source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
 
428
        } else {
 
429
            // resize case
 
430
            qreal hFactor = sr.size().width() / target.size().width();
 
431
            qreal vFactor = sr.size().height() / target.size().height();
 
432
            qreal deltaTop = (target.top() - intersectedRect.top()) * vFactor;
 
433
            qreal deltaLeft = (target.left() - intersectedRect.left()) * hFactor;
 
434
            qreal deltaBottom = (target.bottom() - intersectedRect.bottom()) * vFactor;
 
435
            qreal deltaRight = (target.right() - intersectedRect.right()) * hFactor;
 
436
            source.adjust(-deltaLeft, -deltaTop, -deltaRight, -deltaBottom);
 
437
        }
 
438
    }
 
439
    pmData->unmarkRasterOverlay(intersectedRect);
 
440
    if (opacity)
 
441
        pmData->blittable()->drawPixmapOpacity(intersectedRect, pm, source, q->state()->compositionMode(), q->state()->opacity);
 
442
    else
 
443
        pmData->blittable()->drawPixmap(intersectedRect, pm, source);
 
444
}
 
445
 
 
446
QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePlatformPixmap *p)
 
447
    : QRasterPaintEngine(*(new QBlitterPaintEnginePrivate(p)), p->buffer())
 
448
{}
 
449
 
 
450
// State tracking
 
451
void QBlitterPaintEngine::penChanged()
 
452
{
 
453
    Q_D(QBlitterPaintEngine);
 
454
 
 
455
    QRasterPaintEngine::penChanged();
 
456
    d->updatePenState(state());
 
457
}
 
458
 
 
459
void QBlitterPaintEngine::brushChanged()
 
460
{
 
461
    Q_D(QBlitterPaintEngine);
 
462
 
 
463
    QRasterPaintEngine::brushChanged();
 
464
    d->updateBrushState(state());
 
465
}
 
466
 
 
467
void QBlitterPaintEngine::opacityChanged()
 
468
{
 
469
    Q_D(QBlitterPaintEngine);
 
470
 
 
471
    QRasterPaintEngine::opacityChanged();
 
472
    d->updateOpacityState(state());
 
473
}
 
474
 
 
475
void QBlitterPaintEngine::compositionModeChanged()
 
476
{
 
477
    Q_D(QBlitterPaintEngine);
 
478
 
 
479
    QRasterPaintEngine::compositionModeChanged();
 
480
    d->updateCompositionModeState(state());
 
481
}
 
482
 
 
483
void QBlitterPaintEngine::renderHintsChanged()
 
484
{
 
485
    Q_D(QBlitterPaintEngine);
 
486
 
 
487
    QRasterPaintEngine::renderHintsChanged();
 
488
    d->updateRenderHintsState(state());
 
489
}
 
490
 
 
491
void QBlitterPaintEngine::transformChanged()
 
492
{
 
493
    Q_D(QBlitterPaintEngine);
 
494
 
 
495
    QRasterPaintEngine::transformChanged();
 
496
    d->updateTransformState(state());
 
497
}
 
498
 
 
499
void QBlitterPaintEngine::clipEnabledChanged()
 
500
{
 
501
    Q_D(QBlitterPaintEngine);
 
502
    QRasterPaintEngine::clipEnabledChanged();
 
503
    d->updateClipState(state());
 
504
}
 
505
 
 
506
bool QBlitterPaintEngine::begin(QPaintDevice *pdev)
 
507
{
 
508
    Q_D(QBlitterPaintEngine);
 
509
    bool ok = QRasterPaintEngine::begin(pdev);
 
510
#ifdef QT_BLITTER_RASTEROVERLAY
 
511
    d->pmData->unmergeOverlay();
 
512
#endif
 
513
    d->pdev = pdev;
 
514
    return ok;
 
515
}
 
516
 
 
517
bool QBlitterPaintEngine::end()
 
518
{
 
519
#ifdef QT_BLITTER_RASTEROVERLAY
 
520
    Q_D(QBlitterPaintEngine);
 
521
    d->pmData->mergeOverlay();
 
522
#endif
 
523
 
 
524
    return QRasterPaintEngine::end();
 
525
}
 
526
 
 
527
void QBlitterPaintEngine::setState(QPainterState *s)
 
528
{
 
529
    Q_D(QBlitterPaintEngine);
 
530
 
 
531
    QRasterPaintEngine::setState(s);
 
532
    d->updateCompleteState(s);
 
533
}
 
534
 
 
535
// Accelerated paths
 
536
void QBlitterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
 
537
{
 
538
    Q_D(QBlitterPaintEngine);
 
539
    if (path.shape() == QVectorPath::RectangleHint) {
 
540
        QRectF rect(((const QPointF *) path.points())[0], ((const QPointF *) path.points())[2]);
 
541
        fillRect(rect, brush);
 
542
    } else {
 
543
        d->lock();
 
544
        d->pmData->markRasterOverlay(path);
 
545
        QRasterPaintEngine::fill(path, brush);
 
546
    }
 
547
}
 
548
 
 
549
void QBlitterPaintEngine::fillRect(const QRectF &rect, const QColor &color)
 
550
{
 
551
    Q_D(QBlitterPaintEngine);
 
552
    if (d->caps.canBlitterAlphaFillRect()) {
 
553
        d->fillRect(rect, color, true);
 
554
    } else if (d->caps.canBlitterFillRect() && color.alpha() == 0xff) {
 
555
        d->fillRect(rect, color, false);
 
556
    } else {
 
557
        d->lock();
 
558
        d->pmData->markRasterOverlay(rect);
 
559
        QRasterPaintEngine::fillRect(rect, color);
 
560
    }
 
561
}
 
562
 
 
563
void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
 
564
{
 
565
    if (rect.size().isEmpty())
 
566
        return;
 
567
 
 
568
    Q_D(QBlitterPaintEngine);
 
569
 
 
570
    if (qbrush_style(brush) == Qt::SolidPattern
 
571
        && d->caps.canBlitterAlphaFillRect()) {
 
572
        d->fillRect(rect, qbrush_color(brush), true);
 
573
    } else if (qbrush_style(brush) == Qt::SolidPattern
 
574
        && qbrush_color(brush).alpha() == 0xff
 
575
        && d->caps.canBlitterFillRect()) {
 
576
        d->fillRect(rect, qbrush_color(brush), false);
 
577
    } else if ((brush.style() == Qt::TexturePattern) &&
 
578
               (brush.transform().type() <= QTransform::TxTranslate) &&
 
579
                ((d->caps.canBlitterDrawPixmapOpacity(brush.texture())) ||
 
580
                 (d->caps.canBlitterDrawPixmap(rect, brush.texture(), rect)))) {
 
581
        bool rectIsFilled = false;
 
582
        QRectF transformedRect = state()->matrix.mapRect(rect);
 
583
        qreal x = transformedRect.x();
 
584
        qreal y = transformedRect.y();
 
585
        QPixmap pm = brush.texture();
 
586
        d->unlock();
 
587
        int srcX = int(rect.x() - state()->brushOrigin.x() - brush.transform().dx()) % pm.width();
 
588
        if (srcX < 0)
 
589
            srcX = pm.width() + srcX;
 
590
        const int startX = srcX;
 
591
        int srcY = int(rect.y() - state()->brushOrigin.y() - brush.transform().dy()) % pm.height();
 
592
        if (srcY < 0)
 
593
            srcY = pm.height() + srcY;
 
594
        while (!rectIsFilled) {
 
595
            qreal blitWidth = (pm.width() ) - srcX;
 
596
            qreal blitHeight = (pm.height() ) - srcY;
 
597
            if (x + blitWidth > transformedRect.right())
 
598
                blitWidth = transformedRect.right() -x;
 
599
            if (y + blitHeight > transformedRect.bottom())
 
600
                blitHeight = transformedRect.bottom() - y;
 
601
            const QClipData *clipData = d->clip();
 
602
            if (clipData->hasRectClip) {
 
603
                QRect targetRect = QRect(x, y, blitWidth, blitHeight).intersected(clipData->clipRect);
 
604
                if (targetRect.isValid()) {
 
605
                    int tmpSrcX  = srcX + (targetRect.x() - x);
 
606
                    int tmpSrcY = srcY + (targetRect.y() - y);
 
607
                    QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
 
608
                    d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
 
609
                }
 
610
            } else if (clipData->hasRegionClip) {
 
611
                QRect unclippedTargetRect(x, y, blitWidth, blitHeight);
 
612
                const QVector<QRect> intersectedRects = clipData->clipRegion.intersected(unclippedTargetRect).rects();
 
613
                const int intersectedSize = intersectedRects.size();
 
614
                for (int i = 0; i < intersectedSize; ++i) {
 
615
                    const QRect &targetRect = intersectedRects.at(i);
 
616
                    if (!targetRect.isValid() || targetRect.isEmpty())
 
617
                        continue;
 
618
                    int tmpSrcX = srcX + (targetRect.x() - x);
 
619
                    int tmpSrcY = srcY + (targetRect.y() - y);
 
620
                    QRect srcRect(tmpSrcX, tmpSrcY, targetRect.width(), targetRect.height());
 
621
                    d->pmData->blittable()->drawPixmap(targetRect, pm, srcRect);
 
622
                }
 
623
            }
 
624
            x+=blitWidth;
 
625
            if (qFuzzyCompare(x, transformedRect.right())) {
 
626
                x = transformedRect.x();
 
627
                srcX = startX;
 
628
                srcY = 0;
 
629
                y += blitHeight;
 
630
                if (qFuzzyCompare(y, transformedRect.bottom()))
 
631
                    rectIsFilled = true;
 
632
            } else
 
633
                srcX = 0;
 
634
        }
 
635
    } else {
 
636
        d->lock();
 
637
        d->pmData->markRasterOverlay(rect);
 
638
        QRasterPaintEngine::fillRect(rect, brush);
 
639
    }
 
640
 
 
641
}
 
642
 
 
643
void QBlitterPaintEngine::drawRects(const QRect *rects, int rectCount)
 
644
{
 
645
    Q_D(QBlitterPaintEngine);
 
646
    if (d->caps.canBlitterDrawRectMask()) {
 
647
        for (int i=0; i<rectCount; ++i)
 
648
            d->fillRect(rects[i], qbrush_color(state()->brush), false);
 
649
    } else {
 
650
        d->pmData->markRasterOverlay(rects, rectCount);
 
651
        QRasterPaintEngine::drawRects(rects, rectCount);
 
652
    }
 
653
}
 
654
 
 
655
void QBlitterPaintEngine::drawRects(const QRectF *rects, int rectCount)
 
656
{
 
657
    Q_D(QBlitterPaintEngine);
 
658
    if (d->caps.canBlitterDrawRectMask()) {
 
659
        for (int i = 0; i < rectCount; ++i)
 
660
            d->fillRect(rects[i], qbrush_color(state()->brush), false);
 
661
    } else {
 
662
        d->pmData->markRasterOverlay(rects, rectCount);
 
663
        QRasterPaintEngine::drawRects(rects, rectCount);
 
664
    }
 
665
}
 
666
 
 
667
void QBlitterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pm)
 
668
{
 
669
    drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
 
670
}
 
671
 
 
672
void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
 
673
{
 
674
    Q_D(QBlitterPaintEngine);
 
675
    bool canDrawOpacity;
 
676
 
 
677
    canDrawOpacity = d->caps.canBlitterDrawPixmapOpacity(pm);
 
678
    if (canDrawOpacity || (d->caps.canBlitterDrawPixmap(r, pm, sr))) {
 
679
 
 
680
        d->unlock();
 
681
        QRectF targetRect = r;
 
682
        if (d->hasXForm)
 
683
            targetRect = state()->matrix.mapRect(r);
 
684
        const QClipData *clipData = d->clip();
 
685
        if (clipData) {
 
686
            if (clipData->hasRectClip) {
 
687
                d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity);
 
688
            } else if (clipData->hasRegionClip) {
 
689
                QVector<QRect>rects = clipData->clipRegion.rects();
 
690
                for (int i = 0; i<rects.size(); ++i)
 
691
                    d->clipAndDrawPixmap(rects.at(i), targetRect, pm, sr, canDrawOpacity);
 
692
            }
 
693
        } else {
 
694
            QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height());
 
695
            d->clipAndDrawPixmap(deviceRect, targetRect, pm, sr, canDrawOpacity);
 
696
        }
 
697
    }else {
 
698
        d->lock();
 
699
        d->pmData->markRasterOverlay(r);
 
700
        QRasterPaintEngine::drawPixmap(r, pm, sr);
 
701
    }
 
702
}
 
703
 
 
704
// Overridden methods to lock the graphics memory
 
705
void QBlitterPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
 
706
{
 
707
    Q_D(QBlitterPaintEngine);
 
708
    d->lock();
 
709
    d->pmData->markRasterOverlay(points, pointCount);
 
710
    QRasterPaintEngine::drawPolygon(points, pointCount, mode);
 
711
}
 
712
 
 
713
void QBlitterPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
 
714
{
 
715
    Q_D(QBlitterPaintEngine);
 
716
    d->lock();
 
717
    d->pmData->markRasterOverlay(points, pointCount);
 
718
    QRasterPaintEngine::drawPolygon(points, pointCount, mode);
 
719
}
 
720
 
 
721
void QBlitterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData)
 
722
{
 
723
    Q_D(QBlitterPaintEngine);
 
724
    d->lock();
 
725
    d->pmData->markRasterOverlay(path);
 
726
    QRasterPaintEngine::fillPath(path, fillData);
 
727
}
 
728
 
 
729
void QBlitterPaintEngine::fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
 
730
{
 
731
    Q_D(QBlitterPaintEngine);
 
732
    d->lock();
 
733
    d->pmData->markRasterOverlay(points, pointCount);
 
734
    QRasterPaintEngine::fillPolygon(points, pointCount, mode);
 
735
}
 
736
 
 
737
void QBlitterPaintEngine::drawEllipse(const QRectF &r)
 
738
{
 
739
    Q_D(QBlitterPaintEngine);
 
740
    d->lock();
 
741
    d->pmData->markRasterOverlay(r);
 
742
    QRasterPaintEngine::drawEllipse(r);
 
743
}
 
744
 
 
745
void QBlitterPaintEngine::drawImage(const QPointF &pos, const QImage &image)
 
746
{
 
747
    drawImage(QRectF(pos, image.size()), image, image.rect());
 
748
}
 
749
 
 
750
void QBlitterPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
 
751
                                    Qt::ImageConversionFlags flags)
 
752
{
 
753
    Q_D(QBlitterPaintEngine);
 
754
    d->lock();
 
755
    d->pmData->markRasterOverlay(r);
 
756
    QRasterPaintEngine::drawImage(r, pm, sr, flags);
 
757
}
 
758
 
 
759
void QBlitterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr)
 
760
{
 
761
    Q_D(QBlitterPaintEngine);
 
762
    d->lock();
 
763
    d->pmData->markRasterOverlay(r);
 
764
    QRasterPaintEngine::drawTiledPixmap(r, pm, sr);
 
765
}
 
766
 
 
767
void QBlitterPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &ti)
 
768
{
 
769
    Q_D(QBlitterPaintEngine);
 
770
    d->lock();
 
771
    d->pmData->markRasterOverlay(pos, ti);
 
772
    QRasterPaintEngine::drawTextItem(pos, ti);
 
773
}
 
774
 
 
775
void QBlitterPaintEngine::drawPoints(const QPointF *points, int pointCount)
 
776
{
 
777
    Q_D(QBlitterPaintEngine);
 
778
    d->lock();
 
779
    d->pmData->markRasterOverlay(points, pointCount);
 
780
    QRasterPaintEngine::drawPoints(points, pointCount);
 
781
}
 
782
 
 
783
void QBlitterPaintEngine::drawPoints(const QPoint *points, int pointCount)
 
784
{
 
785
    Q_D(QBlitterPaintEngine);
 
786
    d->lock();
 
787
    d->pmData->markRasterOverlay(points, pointCount);
 
788
    QRasterPaintEngine::drawPoints(points, pointCount);
 
789
}
 
790
 
 
791
void QBlitterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
 
792
{
 
793
    Q_D(QBlitterPaintEngine);
 
794
    d->lock();
 
795
    d->pmData->markRasterOverlay(path);
 
796
    QRasterPaintEngine::stroke(path, pen);
 
797
}
 
798
 
 
799
void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti)
 
800
{
 
801
    Q_D(QBlitterPaintEngine);
 
802
    d->lock();
 
803
    QRasterPaintEngine::drawStaticTextItem(sti);
 
804
 
 
805
#ifdef QT_BLITTER_RASTEROVERLAY
 
806
//#### d->pmData->markRasterOverlay(sti);
 
807
    qWarning("not implemented: markRasterOverlay for QStaticTextItem");
 
808
#endif
 
809
}
 
810
 
 
811
bool QBlitterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine)
 
812
{
 
813
    Q_D(QBlitterPaintEngine);
 
814
    QFontEngine::GlyphFormat glyphFormat = d->glyphCacheFormat;
 
815
    if (fontEngine->glyphFormat != QFontEngine::Format_None)
 
816
        glyphFormat = fontEngine->glyphFormat;
 
817
 
 
818
    const QClipData *clipData = d->clip();
 
819
    const bool complexClip = clipData && !clipData->hasRectClip;
 
820
 
 
821
    const QPainterState *s = state();
 
822
    if (d->caps.canBlitterDrawCachedGlyphs(s->transform(), glyphFormat, complexClip)) {
 
823
        d->unlock();
 
824
        const bool result = d->pmData->blittable()->drawCachedGlyphs(s, glyphFormat, numGlyphs, glyphs, positions, fontEngine);
 
825
        // Lock again as the raster paint engine might draw decorations now.
 
826
        d->lock();
 
827
        return result;
 
828
    } else {
 
829
        return QRasterPaintEngine::drawCachedGlyphs(numGlyphs, glyphs, positions, fontEngine);
 
830
    }
 
831
}
 
832
 
 
833
QT_END_NAMESPACE
 
834
#endif //QT_NO_BLITTABLE
 
835