summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qstroker_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting/qstroker_p.h')
-rw-r--r--src/gui/painting/qstroker_p.h394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
new file mode 100644
index 0000000000..8344f6cf86
--- /dev/null
+++ b/src/gui/painting/qstroker_p.h
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** 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$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTROKER_P_H
+#define QSTROKER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qpainterpath.h"
+#include "private/qdatabuffer_p.h"
+#include "private/qnumeric_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// #define QFIXED_IS_26_6
+
+#if defined QFIXED_IS_26_6
+typedef int qfixed;
+#define qt_real_to_fixed(real) qfixed(real * 64)
+#define qt_int_to_fixed(real) qfixed(int(real) << 6)
+#define qt_fixed_to_real(fixed) qreal(fixed / qreal(64))
+#define qt_fixed_to_int(fixed) int(fixed >> 6)
+struct qfixed2d
+{
+ qfixed x;
+ qfixed y;
+
+ bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
+};
+#elif defined QFIXED_IS_32_32
+typedef qint64 qfixed;
+#define qt_real_to_fixed(real) qfixed(real * double(qint64(1) << 32))
+#define qt_fixed_to_real(fixed) qreal(fixed / double(qint64(1) << 32))
+struct qfixed2d
+{
+ qfixed x;
+ qfixed y;
+
+ bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
+};
+#elif defined QFIXED_IS_16_16
+typedef int qfixed;
+#define qt_real_to_fixed(real) qfixed(real * qreal(1 << 16))
+#define qt_fixed_to_real(fixed) qreal(fixed / qreal(1 << 16))
+struct qfixed2d
+{
+ qfixed x;
+ qfixed y;
+
+ bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
+};
+#else
+typedef qreal qfixed;
+#define qt_real_to_fixed(real) qfixed(real)
+#define qt_fixed_to_real(fixed) fixed
+struct qfixed2d
+{
+ qfixed x;
+ qfixed y;
+
+ bool operator==(const qfixed2d &other) const { return qFuzzyCompare(x, other.x)
+ && qFuzzyCompare(y, other.y); }
+};
+#endif
+
+#define QT_PATH_KAPPA 0.5522847498
+
+QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength,
+ QPointF *controlPoints, int *point_count);
+
+qreal qt_t_for_arc_angle(qreal angle);
+
+typedef void (*qStrokerMoveToHook)(qfixed x, qfixed y, void *data);
+typedef void (*qStrokerLineToHook)(qfixed x, qfixed y, void *data);
+typedef void (*qStrokerCubicToHook)(qfixed c1x, qfixed c1y,
+ qfixed c2x, qfixed c2y,
+ qfixed ex, qfixed ey,
+ void *data);
+
+// qtransform.cpp
+Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
+
+class Q_GUI_EXPORT QStrokerOps
+{
+public:
+ struct Element {
+ QPainterPath::ElementType type;
+ qfixed x;
+ qfixed y;
+
+ inline bool isMoveTo() const { return type == QPainterPath::MoveToElement; }
+ inline bool isLineTo() const { return type == QPainterPath::LineToElement; }
+ inline bool isCurveTo() const { return type == QPainterPath::CurveToElement; }
+
+ operator qfixed2d () { qfixed2d pt = { x, y }; return pt; }
+ };
+
+ QStrokerOps();
+ virtual ~QStrokerOps();
+
+ void setMoveToHook(qStrokerMoveToHook moveToHook) { m_moveTo = moveToHook; }
+ void setLineToHook(qStrokerLineToHook lineToHook) { m_lineTo = lineToHook; }
+ void setCubicToHook(qStrokerCubicToHook cubicToHook) { m_cubicTo = cubicToHook; }
+
+ virtual void begin(void *customData);
+ virtual void end();
+
+ inline void moveTo(qfixed x, qfixed y);
+ inline void lineTo(qfixed x, qfixed y);
+ inline void cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey);
+
+ void strokePath(const QPainterPath &path, void *data, const QTransform &matrix);
+ void strokePolygon(const QPointF *points, int pointCount, bool implicit_close,
+ void *data, const QTransform &matrix);
+ void strokeEllipse(const QRectF &ellipse, void *data, const QTransform &matrix);
+
+ QRectF clipRect() const { return m_clip_rect; }
+ void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
+
+ void setCurveThresholdFromTransform(const QTransform &transform)
+ {
+ qreal scale;
+ qt_scaleForTransform(transform, &scale);
+ m_dashThreshold = scale == 0 ? qreal(0.5) : (qreal(0.5) / scale);
+ }
+
+ void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
+ qfixed curveThreshold() const { return m_curveThreshold; }
+
+protected:
+ inline void emitMoveTo(qfixed x, qfixed y);
+ inline void emitLineTo(qfixed x, qfixed y);
+ inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
+
+ virtual void processCurrentSubpath() = 0;
+ QDataBuffer<Element> m_elements;
+
+ QRectF m_clip_rect;
+ qfixed m_curveThreshold;
+ qfixed m_dashThreshold;
+
+ void *m_customData;
+ qStrokerMoveToHook m_moveTo;
+ qStrokerLineToHook m_lineTo;
+ qStrokerCubicToHook m_cubicTo;
+
+};
+
+class Q_GUI_EXPORT QStroker : public QStrokerOps
+{
+public:
+
+ enum LineJoinMode {
+ FlatJoin,
+ SquareJoin,
+ MiterJoin,
+ RoundJoin,
+ RoundCap,
+ SvgMiterJoin
+ };
+
+ QStroker();
+ ~QStroker();
+
+ void setStrokeWidth(qfixed width) { m_strokeWidth = width; }
+ qfixed strokeWidth() const { return m_strokeWidth; }
+
+ void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); }
+ Qt::PenCapStyle capStyle() const { return capForJoinMode(m_capStyle); }
+ LineJoinMode capStyleMode() const { return m_capStyle; }
+
+ void setJoinStyle(Qt::PenJoinStyle style) { m_joinStyle = joinModeForJoin(style); }
+ Qt::PenJoinStyle joinStyle() const { return joinForJoinMode(m_joinStyle); }
+ LineJoinMode joinStyleMode() const { return m_joinStyle; }
+
+ void setMiterLimit(qfixed length) { m_miterLimit = length; }
+ qfixed miterLimit() const { return m_miterLimit; }
+
+ void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
+ inline void emitMoveTo(qfixed x, qfixed y);
+ inline void emitLineTo(qfixed x, qfixed y);
+ inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
+
+protected:
+ static Qt::PenCapStyle capForJoinMode(LineJoinMode mode);
+ static LineJoinMode joinModeForCap(Qt::PenCapStyle);
+
+ static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode);
+ static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle);
+
+ virtual void processCurrentSubpath();
+
+ qfixed m_strokeWidth;
+ qfixed m_miterLimit;
+
+ LineJoinMode m_capStyle;
+ LineJoinMode m_joinStyle;
+
+ qfixed m_back1X;
+ qfixed m_back1Y;
+
+ qfixed m_back2X;
+ qfixed m_back2Y;
+};
+
+class Q_GUI_EXPORT QDashStroker : public QStrokerOps
+{
+public:
+ QDashStroker(QStroker *stroker);
+
+ QStroker *stroker() const { return m_stroker; }
+
+ static QVector<qfixed> patternForStyle(Qt::PenStyle style);
+
+ void setDashPattern(const QVector<qfixed> &dashPattern) { m_dashPattern = dashPattern; }
+ QVector<qfixed> dashPattern() const { return m_dashPattern; }
+
+ void setDashOffset(qreal offset) { m_dashOffset = offset; }
+ qreal dashOffset() const { return m_dashOffset; }
+
+ virtual void begin(void *data);
+ virtual void end();
+
+ inline void setStrokeWidth(qreal width) { m_stroke_width = width; }
+ inline void setMiterLimit(qreal limit) { m_miter_limit = limit; }
+
+protected:
+ virtual void processCurrentSubpath();
+
+ QStroker *m_stroker;
+ QVector<qfixed> m_dashPattern;
+ qreal m_dashOffset;
+
+ qreal m_stroke_width;
+ qreal m_miter_limit;
+};
+
+
+/*******************************************************************************
+ * QStrokerOps inline membmers
+ */
+
+inline void QStrokerOps::emitMoveTo(qfixed x, qfixed y)
+{
+ Q_ASSERT(m_moveTo);
+ m_moveTo(x, y, m_customData);
+}
+
+inline void QStrokerOps::emitLineTo(qfixed x, qfixed y)
+{
+ Q_ASSERT(m_lineTo);
+ m_lineTo(x, y, m_customData);
+}
+
+inline void QStrokerOps::emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey)
+{
+ Q_ASSERT(m_cubicTo);
+ m_cubicTo(c1x, c1y, c2x, c2y, ex, ey, m_customData);
+}
+
+inline void QStrokerOps::moveTo(qfixed x, qfixed y)
+{
+ if (m_elements.size()>1)
+ processCurrentSubpath();
+ m_elements.reset();
+ Element e = { QPainterPath::MoveToElement, x, y };
+ m_elements.add(e);
+}
+
+inline void QStrokerOps::lineTo(qfixed x, qfixed y)
+{
+ Element e = { QPainterPath::LineToElement, x, y };
+ m_elements.add(e);
+}
+
+inline void QStrokerOps::cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey)
+{
+ Element c1 = { QPainterPath::CurveToElement, x1, y1 };
+ Element c2 = { QPainterPath::CurveToDataElement, x2, y2 };
+ Element e = { QPainterPath::CurveToDataElement, ex, ey };
+ m_elements.add(c1);
+ m_elements.add(c2);
+ m_elements.add(e);
+}
+
+/*******************************************************************************
+ * QStroker inline members
+ */
+inline void QStroker::emitMoveTo(qfixed x, qfixed y)
+{
+ m_back2X = m_back1X;
+ m_back2Y = m_back1Y;
+ m_back1X = x;
+ m_back1Y = y;
+ QStrokerOps::emitMoveTo(x, y);
+}
+
+inline void QStroker::emitLineTo(qfixed x, qfixed y)
+{
+ m_back2X = m_back1X;
+ m_back2Y = m_back1Y;
+ m_back1X = x;
+ m_back1Y = y;
+ QStrokerOps::emitLineTo(x, y);
+}
+
+inline void QStroker::emitCubicTo(qfixed c1x, qfixed c1y,
+ qfixed c2x, qfixed c2y,
+ qfixed ex, qfixed ey)
+{
+ if (c2x == ex && c2y == ey) {
+ if (c1x == ex && c1y == ey) {
+ m_back2X = m_back1X;
+ m_back2Y = m_back1Y;
+ } else {
+ m_back2X = c1x;
+ m_back2Y = c1y;
+ }
+ } else {
+ m_back2X = c2x;
+ m_back2Y = c2y;
+ }
+ m_back1X = ex;
+ m_back1Y = ey;
+ QStrokerOps::emitCubicTo(c1x, c1y, c2x, c2y, ex, ey);
+}
+
+/*******************************************************************************
+ * QDashStroker inline members
+ */
+inline void QDashStroker::begin(void *data)
+{
+ if (m_stroker)
+ m_stroker->begin(data);
+ QStrokerOps::begin(data);
+}
+
+inline void QDashStroker::end()
+{
+ QStrokerOps::end();
+ if (m_stroker)
+ m_stroker->end();
+}
+
+QT_END_NAMESPACE
+
+#endif // QSTROKER_P_H