📄 qrasterizer.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 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://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** 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 "qrasterizer_p.h"#include <QDebug>#include <QLine>#include <QPoint>#include <QRect>#include <QTransform>#include <private/qmath_p.h>#include <private/qdrawhelper_p.h>#include <private/qpaintengine_raster_p.h>typedef int Q16Dot16;#define Q16Dot16ToFloat(i) ((i)/65536.)#define FloatToQ16Dot16(i) (int)((i) * 65536.)#define IntToQ16Dot16(i) ((i) << 16)#define Q16Dot16ToInt(i) ((i) >> 16)#define Q16Dot16Factor 65536#define Q16Dot16Multiply(x, y) (int)((qlonglong(x) * qlonglong(y)) >> 16)#define Q16Dot16FastMultiply(x, y) (((x) * (y)) >> 16)#define SPAN_BUFFER_SIZE 256class QSpanBuffer {public: QSpanBuffer(QSpanData *data, QRasterBuffer *rb, const QRect &deviceRect) : m_spanCount(0) , m_data(data) , m_rb(rb) , m_blend(data->blend) , m_deviceRect(deviceRect) { } ~QSpanBuffer() { flushSpans(); } void addSpan(int x, unsigned int len, int y, unsigned char coverage) { if (!coverage || !len) return; Q_ASSERT(y >= m_deviceRect.top()); Q_ASSERT(y <= m_deviceRect.bottom()); Q_ASSERT(x >= m_deviceRect.left()); Q_ASSERT(x + int(len) - 1 <= m_deviceRect.right()); m_spans[m_spanCount].x = x; m_spans[m_spanCount].len = len; m_spans[m_spanCount].y = y; m_spans[m_spanCount].coverage = coverage; if (++m_spanCount == SPAN_BUFFER_SIZE) flushSpans(); } void setBoundingRect(int left, int top, int right, int bottom) { m_blend = isUnclipped(QRect(left, top, right - left + 1, bottom - top + 1)) ? m_data->unclipped_blend : m_data->blend; }private: bool isUnclipped(const QRect &r) { if (m_rb->clip) return false; if (m_rb->clipRect == m_deviceRect) return true; if (!m_rb->clipRect.isEmpty()) { const QRect &r1 = m_rb->clipRect; return (r.left() >= r1.left() && r.right() <= r1.right() && r.top() >= r1.top() && r.bottom() <= r1.bottom()); } else { return qt_region_strictContains(m_rb->clipRegion, r); } } void flushSpans() { m_blend(m_spanCount, m_spans, m_data); m_spanCount = 0; } QT_FT_Span m_spans[SPAN_BUFFER_SIZE]; int m_spanCount; QSpanData *m_data; QRasterBuffer *m_rb; QRasterPaintEnginePrivate *m_pe; ProcessSpans m_blend; QRect m_deviceRect;};class QRasterizerPrivate{public: bool antialiased; QSpanData *spanData; QRasterBuffer *rasterBuffer; QRect deviceRect;};QRasterizer::QRasterizer() : d(new QRasterizerPrivate){}QRasterizer::~QRasterizer(){ delete d;}void QRasterizer::initialize(bool antialiased, QRasterBuffer *rb){ d->antialiased = antialiased; d->rasterBuffer = rb;}void QRasterizer::setSpanData(QSpanData *data){ d->spanData = data;}void QRasterizer::setDeviceRect(const QRect &deviceRect){ d->deviceRect = deviceRect;}static Q16Dot16 intersectPixelFP(int x, Q16Dot16 top, Q16Dot16 bottom, Q16Dot16 leftIntersectX, Q16Dot16 rightIntersectX, Q16Dot16 slope, Q16Dot16 invSlope){ Q16Dot16 leftX = IntToQ16Dot16(x); Q16Dot16 rightX = IntToQ16Dot16(x) + Q16Dot16Factor; Q16Dot16 leftIntersectY, rightIntersectY; if (slope > 0) { leftIntersectY = top + Q16Dot16Multiply(leftX - leftIntersectX, invSlope); rightIntersectY = leftIntersectY + invSlope; } else { leftIntersectY = top + Q16Dot16Multiply(leftX - rightIntersectX, invSlope); rightIntersectY = leftIntersectY + invSlope; } if (leftIntersectX >= leftX && rightIntersectX <= rightX) { return Q16Dot16Multiply(bottom - top, leftIntersectX - leftX + ((rightIntersectX - leftIntersectX) >> 1)); } else if (leftIntersectX >= rightX) { return bottom - top; } else if (leftIntersectX >= leftX) { if (slope > 0) { return (bottom - top) - Q16Dot16FastMultiply((rightX - leftIntersectX) >> 1, rightIntersectY - top); } else { return (bottom - top) - Q16Dot16FastMultiply((rightX - leftIntersectX) >> 1, bottom - rightIntersectY); } } else if (rightIntersectX <= leftX) { return 0; } else if (rightIntersectX <= rightX) { if (slope > 0) { return Q16Dot16FastMultiply((rightIntersectX - leftX) >> 1, bottom - leftIntersectY); } else { return Q16Dot16FastMultiply((rightIntersectX - leftX) >> 1, leftIntersectY - top); } } else { if (slope > 0) { return (bottom - rightIntersectY) + ((rightIntersectY - leftIntersectY) >> 1); } else { return (rightIntersectY - top) + ((leftIntersectY - rightIntersectY) >> 1); } }}void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, bool squareCap){ QPointF pa = a; QPointF pb = b; QSpanBuffer buffer(d->spanData, d->rasterBuffer, d->deviceRect); if (qFuzzyCompare(pa.y(), pb.y())) { const qreal x = (a.x() + b.x()) * 0.5f; const qreal dx = qAbs(b.x() - a.x()) * 0.5f; const qreal dy = width * dx; pa = QPointF(x, a.y() - dy); pb = QPointF(x, a.y() + dy); if (squareCap) width = 1 / width + 1.0f; else width = 1 / width; squareCap = false; } if (qFuzzyCompare(pa.x(), pb.x())) { if (pa.y() > pb.y()) qSwap(pa, pb); const qreal dy = pb.y() - pa.y(); const qreal halfWidth = 0.5f * width * dy; if (squareCap) { pa.ry() -= halfWidth; pb.ry() += halfWidth; } qreal left = pa.x() - halfWidth; qreal right = pa.x() + halfWidth; left = qBound(qreal(d->deviceRect.left()), left, qreal(d->deviceRect.right() + 1)); right = qBound(qreal(d->deviceRect.left()), right, qreal(d->deviceRect.right() + 1)); pa.ry() = qBound(qreal(d->deviceRect.top()), pa.y(), qreal(d->deviceRect.bottom() + 1)); pb.ry() = qBound(qreal(d->deviceRect.top()), pb.y(), qreal(d->deviceRect.bottom() + 1)); if (qFuzzyCompare(left, right) || qFuzzyCompare(pa.y(), pb.y())) return; if (d->antialiased) { int iTop = int(pa.y()) ; int iBottom = int(pb.y()); int iLeft = int(left); int iRight = int(right); buffer.setBoundingRect(iLeft, iTop, iRight, iBottom); Q16Dot16 leftWidth = FloatToQ16Dot16(iLeft + 1.0f - left); Q16Dot16 rightWidth = FloatToQ16Dot16(right - iRight); Q16Dot16 coverage[3]; int x[3]; int len[3]; int n = 1; if (iLeft == iRight) { coverage[0] = leftWidth + rightWidth; x[0] = iLeft; len[0] = 1; } else { coverage[0] = leftWidth; x[0] = iLeft; len[0] = 1; if (leftWidth == Q16Dot16Factor) { len[0] = iRight - iLeft; } else if (iRight - iLeft > 1) { coverage[1] = Q16Dot16Factor; x[1] = iLeft + 1; len[1] = iRight - iLeft - 1; ++n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -