| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|---|
| 4 | ** All rights reserved.
|
|---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
|---|
| 6 | **
|
|---|
| 7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
|---|
| 8 | **
|
|---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
|---|
| 10 | ** Commercial Usage
|
|---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
|---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
|---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
|---|
| 14 | ** a written agreement between you and Nokia.
|
|---|
| 15 | **
|
|---|
| 16 | ** GNU Lesser General Public License Usage
|
|---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|---|
| 18 | ** General Public License version 2.1 as published by the Free Software
|
|---|
| 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|---|
| 20 | ** packaging of this file. Please review the following information to
|
|---|
| 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|---|
| 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|---|
| 23 | **
|
|---|
| 24 | ** In addition, as a special exception, Nokia gives you certain additional
|
|---|
| 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
|---|
| 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|---|
| 27 | **
|
|---|
| 28 | ** GNU General Public License Usage
|
|---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
|---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
|---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 32 | ** packaging of this file. Please review the following information to
|
|---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
|---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
|---|
| 35 | **
|
|---|
| 36 | ** If you have questions regarding the use of this file, please contact
|
|---|
| 37 | ** Nokia at [email protected].
|
|---|
| 38 | ** $QT_END_LICENSE$
|
|---|
| 39 | **
|
|---|
| 40 | ****************************************************************************/
|
|---|
| 41 |
|
|---|
| 42 | #ifndef QOUTLINEMAPPER_P_H
|
|---|
| 43 | #define QOUTLINEMAPPER_P_H
|
|---|
| 44 |
|
|---|
| 45 | //
|
|---|
| 46 | // W A R N I N G
|
|---|
| 47 | // -------------
|
|---|
| 48 | //
|
|---|
| 49 | // This file is not part of the Qt API. It exists purely as an
|
|---|
| 50 | // implementation detail. This header file may change from version to
|
|---|
| 51 | // version without notice, or even be removed.
|
|---|
| 52 | //
|
|---|
| 53 | // We mean it.
|
|---|
| 54 | //
|
|---|
| 55 |
|
|---|
| 56 | #include <QtCore/qrect.h>
|
|---|
| 57 |
|
|---|
| 58 | #include <QtGui/qtransform.h>
|
|---|
| 59 | #include <QtGui/qpainterpath.h>
|
|---|
| 60 |
|
|---|
| 61 | #define QT_FT_BEGIN_HEADER
|
|---|
| 62 | #define QT_FT_END_HEADER
|
|---|
| 63 |
|
|---|
| 64 | #include <private/qrasterdefs_p.h>
|
|---|
| 65 | #include <private/qdatabuffer_p.h>
|
|---|
| 66 | #include "qpaintengineex_p.h"
|
|---|
| 67 |
|
|---|
| 68 | QT_BEGIN_NAMESPACE
|
|---|
| 69 |
|
|---|
| 70 | // This limitations comes from qgrayraster.c. Any higher and
|
|---|
| 71 | // rasterization of shapes will produce incorrect results.
|
|---|
| 72 | const int QT_RASTER_COORD_LIMIT = 32767;
|
|---|
| 73 |
|
|---|
| 74 | //#define QT_DEBUG_CONVERT
|
|---|
| 75 |
|
|---|
| 76 | /********************************************************************************
|
|---|
| 77 | * class QOutlineMapper
|
|---|
| 78 | *
|
|---|
| 79 | * Used to map between QPainterPath and the QT_FT_Outline structure used by the
|
|---|
| 80 | * freetype scanconvertor.
|
|---|
| 81 | *
|
|---|
| 82 | * The outline mapper uses a path iterator to get points from the path,
|
|---|
| 83 | * so that it is possible to transform the points as they are converted. The
|
|---|
| 84 | * callback can be a noop, translate or full-fledged xform. (Tests indicated
|
|---|
| 85 | * that using a C callback was low cost).
|
|---|
| 86 | */
|
|---|
| 87 | class QOutlineMapper
|
|---|
| 88 | {
|
|---|
| 89 | public:
|
|---|
| 90 | QOutlineMapper()
|
|---|
| 91 | : m_round_coords(false)
|
|---|
| 92 | {
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | /*!
|
|---|
| 96 | Sets up the matrix to be used for conversion. This also
|
|---|
| 97 | sets up the qt_path_iterator function that is used as a callback
|
|---|
| 98 | to get points.
|
|---|
| 99 | */
|
|---|
| 100 | void setMatrix(const QTransform &m)
|
|---|
| 101 | {
|
|---|
| 102 | m_m11 = m.m11();
|
|---|
| 103 | m_m12 = m.m12();
|
|---|
| 104 | m_m13 = m.m13();
|
|---|
| 105 | m_m21 = m.m21();
|
|---|
| 106 | m_m22 = m.m22();
|
|---|
| 107 | m_m23 = m.m23();
|
|---|
| 108 | m_m33 = m.m33();
|
|---|
| 109 | m_dx = m.dx();
|
|---|
| 110 | m_dy = m.dy();
|
|---|
| 111 | m_txop = m.type();
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 | void beginOutline(Qt::FillRule fillRule)
|
|---|
| 115 | {
|
|---|
| 116 | #ifdef QT_DEBUG_CONVERT
|
|---|
| 117 | printf("QOutlineMapper::beginOutline rule=%d\n", fillRule);
|
|---|
| 118 | #endif
|
|---|
| 119 | m_valid = true;
|
|---|
| 120 | m_elements.reset();
|
|---|
| 121 | m_elements_dev.reset();
|
|---|
| 122 | m_element_types.reset();
|
|---|
| 123 | m_points.reset();
|
|---|
| 124 | m_tags.reset();
|
|---|
| 125 | m_contours.reset();
|
|---|
| 126 | m_outline.flags = fillRule == Qt::WindingFill
|
|---|
| 127 | ? QT_FT_OUTLINE_NONE
|
|---|
| 128 | : QT_FT_OUTLINE_EVEN_ODD_FILL;
|
|---|
| 129 | m_subpath_start = 0;
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | void endOutline();
|
|---|
| 133 |
|
|---|
| 134 | void clipElements(const QPointF *points, const QPainterPath::ElementType *types, int count);
|
|---|
| 135 |
|
|---|
| 136 | void convertElements(const QPointF *points, const QPainterPath::ElementType *types, int count);
|
|---|
| 137 |
|
|---|
| 138 | inline void moveTo(const QPointF &pt) {
|
|---|
| 139 | #ifdef QT_DEBUG_CONVERT
|
|---|
| 140 | printf("QOutlineMapper::moveTo() (%f, %f)\n", pt.x(), pt.y());
|
|---|
| 141 | #endif
|
|---|
| 142 | closeSubpath();
|
|---|
| 143 | m_subpath_start = m_elements.size();
|
|---|
| 144 | m_elements << pt;
|
|---|
| 145 | m_element_types << QPainterPath::MoveToElement;
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | inline void lineTo(const QPointF &pt) {
|
|---|
| 149 | #ifdef QT_DEBUG_CONVERT
|
|---|
| 150 | printf("QOutlineMapper::lineTo() (%f, %f)\n", pt.x(), pt.y());
|
|---|
| 151 | #endif
|
|---|
| 152 | m_elements.add(pt);
|
|---|
| 153 | m_element_types << QPainterPath::LineToElement;
|
|---|
| 154 | }
|
|---|
| 155 |
|
|---|
| 156 | inline void curveTo(const QPointF &cp1, const QPointF &cp2, const QPointF &ep) {
|
|---|
| 157 | #ifdef QT_DEBUG_CONVERT
|
|---|
| 158 | printf("QOutlineMapper::curveTo() (%f, %f)\n", ep.x(), ep.y());
|
|---|
| 159 | #endif
|
|---|
| 160 | m_elements << cp1 << cp2 << ep;
|
|---|
| 161 | m_element_types << QPainterPath::CurveToElement
|
|---|
| 162 | << QPainterPath::CurveToDataElement
|
|---|
| 163 | << QPainterPath::CurveToDataElement;
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | inline void closeSubpath() {
|
|---|
| 167 | int element_count = m_elements.size();
|
|---|
| 168 | if (element_count > 0) {
|
|---|
| 169 | if (m_elements.at(element_count-1) != m_elements.at(m_subpath_start)) {
|
|---|
| 170 | #ifdef QT_DEBUG_CONVERT
|
|---|
| 171 | printf(" - implicitly closing\n");
|
|---|
| 172 | #endif
|
|---|
| 173 | // Put the object on the stack to avoid the odd case where
|
|---|
| 174 | // lineTo reallocs the databuffer and the QPointF & will
|
|---|
| 175 | // be invalidated.
|
|---|
| 176 | QPointF pt = m_elements.at(m_subpath_start);
|
|---|
| 177 |
|
|---|
| 178 | // only do lineTo if we have element_type array...
|
|---|
| 179 | if (m_element_types.size())
|
|---|
| 180 | lineTo(pt);
|
|---|
| 181 | else
|
|---|
| 182 | m_elements << pt;
|
|---|
| 183 |
|
|---|
| 184 | }
|
|---|
| 185 | }
|
|---|
| 186 | }
|
|---|
| 187 |
|
|---|
| 188 | QT_FT_Outline *outline() {
|
|---|
| 189 | if (m_valid)
|
|---|
| 190 | return &m_outline;
|
|---|
| 191 | return 0;
|
|---|
| 192 | }
|
|---|
| 193 |
|
|---|
| 194 | QT_FT_Outline *convertPath(const QPainterPath &path);
|
|---|
| 195 | QT_FT_Outline *convertPath(const QVectorPath &path);
|
|---|
| 196 |
|
|---|
| 197 | void setCoordinateRounding(bool coordinateRounding) { m_round_coords = coordinateRounding; }
|
|---|
| 198 |
|
|---|
| 199 | inline QPainterPath::ElementType *elementTypes() const { return m_element_types.size() == 0 ? 0 : m_element_types.data(); }
|
|---|
| 200 |
|
|---|
| 201 | public:
|
|---|
| 202 | QDataBuffer<QPainterPath::ElementType> m_element_types;
|
|---|
| 203 | QDataBuffer<QPointF> m_elements;
|
|---|
| 204 | QDataBuffer<QPointF> m_elements_dev;
|
|---|
| 205 | QDataBuffer<QT_FT_Vector> m_points;
|
|---|
| 206 | QDataBuffer<char> m_tags;
|
|---|
| 207 | QDataBuffer<int> m_contours;
|
|---|
| 208 |
|
|---|
| 209 | QRect m_clip_rect;
|
|---|
| 210 | QDataBuffer<QPointF> m_polygon_dev;
|
|---|
| 211 |
|
|---|
| 212 | QRectF controlPointRect; // only valid after endOutline()
|
|---|
| 213 |
|
|---|
| 214 | QT_FT_Outline m_outline;
|
|---|
| 215 | uint m_txop;
|
|---|
| 216 |
|
|---|
| 217 | int m_subpath_start;
|
|---|
| 218 |
|
|---|
| 219 | // Matrix
|
|---|
| 220 | qreal m_m11;
|
|---|
| 221 | qreal m_m12;
|
|---|
| 222 | qreal m_m13;
|
|---|
| 223 | qreal m_m21;
|
|---|
| 224 | qreal m_m22;
|
|---|
| 225 | qreal m_m23;
|
|---|
| 226 | qreal m_m33;
|
|---|
| 227 | qreal m_dx;
|
|---|
| 228 | qreal m_dy;
|
|---|
| 229 |
|
|---|
| 230 | bool m_valid;
|
|---|
| 231 |
|
|---|
| 232 | private:
|
|---|
| 233 | bool m_round_coords;
|
|---|
| 234 | };
|
|---|
| 235 |
|
|---|
| 236 | QT_END_NAMESPACE
|
|---|
| 237 |
|
|---|
| 238 | #endif // QOUTLINEMAPPER_P_H
|
|---|