#include "private/qstroker_p.h"
#include "private/qbezier_p.h"
#include "private/qmath_p.h"
#include "qline.h"
Include dependency graph for qstroker.cpp:

Go to the source code of this file.
Classes | |
| class | QSubpathForwardIterator |
| class | QSubpathBackwardIterator |
| class | QSubpathFlatIterator |
Defines | |
| #define | ANGLE(t) ((t) * 2 * Q_PI / 360.0) |
| #define | SIGN(t) (t > 0 ? 1 : -1) |
Functions | |
| template<class Iterator> | |
| bool | qt_stroke_side (Iterator *it, QStroker *stroker, bool capFirst, QLineF *startTangent) |
| static qreal | adapted_angle_on_x (const QLineF &line) |
| QPointF | qt_curves_for_arc (const QRectF &rect, qreal startAngle, qreal sweepLength, QPointF *curves, int *point_count) |
| #define ANGLE | ( | t | ) | ((t) * 2 * Q_PI / 360.0) |
| #define SIGN | ( | t | ) | (t > 0 ? 1 : -1) |
Referenced by qt_curves_for_arc().
| static qreal adapted_angle_on_x | ( | const QLineF & | line | ) | [inline, static] |
Definition at line 159 of file qstroker.cpp.
References angle(), QLineF::angle(), and QLineF::dy().
Referenced by QStroker::joinPoints().
00160 { 00161 qreal angle = line.angle(QLineF(0, 0, 1, 0)); 00162 if (line.dy() > 0) 00163 angle = 360 - angle; 00164 return angle; 00165 }
Here is the call graph for this function:

| QPointF qt_curves_for_arc | ( | const QRectF & | rect, | |
| qreal | startAngle, | |||
| qreal | sweepLength, | |||
| QPointF * | curves, | |||
| int * | point_count | |||
| ) |
Definition at line 722 of file qstroker.cpp.
References a, ANGLE, b, ceil, QRectF::center(), h, QRectF::height(), i, int, QRectF::isNull(), QLineF::length(), QLineF::p2(), qCos, qIsNan(), qSin, QT_PATH_KAPPA, qWarning(), QLineF::setLength(), SIGN, w, QRectF::width(), QRectF::x(), x, QRectF::y(), and y.
Referenced by QPainterPath::addEllipse(), QPainterPath::arcTo(), QRasterPaintEngine::drawEllipse(), QStroker::joinPoints(), and QStrokerOps::strokeEllipse().
00724 { 00725 Q_ASSERT(point_count); 00726 Q_ASSERT(curves); 00727 00728 #ifndef QT_NO_DEBUG 00729 if (qIsNan(rect.x()) || qIsNan(rect.y()) || qIsNan(rect.width()) || qIsNan(rect.height()) 00730 || qIsNan(startAngle) || qIsNan(sweepLength)) 00731 qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined"); 00732 #endif 00733 *point_count = 0; 00734 00735 if (rect.isNull()) { 00736 return QPointF(); 00737 } 00738 00739 if (sweepLength > 360) sweepLength = 360; 00740 else if (sweepLength < -360) sweepLength = -360; 00741 00742 // Special case fast path 00743 if (startAngle == 0.0 && sweepLength == 360.0) { 00744 qreal x = rect.x(); 00745 qreal y = rect.y(); 00746 00747 qreal w = rect.width(); 00748 qreal w2 = rect.width() / 2; 00749 qreal w2k = w2 * QT_PATH_KAPPA; 00750 00751 qreal h = rect.height(); 00752 qreal h2 = rect.height() / 2; 00753 qreal h2k = h2 * QT_PATH_KAPPA; 00754 00755 // 0 -> 270 degrees 00756 curves[(*point_count)++] = QPointF(x + w, y + h2 + h2k); 00757 curves[(*point_count)++] = QPointF(x + w2 + w2k, y + h); 00758 curves[(*point_count)++] = QPointF(x + w2, y + h); 00759 00760 // 270 -> 180 degrees 00761 curves[(*point_count)++] = QPointF(x + w2 - w2k, y + h); 00762 curves[(*point_count)++] = QPointF(x, y + h2 + h2k); 00763 curves[(*point_count)++] = QPointF(x, y + h2); 00764 00765 // 180 -> 90 degrees 00766 curves[(*point_count)++] = QPointF(x, y + h2 - h2k); 00767 curves[(*point_count)++] = QPointF(x + w2 - w2k, y); 00768 curves[(*point_count)++] = QPointF(x + w2, y); 00769 00770 // 90 -> 0 degrees 00771 curves[(*point_count)++] = QPointF(x + w2 + w2k, y); 00772 curves[(*point_count)++] = QPointF(x + w, y + h2 - h2k); 00773 curves[(*point_count)++] = QPointF(x + w, y + h2); 00774 00775 return QPointF(x + w, y + h2); 00776 } 00777 00778 #define ANGLE(t) ((t) * 2 * Q_PI / 360.0) 00779 #define SIGN(t) (t > 0 ? 1 : -1) 00780 qreal a = rect.width() / 2.0; 00781 qreal b = rect.height() / 2.0; 00782 00783 qreal absSweepLength = (sweepLength < 0 ? -sweepLength : sweepLength); 00784 int iterations = (int)ceil((absSweepLength) / 90.0); 00785 00786 QPointF first_point; 00787 00788 if (iterations == 0) { 00789 first_point = rect.center() + QPointF(a * qCos(ANGLE(startAngle)), 00790 -b * qSin(ANGLE(startAngle))); 00791 } else { 00792 qreal clength = sweepLength / iterations; 00793 qreal cosangle1, sinangle1, cosangle2, sinangle2; 00794 00795 for (int i=0; i<iterations; ++i) { 00796 qreal cangle = startAngle + i * clength; 00797 00798 cosangle1 = qCos(ANGLE(cangle)); 00799 sinangle1 = qSin(ANGLE(cangle)); 00800 cosangle2 = qCos(ANGLE(cangle + clength)); 00801 sinangle2 = qSin(ANGLE(cangle + clength)); 00802 00803 // Find the start and end point of the curve. 00804 QPointF startPoint = rect.center() + QPointF(a * cosangle1, -b * sinangle1); 00805 QPointF endPoint = rect.center() + QPointF(a * cosangle2, -b * sinangle2); 00806 00807 // The derived at the start and end point. 00808 qreal sdx = -a * sinangle1; 00809 qreal sdy = -b * cosangle1; 00810 qreal edx = -a * sinangle2; 00811 qreal edy = -b * cosangle2; 00812 00813 // Creating the tangent lines. We need to reverse their direction if the 00814 // sweep is negative (clockwise) 00815 QLineF controlLine1(startPoint, startPoint + SIGN(sweepLength) * QPointF(sdx, sdy)); 00816 QLineF controlLine2(endPoint, endPoint - SIGN(sweepLength) * QPointF(edx, edy)); 00817 00818 // We need to scale down the control lines to match that of the current sweeplength. 00819 // qAbs because we only want to scale, not change direction. 00820 qreal kappa = QT_PATH_KAPPA * qAbs(clength) / 90.0; 00821 // Adjust their length to fit the magic KAPPA length. 00822 controlLine1.setLength(controlLine1.length() * kappa); 00823 controlLine2.setLength(controlLine2.length() * kappa); 00824 00825 curves[(*point_count)++] = controlLine1.p2(); 00826 curves[(*point_count)++] = controlLine2.p2(); 00827 curves[(*point_count)++] = endPoint; 00828 00829 if (i == 0) 00830 first_point = startPoint; 00831 } 00832 } 00833 00834 return first_point; 00835 }
Here is the call graph for this function:

| bool qt_stroke_side | ( | Iterator * | it, | |
| QStroker * | stroker, | |||
| bool | capFirst, | |||
| QLineF * | startTangent | |||
| ) |
Definition at line 579 of file qstroker.cpp.
References QStroker::capStyleMode(), QStroker::curveThreshold(), QLineF::dx(), QLineF::dy(), QStroker::emitCubicTo(), QStroker::emitLineTo(), QStroker::emitMoveTo(), QBezier::fromPoints(), i, QStroker::joinPoints(), QStroker::joinStyleMode(), QLineF::normalVector(), QBezier::pt1(), QBezier::pt3(), QBezier::pt4(), qDebug(), qt_fixed_to_real, qt_real_to_fixed, QLineF::setLength(), QBezier::shifted(), start, QStroker::strokeWidth(), QLineF::translate(), qfixed2d::x, QStrokerOps::Element::x, QPointF::x(), QLineF::x1(), QLineF::x2(), qfixed2d::y, QStrokerOps::Element::y, QPointF::y(), QLineF::y1(), and QLineF::y2().
Referenced by QStroker::processCurrentSubpath().
00583 { 00584 // Used in CurveToElement section below. 00585 const int MAX_OFFSET = 16; 00586 QBezier offsetCurves[MAX_OFFSET]; 00587 00588 Q_ASSERT(it->hasNext()); // The initaial move to 00589 QStrokerOps::Element first_element = it->next(); 00590 Q_ASSERT(first_element.isMoveTo()); 00591 00592 qfixed2d start = first_element; 00593 00594 #ifdef QPP_STROKE_DEBUG 00595 qDebug(" -> (side) [%.2f, %.2f], startPos=%d", 00596 qt_fixed_to_real(start.x), 00597 qt_fixed_to_real(start.y)); 00598 #endif 00599 00600 qfixed2d prev = start; 00601 00602 bool first = true; 00603 00604 qfixed offset = stroker->strokeWidth() / 2; 00605 00606 while (it->hasNext()) { 00607 QStrokerOps::Element e = it->next(); 00608 00609 // LineToElement 00610 if (e.isLineTo()) { 00611 #ifdef QPP_STROKE_DEBUG 00612 qDebug("\n ---> (side) lineto [%.2f, %.2f]", e.x, e.y); 00613 #endif 00614 QLineF line(qt_fixed_to_real(prev.x), qt_fixed_to_real(prev.y), 00615 qt_fixed_to_real(e.x), qt_fixed_to_real(e.y)); 00616 QLineF normal = line.normalVector(); 00617 normal.setLength(offset); 00618 line.translate(normal.dx(), normal.dy()); 00619 00620 // If we are starting a new subpath, move to correct starting point. 00621 if (first) { 00622 if (capFirst) 00623 stroker->joinPoints(prev.x, prev.y, line, stroker->capStyleMode()); 00624 else 00625 stroker->emitMoveTo(qt_real_to_fixed(line.x1()), qt_real_to_fixed(line.y1())); 00626 *startTangent = line; 00627 first = false; 00628 } else { 00629 stroker->joinPoints(prev.x, prev.y, line, stroker->joinStyleMode()); 00630 } 00631 00632 // Add the stroke for this line. 00633 stroker->emitLineTo(qt_real_to_fixed(line.x2()), 00634 qt_real_to_fixed(line.y2())); 00635 prev = e; 00636 00637 // CurveToElement 00638 } else if (e.isCurveTo()) { 00639 QStrokerOps::Element cp2 = it->next(); // control point 2 00640 QStrokerOps::Element ep = it->next(); // end point 00641 00642 #ifdef QPP_STROKE_DEBUG 00643 qDebug("\n ---> (side) cubicTo [%.2f, %.2f]", 00644 qt_fixed_to_real(ep.x), 00645 qt_fixed_to_real(ep.y)); 00646 #endif 00647 00648 QBezier bezier = 00649 QBezier::fromPoints(QPointF(qt_fixed_to_real(prev.x), qt_fixed_to_real(prev.y)), 00650 QPointF(qt_fixed_to_real(e.x), qt_fixed_to_real(e.y)), 00651 QPointF(qt_fixed_to_real(cp2.x), qt_fixed_to_real(cp2.y)), 00652 QPointF(qt_fixed_to_real(ep.x), qt_fixed_to_real(ep.y))); 00653 00654 int count = bezier.shifted(offsetCurves, 00655 MAX_OFFSET, 00656 offset, 00657 stroker->curveThreshold()); 00658 00659 if (count) { 00660 // If we are starting a new subpath, move to correct starting point 00661 if (first) { 00662 QPointF pt = offsetCurves[0].pt1(); 00663 if (capFirst) { 00664 stroker->joinPoints(prev.x, prev.y, 00665 QLineF(pt, offsetCurves[0].pt2()), 00666 stroker->capStyleMode()); 00667 } else { 00668 stroker->emitMoveTo(qt_real_to_fixed(pt.x()), 00669 qt_real_to_fixed(pt.y())); 00670 } 00671 *startTangent = QLineF(offsetCurves[0].pt1(), offsetCurves[0].pt2()); 00672 first = false; 00673 } else { 00674 stroker->joinPoints(prev.x, prev.y, 00675 QLineF(offsetCurves[0].pt1(), offsetCurves[0].pt2()), 00676 stroker->joinStyleMode()); 00677 } 00678 00679 // Add these beziers 00680 for (int i=0; i<count; ++i) { 00681 QPointF cp1 = offsetCurves[i].pt2(); 00682 QPointF cp2 = offsetCurves[i].pt3(); 00683 QPointF ep = offsetCurves[i].pt4(); 00684 stroker->emitCubicTo(qt_real_to_fixed(cp1.x()), qt_real_to_fixed(cp1.y()), 00685 qt_real_to_fixed(cp2.x()), qt_real_to_fixed(cp2.y()), 00686 qt_real_to_fixed(ep.x()), qt_real_to_fixed(ep.y())); 00687 } 00688 } 00689 00690 prev = ep; 00691 } 00692 } 00693 00694 if (start == prev) { 00695 // closed subpath, join first and last point 00696 #ifdef QPP_STROKE_DEBUG 00697 qDebug("\n ---> (side) closed subpath"); 00698 #endif 00699 stroker->joinPoints(prev.x, prev.y, *startTangent, stroker->joinStyleMode()); 00700 return true; 00701 } else { 00702 #ifdef QPP_STROKE_DEBUG 00703 qDebug("\n ---> (side) open subpath"); 00704 #endif 00705 return false; 00706 } 00707 }
Here is the call graph for this function:

1.5.1