src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    46 QT_BEGIN_NAMESPACE
    46 QT_BEGIN_NAMESPACE
    47 
    47 
    48 void QGL2PEXVertexArray::clear()
    48 void QGL2PEXVertexArray::clear()
    49 {
    49 {
    50     vertexArray.reset();
    50     vertexArray.reset();
    51     vertexArrayStops.clear();
    51     vertexArrayStops.reset();
    52     boundingRectDirty = true;
    52     boundingRectDirty = true;
    53 }
    53 }
    54 
    54 
    55 
    55 
    56 QGLRect QGL2PEXVertexArray::boundingRect() const
    56 QGLRect QGL2PEXVertexArray::boundingRect() const
    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