| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #ifndef QPAINTENGINE_RASTER_P_H |
| #define QPAINTENGINE_RASTER_P_H |
| |
| // |
| // W A R N I N G |
| // ------------- |
| // |
| // This file is not part of the Qt API. It exists for the convenience |
| // of other Qt classes. This header file may change from version to |
| // version without notice, or even be removed. |
| // |
| // We mean it. |
| // |
| |
| #include "private/qpaintengineex_p.h" |
| #include "QtGui/qpainterpath.h" |
| #include "private/qdatabuffer_p.h" |
| #include "private/qdrawhelper_p.h" |
| #include "private/qpaintengine_p.h" |
| #include "private/qrasterizer_p.h" |
| #include "private/qstroker_p.h" |
| #include "private/qpainter_p.h" |
| #include "private/qtextureglyphcache_p.h" |
| #include "private/qoutlinemapper_p.h" |
| |
| #include <stdlib.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| class QOutlineMapper; |
| class QRasterPaintEnginePrivate; |
| class QRasterBuffer; |
| class QClipData; |
| class QCustomRasterPaintDevice; |
| |
| class QRasterPaintEngineState : public QPainterState |
| { |
| public: |
| QRasterPaintEngineState(QRasterPaintEngineState &other); |
| QRasterPaintEngineState(); |
| ~QRasterPaintEngineState(); |
| |
| |
| QPen lastPen; |
| QSpanData penData; |
| QStrokerOps *stroker; |
| uint strokeFlags; |
| |
| QBrush lastBrush; |
| QSpanData brushData; |
| uint fillFlags; |
| |
| uint pixmapFlags; |
| int intOpacity; |
| |
| qreal txscale; |
| |
| QClipData *clip; |
| // QRect clipRect; |
| // QRegion clipRegion; |
| |
| // QPainter::RenderHints hints; |
| // QPainter::CompositionMode compositionMode; |
| |
| uint dirty; |
| |
| struct Flags { |
| uint has_clip_ownership : 1; // should delete the clip member.. |
| uint fast_pen : 1; // cosmetic 1-width pens, using midpoint drawlines |
| uint non_complex_pen : 1; // can use rasterizer, rather than stroker |
| uint antialiased : 1; |
| uint bilinear : 1; |
| uint fast_text : 1; |
| uint int_xform : 1; |
| uint tx_noshear : 1; |
| uint fast_images : 1; |
| }; |
| |
| union { |
| Flags flags; |
| uint flag_bits; |
| }; |
| }; |
| |
| |
| |
| |
| /******************************************************************************* |
| * QRasterPaintEngine |
| */ |
| class |
| #ifdef Q_WS_QWS |
| Q_GUI_EXPORT |
| #endif |
| QRasterPaintEngine : public QPaintEngineEx |
| { |
| Q_DECLARE_PRIVATE(QRasterPaintEngine) |
| public: |
| |
| QRasterPaintEngine(QPaintDevice *device); |
| ~QRasterPaintEngine(); |
| bool begin(QPaintDevice *device); |
| bool end(); |
| |
| void penChanged(); |
| void brushChanged(); |
| void brushOriginChanged(); |
| void opacityChanged(); |
| void compositionModeChanged(); |
| void renderHintsChanged(); |
| void transformChanged(); |
| void clipEnabledChanged(); |
| |
| void setState(QPainterState *s); |
| QPainterState *createState(QPainterState *orig) const; |
| inline QRasterPaintEngineState *state() { |
| return static_cast<QRasterPaintEngineState *>(QPaintEngineEx::state()); |
| } |
| inline const QRasterPaintEngineState *state() const { |
| return static_cast<const QRasterPaintEngineState *>(QPaintEngineEx::state()); |
| } |
| |
| void updateBrush(const QBrush &brush); |
| void updatePen(const QPen &pen); |
| |
| void updateMatrix(const QTransform &matrix); |
| |
| void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); |
| void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); |
| void fillPath(const QPainterPath &path, QSpanData *fillData); |
| void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); |
| |
| void drawEllipse(const QRectF &rect); |
| |
| void fillRect(const QRectF &rect, const QBrush &brush); |
| void fillRect(const QRectF &rect, const QColor &color); |
| |
| void drawRects(const QRect *rects, int rectCount); |
| void drawRects(const QRectF *rects, int rectCount); |
| |
| void drawPixmap(const QPointF &p, const QPixmap &pm); |
| void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); |
| void drawImage(const QPointF &p, const QImage &img); |
| void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, |
| Qt::ImageConversionFlags falgs = Qt::AutoColor); |
| void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); |
| void drawTextItem(const QPointF &p, const QTextItem &textItem); |
| |
| void drawLines(const QLine *line, int lineCount); |
| void drawLines(const QLineF *line, int lineCount); |
| |
| void drawPoints(const QPointF *points, int pointCount); |
| void drawPoints(const QPoint *points, int pointCount); |
| |
| void stroke(const QVectorPath &path, const QPen &pen); |
| void fill(const QVectorPath &path, const QBrush &brush); |
| |
| void strokePolygonCosmetic(const QPoint *pts, int pointCount, PolygonDrawMode mode); |
| void strokePolygonCosmetic(const QPointF *pt, int pointCount, PolygonDrawMode mode); |
| |
| void clip(const QVectorPath &path, Qt::ClipOperation op); |
| void clip(const QRect &rect, Qt::ClipOperation op); |
| void clip(const QRegion ®ion, Qt::ClipOperation op); |
| |
| void drawStaticTextItem(QStaticTextItem *textItem); |
| |
| enum ClipType { |
| RectClip, |
| ComplexClip |
| }; |
| ClipType clipType() const; |
| QRect clipBoundingRect() const; |
| |
| #ifdef Q_NO_USING_KEYWORD |
| inline void drawEllipse(const QRect &rect) { QPaintEngineEx::drawEllipse(rect); } |
| #else |
| using QPaintEngineEx::drawPolygon; |
| using QPaintEngineEx::drawEllipse; |
| #endif |
| |
| void releaseBuffer(); |
| |
| QSize size() const; |
| |
| #ifndef QT_NO_DEBUG |
| void saveBuffer(const QString &s) const; |
| #endif |
| |
| #ifdef Q_WS_MAC |
| void setCGContext(CGContextRef ref); |
| CGContextRef getCGContext() const; |
| #endif |
| |
| #ifdef Q_WS_WIN |
| void setDC(HDC hdc); |
| HDC getDC() const; |
| void releaseDC(HDC hdc) const; |
| #endif |
| |
| void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h); |
| |
| Type type() const { return Raster; } |
| |
| QPoint coordinateOffset() const; |
| |
| #if defined(Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| virtual void drawColorSpans(const QSpan *spans, int count, uint color); |
| virtual void drawBufferSpan(const uint *buffer, int bufsize, |
| int x, int y, int length, uint const_alpha); |
| #endif |
| |
| protected: |
| QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *); |
| private: |
| friend struct QSpanData; |
| void init(); |
| |
| void fillRect(const QRectF &rect, QSpanData *data); |
| void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill); |
| |
| void drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, |
| QFontEngine *fontEngine); |
| |
| #if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) |
| void drawGlyphsS60(const QPointF &p, const QTextItemInt &ti); |
| #endif // Q_OS_SYMBIAN && QT_NO_FREETYPE |
| |
| bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op); |
| |
| inline void ensureBrush(const QBrush &brush) { |
| if (!qbrush_fast_equals(state()->lastBrush, brush) || (brush.style() != Qt::NoBrush && state()->fillFlags)) |
| updateBrush(brush); |
| } |
| inline void ensureBrush() { ensureBrush(state()->brush); } |
| |
| inline void ensurePen(const QPen &pen) { |
| if (!qpen_fast_equals(state()->lastPen, pen) || (pen.style() != Qt::NoPen && state()->strokeFlags)) |
| updatePen(pen); |
| } |
| inline void ensurePen() { ensurePen(state()->pen); } |
| |
| void updateOutlineMapper(); |
| inline void ensureOutlineMapper(); |
| |
| void updateState(); |
| inline void ensureState() { |
| if (state()->dirty) |
| updateState(); |
| } |
| }; |
| |
| |
| /******************************************************************************* |
| * QRasterPaintEnginePrivate |
| */ |
| class |
| #ifdef Q_WS_QWS |
| Q_GUI_EXPORT |
| #endif |
| QRasterPaintEnginePrivate : public QPaintEngineExPrivate |
| { |
| Q_DECLARE_PUBLIC(QRasterPaintEngine) |
| public: |
| QRasterPaintEnginePrivate(); |
| |
| void rasterizeLine_dashed(QLineF line, qreal width, |
| int *dashIndex, qreal *dashOffset, bool *inDash); |
| void rasterize(QT_FT_Outline *outline, ProcessSpans callback, QSpanData *spanData, QRasterBuffer *rasterBuffer); |
| void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer); |
| void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix); |
| |
| void systemStateChanged(); |
| |
| void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func, |
| const QRect &clip, int alpha, const QRect &sr = QRect()); |
| |
| QTransform brushMatrix() const { |
| Q_Q(const QRasterPaintEngine); |
| const QRasterPaintEngineState *s = q->state(); |
| QTransform m(s->matrix); |
| m.translate(s->brushOrigin.x(), s->brushOrigin.y()); |
| return m; |
| } |
| |
| 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 QRect &rect, const QSpanData *data) 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; |
| |
| #ifdef Q_WS_QWS |
| void prepare(QCustomRasterPaintDevice *); |
| #endif |
| |
| inline const QClipData *clip() const; |
| |
| void initializeRasterizer(QSpanData *data); |
| |
| void recalculateFastImages(); |
| |
| QPaintDevice *device; |
| QScopedPointer<QOutlineMapper> outlineMapper; |
| QScopedPointer<QRasterBuffer> rasterBuffer; |
| |
| #if defined (Q_WS_WIN) |
| HDC hdc; |
| #elif defined(Q_WS_MAC) |
| CGContextRef cgContext; |
| #endif |
| |
| QRect deviceRect; |
| |
| QStroker basicStroker; |
| QScopedPointer<QDashStroker> dashStroker; |
| |
| QScopedPointer<QT_FT_Raster> grayRaster; |
| |
| QDataBuffer<QLineF> cachedLines; |
| QSpanData image_filler; |
| QSpanData image_filler_xform; |
| QSpanData solid_color_filler; |
| |
| |
| QFontEngineGlyphCache::Type glyphCacheType; |
| |
| QScopedPointer<QClipData> baseClip; |
| |
| int deviceDepth; |
| |
| uint mono_surface : 1; |
| uint outlinemapper_xform_dirty : 1; |
| |
| #ifdef Q_WS_WIN |
| uint isPlain45DegreeRotation : 1; |
| #endif |
| |
| QScopedPointer<QRasterizer> rasterizer; |
| }; |
| |
| |
| class |
| #ifdef Q_WS_QWS |
| Q_GUI_EXPORT |
| #endif |
| QClipData { |
| public: |
| QClipData(int height); |
| ~QClipData(); |
| |
| int clipSpanHeight; |
| struct ClipLine { |
| int count; |
| QSpan *spans; |
| } *m_clipLines; |
| |
| void initialize(); |
| |
| inline ClipLine *clipLines() { |
| if (!m_clipLines) |
| initialize(); |
| return m_clipLines; |
| } |
| |
| inline QSpan *spans() { |
| if (!m_spans) |
| initialize(); |
| return m_spans; |
| } |
| |
| int allocated; |
| int count; |
| QSpan *m_spans; |
| int xmin, xmax, ymin, ymax; |
| |
| QRect clipRect; |
| QRegion clipRegion; |
| |
| uint enabled : 1; |
| uint hasRectClip : 1; |
| uint hasRegionClip : 1; |
| |
| void appendSpan(int x, int length, int y, int coverage); |
| void appendSpans(const QSpan *s, int num); |
| |
| // ### Should optimize and actually kill the QSpans if the rect is |
| // ### a subset of The current region. Thus the "fast" clipspan |
| // ### callback can be used |
| void setClipRect(const QRect &rect); |
| void setClipRegion(const QRegion ®ion); |
| void fixup(); |
| }; |
| |
| inline void QClipData::appendSpan(int x, int length, int y, int coverage) |
| { |
| Q_ASSERT(m_spans); // initialize() has to be called prior to adding spans.. |
| |
| if (count == allocated) { |
| allocated *= 2; |
| m_spans = (QSpan *)realloc(m_spans, allocated*sizeof(QSpan)); |
| } |
| m_spans[count].x = x; |
| m_spans[count].len = length; |
| m_spans[count].y = y; |
| m_spans[count].coverage = coverage; |
| ++count; |
| } |
| |
| inline void QClipData::appendSpans(const QSpan *s, int num) |
| { |
| Q_ASSERT(m_spans); |
| |
| if (count + num > allocated) { |
| do { |
| allocated *= 2; |
| } while (count + num > allocated); |
| m_spans = (QSpan *)realloc(m_spans, allocated*sizeof(QSpan)); |
| } |
| memcpy(m_spans+count, s, num*sizeof(QSpan)); |
| count += num; |
| } |
| |
| #ifdef Q_WS_QWS |
| class Q_GUI_EXPORT QCustomRasterPaintDevice : public QPaintDevice |
| { |
| public: |
| QCustomRasterPaintDevice(QWidget *w) : widget(w) {} |
| |
| int devType() const { return QInternal::CustomRaster; } |
| |
| virtual int metric(PaintDeviceMetric m) const; |
| |
| virtual void* memory() const { return 0; } |
| |
| virtual QImage::Format format() const { |
| return QImage::Format_ARGB32_Premultiplied; |
| } |
| |
| virtual int bytesPerLine() const; |
| |
| virtual QSize size() const { |
| return static_cast<QRasterPaintEngine*>(paintEngine())->size(); |
| } |
| |
| private: |
| QWidget *widget; |
| }; |
| #endif // Q_WS_QWS |
| |
| /******************************************************************************* |
| * QRasterBuffer |
| */ |
| class |
| #ifdef Q_WS_QWS |
| Q_GUI_EXPORT |
| #endif |
| QRasterBuffer |
| { |
| public: |
| QRasterBuffer() : m_width(0), m_height(0), m_buffer(0) { init(); } |
| |
| ~QRasterBuffer(); |
| |
| void init(); |
| |
| QImage::Format prepare(QImage *image); |
| QImage::Format prepare(QPixmap *pix); |
| #ifdef Q_WS_QWS |
| void prepare(QCustomRasterPaintDevice *device); |
| #endif |
| void prepare(int w, int h); |
| void prepareBuffer(int w, int h); |
| |
| void resetBuffer(int val=0); |
| |
| uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * bytes_per_line; } |
| |
| #ifndef QT_NO_DEBUG |
| QImage bufferImage() const; |
| #endif |
| |
| void flushToARGBImage(QImage *image) const; |
| |
| int width() const { return m_width; } |
| int height() const { return m_height; } |
| int bytesPerLine() const { return bytes_per_line; } |
| int bytesPerPixel() const { return bytes_per_pixel; } |
| |
| uchar *buffer() const { return m_buffer; } |
| |
| bool monoDestinationWithClut; |
| QRgb destColor0; |
| QRgb destColor1; |
| |
| QPainter::CompositionMode compositionMode; |
| QImage::Format format; |
| DrawHelper *drawHelper; |
| QImage colorizeBitmap(const QImage &image, const QColor &color); |
| |
| private: |
| int m_width; |
| int m_height; |
| int bytes_per_line; |
| int bytes_per_pixel; |
| uchar *m_buffer; |
| }; |
| |
| inline void QRasterPaintEngine::ensureOutlineMapper() { |
| if (d_func()->outlinemapper_xform_dirty) |
| updateOutlineMapper(); |
| } |
| |
| inline const QClipData *QRasterPaintEnginePrivate::clip() const { |
| Q_Q(const QRasterPaintEngine); |
| if (q->state() && q->state()->clip && q->state()->clip->enabled) |
| return q->state()->clip; |
| return baseClip.data(); |
| } |
| |
| |
| QT_END_NAMESPACE |
| #endif // QPAINTENGINE_RASTER_P_H |