📄 qpaintengine_x11.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qplatformdefs.h"#include "private/qpixmap_p.h"#include "qapplication.h"#include "qdebug.h"#include "qfont.h"#include "qwidget.h"#include "qbitmap.h"#include "qpixmapcache.h"#include "qtextcodec.h"#include "qcoreevent.h"#include "qiodevice.h"#include "qpainter_p.h"#include <qtextlayout.h>#include <qvarlengtharray.h>#include <private/qfont_p.h>#include <private/qtextengine_p.h>#include <private/qpaintengine_x11_p.h>#include <private/qfontengine_p.h>#include "qpen.h"#include "qcolor.h"#include "qcolormap.h"#include "qmath_p.h"#include <private/qpaintengine_p.h>#include "qpaintengine_x11_p.h"#include <private/qt_x11_p.h>#include <private/qnumeric_p.h>#include <limits.h>extern Drawable qt_x11Handle(const QPaintDevice *pd);extern const QX11Info *qt_x11Info(const QPaintDevice *pd);extern QPixmap qt_pixmapForBrush(int brushStyle, bool invert); //in qbrush.cpp// hack, so we don't have to make QRegion::clipRectangles() public or include// X11 headers in qregion.hvoid *qt_getClipRects(const QRegion &r, int &num){ return r.clipRectangles(num);}static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2,#ifndef QT_NO_XRENDER Picture picture,#else Qt::HANDLE picture,#endif const QRegion &r){ int num; XRectangle *rects = (XRectangle *)qt_getClipRects(r, num); if (gc) XSetClipRectangles( dpy, gc, 0, 0, rects, num, YXBanded ); if (gc2) XSetClipRectangles( dpy, gc2, 0, 0, rects, num, YXBanded );#ifndef QT_NO_XRENDER if (picture) XRenderSetPictureClipRectangles(dpy, picture, 0, 0, rects, num);#else Q_UNUSED(picture);#endif // QT_NO_XRENDER}static inline int qpainterOpToXrender(QPainter::CompositionMode mode){#ifndef QT_NO_XRENDER switch (mode) { case QPainter::CompositionMode_SourceOver: return PictOpOver; break; case QPainter::CompositionMode_DestinationOver: return PictOpOverReverse; break; case QPainter::CompositionMode_Clear: return PictOpClear; break; case QPainter::CompositionMode_Source: return PictOpSrc; break; case QPainter::CompositionMode_Destination: return PictOpDst; break; case QPainter::CompositionMode_SourceIn: return PictOpIn; break; case QPainter::CompositionMode_DestinationIn: return PictOpInReverse; break; case QPainter::CompositionMode_SourceOut: return PictOpOut; break; case QPainter::CompositionMode_DestinationOut: return PictOpOutReverse; break; case QPainter::CompositionMode_SourceAtop: return PictOpAtop; break; case QPainter::CompositionMode_DestinationAtop: return PictOpAtopReverse; break; case QPainter::CompositionMode_Xor: return PictOpXor; break; default: return PictOpOver; break; }#endif return 0;}static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2,#ifndef QT_NO_XRENDER Picture picture#else Qt::HANDLE picture#endif ){ if (gc) XSetClipMask(dpy, gc, XNone); if (gc2) XSetClipMask(dpy, gc2, XNone);#ifndef QT_NO_XRENDER if (picture) { XRenderPictureAttributes attrs; attrs.clip_mask = XNone; XRenderChangePicture (dpy, picture, CPClipMask, &attrs); }#else Q_UNUSED(picture);#endif // QT_NO_XRENDER}void qt_draw_transformed_rect(QPaintEngine *pe, int x, int y, int w, int h, bool fill){ QX11PaintEngine *p = static_cast<QX11PaintEngine *>(pe); QMatrix matrix = p->d_func()->matrix; XPoint points[5]; int xp = x, yp = y; matrix.map(xp, yp, &xp, &yp); points[0].x = xp; points[0].y = yp; xp = x + w; yp = y; matrix.map(xp, yp, &xp, &yp); points[1].x = xp; points[1].y = yp; xp = x + w; yp = y + h; matrix.map(xp, yp, &xp, &yp); points[2].x = xp; points[2].y = yp; xp = x; yp = y + h; matrix.map(xp, yp, &xp, &yp); points[3].x = xp; points[3].y = yp; points[4] = points[0]; if (fill) XFillPolygon(p->d_func()->dpy, p->d_func()->hd, p->d_func()->gc, points, 4, Convex, CoordModeOrigin); else XDrawLines(p->d_func()->dpy, p->d_func()->hd, p->d_func()->gc, points, 5, CoordModeOrigin);}#define DITHER_SIZE 16static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = { { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }};static QPixmap qt_patternForAlpha(uchar alpha){ static QPixmap pm; QString key = "$qt-alpha-brush$" + QString::number(alpha); if (!QPixmapCache::find(key, pm)) { // #### why not use a mono image here???? QImage pattern(DITHER_SIZE, DITHER_SIZE, QImage::Format_ARGB32); pattern.fill(0xffffffff); for (int y = 0; y < DITHER_SIZE; ++y) { for (int x = 0; x < DITHER_SIZE; ++x) { if (base_dither_matrix[x][y] <= alpha) pattern.setPixel(x, y, 0x00000000); } } pm = QBitmap::fromImage(pattern); QPixmapCache::insert(key, pm); } return pm;}#if !defined(QT_NO_XRENDER)/* * Polygon tesselator - can probably be optimized a bit more *///#define QT_DEBUG_TESSELATOR#define FloatToXFixed(i) (int)((i) * 65536)#define IntToXFixed(i) ((i) << 16)Q_DECLARE_TYPEINFO(XTrapezoid, Q_PRIMITIVE_TYPE);// used by the edge point sort algorithmstatic qreal currentY = 0.f;struct QEdge { XPointFixed p1, p2; qreal m; qreal b; signed char winding;};Q_DECLARE_TYPEINFO(QEdge, Q_PRIMITIVE_TYPE);static inline bool compareEdges(const QEdge *e1, const QEdge *e2){ return e1->p1.y < e2->p1.y;}static inline bool isEqual(const XPointFixed &p1, const XPointFixed &p2){ return ((p1.x == p2.x) && (p1.y == p2.y));}struct QIntersectionPoint { qreal x; const QEdge *edge;};Q_DECLARE_TYPEINFO(QIntersectionPoint, Q_PRIMITIVE_TYPE);static inline bool compareIntersections(const QIntersectionPoint &i1, const QIntersectionPoint &i2){ if (qAbs(i1.x - i2.x) > 0.01) { // x != other.x in 99% of the cases return i1.x < i2.x; } else { qreal x1 = !qIsFinite(i1.edge->b) ? XFixedToDouble(i1.edge->p1.x) : (currentY+1.f - i1.edge->b)*i1.edge->m; qreal x2 = !qIsFinite(i2.edge->b) ? XFixedToDouble(i2.edge->p1.x) : (currentY+1.f - i2.edge->b)*i2.edge->m; return x1 < x2; }}#define qrealToXFixed FloatToXFixedstatic XTrapezoid QT_FASTCALL toXTrapezoid(XFixed y1, XFixed y2, const QEdge &left, const QEdge &right){ XTrapezoid trap; trap.top = y1; trap.bottom = y2; trap.left.p1.y = left.p1.y; trap.left.p2.y = left.p2.y; trap.right.p1.y = right.p1.y; trap.right.p2.y = right.p2.y; trap.left.p1.x = left.p1.x; trap.left.p2.x = left.p2.x; trap.right.p1.x = right.p1.x; trap.right.p2.x = right.p2.x; return trap;}#ifdef QT_DEBUG_TESSELATORstatic QPointF xf_to_qt(XPointFixed pt){ return QPointF(XFixedToDouble(pt.x), XFixedToDouble(pt.y));}static void dump_edges(const QList<const QEdge *> &et){ for (int x = 0; x < et.size(); ++x) { qDebug() << "edge#" << x << xf_to_qt(et.at(x)->p1) << xf_to_qt(et.at(x)->p2) << "b: " << et.at(x)->b << "m:" << et.at(x)->m << et.at(x); }}static void dump_trap(const XTrapezoid &t){ qDebug() << "trap# t=" << XFixedToDouble(t.top) << "b=" << XFixedToDouble(t.bottom) << "h=" << XFixedToDouble(t.bottom - t.top) << "\tleft p1: (" << XFixedToDouble(t.left.p1.x) << ","<< XFixedToDouble(t.left.p1.y) << ")" << "\tleft p2: (" << XFixedToDouble(t.left.p2.x) << "," << XFixedToDouble(t.left.p2.y) << ")" << "\n\t\t\t\tright p1:(" << XFixedToDouble(t.right.p1.x) << "," << XFixedToDouble(t.right.p1.y) << ")" << "\tright p2:(" << XFixedToDouble(t.right.p2.x) << "," << XFixedToDouble(t.right.p2.y) << ")";}#endifstatic void qt_tesselate_polygon(QVector<XTrapezoid> *traps, const QPointF *pg, int pgSize, bool winding, QRect *br){ QVector<QEdge> edges; edges.reserve(128); qreal ymin(INT_MAX/256); qreal ymax(INT_MIN/256); qreal xmin(INT_MAX/256); qreal xmax(INT_MIN/256); Q_ASSERT(pg[0] == pg[pgSize-1]); // generate edge table for (int x = 0; x < pgSize-1; ++x) { QEdge edge; edge.winding = pg[x].y() > pg[x+1].y() ? 1 : -1; QPointF p1, p2; if (edge.winding > 0) { p1 = pg[x+1]; p2 = pg[x]; } else { p1 = pg[x]; p2 = pg[x+1]; } edge.p1.x = XDoubleToFixed(p1.x()); edge.p1.y = XDoubleToFixed(p1.y()); edge.p2.x = XDoubleToFixed(p2.x()); edge.p2.y = XDoubleToFixed(p2.y()); edge.m = (p1.y() - p2.y()) / (p1.x() - p2.x()); // line derivative edge.b = p1.y() - edge.m * p1.x(); // intersection with y axis edge.m = edge.m != 0.0 ? 1.0 / edge.m : 0.0; // inverted derivative edges.append(edge); xmin = qMin(xmin, XFixedToDouble(edge.p1.x)); xmax = qMax(xmax, XFixedToDouble(edge.p2.x)); ymin = qMin(ymin, XFixedToDouble(edge.p1.y)); ymax = qMax(ymax, XFixedToDouble(edge.p2.y)); } br->setX(qRound(xmin)); br->setY(qRound(ymin)); br->setWidth(qRound(xmax - xmin)); br->setHeight(qRound(ymax - ymin)); QList<const QEdge *> et; // edge list for (int i = 0; i < edges.size(); ++i) et.append(&edges.at(i)); // sort edge table by min y value qSort(et.begin(), et.end(), compareEdges);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -