99 minX = maxX = points[0].x(); |
99 minX = maxX = points[0].x(); |
100 minY = maxY = points[0].y(); |
100 minY = maxY = points[0].y(); |
101 boundingRectDirty = false; |
101 boundingRectDirty = false; |
102 } |
102 } |
103 |
103 |
104 if (!outline) |
104 if (!outline && !path.isConvex()) |
105 addCentroid(path, 0); |
105 addCentroid(path, 0); |
106 |
106 |
107 int lastMoveTo = vertexArray.size(); |
107 int lastMoveTo = vertexArray.size(); |
108 vertexArray.add(points[0]); // The first element is always a moveTo |
108 vertexArray.add(points[0]); // The first element is always a moveTo |
109 |
109 |
118 break; |
118 break; |
119 } |
119 } |
120 // qDebug("QVectorPath has element types"); |
120 // qDebug("QVectorPath has element types"); |
121 |
121 |
122 for (int i=1; i<path.elementCount(); ++i) { |
122 for (int i=1; i<path.elementCount(); ++i) { |
123 const QPainterPath::ElementType elementType = elements[i]; |
123 switch (elements[i]) { |
124 switch (elementType) { |
|
125 case QPainterPath::MoveToElement: |
124 case QPainterPath::MoveToElement: |
126 if (!outline) |
125 if (!outline) |
127 addClosingLine(lastMoveTo); |
126 addClosingLine(lastMoveTo); |
128 // qDebug("element[%d] is a MoveToElement", i); |
127 // qDebug("element[%d] is a MoveToElement", i); |
129 vertexArrayStops.append(vertexArray.size()); |
128 vertexArrayStops.add(vertexArray.size()); |
130 if (!outline) { |
129 if (!outline) { |
131 addCentroid(path, i); |
130 if (!path.isConvex()) addCentroid(path, i); |
132 lastMoveTo = vertexArray.size(); |
131 lastMoveTo = vertexArray.size(); |
133 } |
132 } |
134 lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex |
133 lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex |
135 break; |
134 break; |
136 case QPainterPath::LineToElement: |
135 case QPainterPath::LineToElement: |
137 // qDebug("element[%d] is a LineToElement", i); |
136 // qDebug("element[%d] is a LineToElement", i); |
138 lineToArray(points[i].x(), points[i].y()); |
137 lineToArray(points[i].x(), points[i].y()); |
139 break; |
138 break; |
140 case QPainterPath::CurveToElement: |
139 case QPainterPath::CurveToElement: { |
141 // qDebug("element[%d] is a CurveToElement", i); |
140 QBezier b = QBezier::fromPoints(*(((const QPointF *) points) + i - 1), |
142 curveToArray(points[i], points[i+1], points[i+2], curveInverseScale); |
141 points[i], |
143 i+=2; |
142 points[i+1], |
144 break; |
143 points[i+2]); |
|
144 QRectF bounds = b.bounds(); |
|
145 // threshold based on same algorithm as in qtriangulatingstroker.cpp |
|
146 int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6)); |
|
147 if (threshold < 3) threshold = 3; |
|
148 qreal one_over_threshold_minus_1 = 1.f / (threshold - 1); |
|
149 for (int t=0; t<threshold; ++t) { |
|
150 QPointF pt = b.pointAt(t * one_over_threshold_minus_1); |
|
151 lineToArray(pt.x(), pt.y()); |
|
152 } |
|
153 i += 2; |
|
154 break; } |
145 default: |
155 default: |
146 break; |
156 break; |
147 } |
157 } |
148 } |
158 } |
149 } while (0); |
159 } while (0); |
150 |
160 |
151 if (!outline) |
161 if (!outline) |
152 addClosingLine(lastMoveTo); |
162 addClosingLine(lastMoveTo); |
153 vertexArrayStops.append(vertexArray.size()); |
163 vertexArrayStops.add(vertexArray.size()); |
154 } |
164 } |
155 |
165 |
156 void QGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y) |
166 void QGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y) |
157 { |
167 { |
158 vertexArray.add(QGLPoint(x, y)); |
168 vertexArray.add(QGLPoint(x, y)); |
165 maxY = y; |
175 maxY = y; |
166 else if (y < minY) |
176 else if (y < minY) |
167 minY = y; |
177 minY = y; |
168 } |
178 } |
169 |
179 |
170 void QGL2PEXVertexArray::curveToArray(const QGLPoint &cp1, const QGLPoint &cp2, const QGLPoint &ep, GLfloat inverseScale) |
|
171 { |
|
172 qreal inverseScaleHalf = inverseScale / 2; |
|
173 |
|
174 QBezier beziers[32]; |
|
175 beziers[0] = QBezier::fromPoints(vertexArray.last(), cp1, cp2, ep); |
|
176 QBezier *b = beziers; |
|
177 while (b >= beziers) { |
|
178 // check if we can pop the top bezier curve from the stack |
|
179 qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1); |
|
180 qreal d; |
|
181 if (l > inverseScale) { |
|
182 d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) ) |
|
183 + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) ); |
|
184 d /= l; |
|
185 } else { |
|
186 d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) + |
|
187 qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3); |
|
188 } |
|
189 if (d < inverseScaleHalf || b == beziers + 31) { |
|
190 // good enough, we pop it off and add the endpoint |
|
191 lineToArray(b->x4, b->y4); |
|
192 --b; |
|
193 } else { |
|
194 // split, second half of the polygon goes lower into the stack |
|
195 b->split(b+1, b); |
|
196 ++b; |
|
197 } |
|
198 } |
|
199 } |
|
200 |
|
201 QT_END_NAMESPACE |
180 QT_END_NAMESPACE |