/**************************************************************************** | |
** | |
** 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 |