Ejemplo n.º 1
0
void Path::addRoundedRectangle (const float x, const float y, const float w, const float h,
                                float csx, float csy,
                                const bool curveTopLeft, const bool curveTopRight,
                                const bool curveBottomLeft, const bool curveBottomRight)
{
    csx = jmin (csx, w * 0.5f);
    csy = jmin (csy, h * 0.5f);
    const float cs45x = csx * 0.45f;
    const float cs45y = csy * 0.45f;
    const float x2 = x + w;
    const float y2 = y + h;

    if (curveTopLeft)
    {
        startNewSubPath (x, y + csy);
        cubicTo (x, y + cs45y, x + cs45x, y, x + csx, y);
    }
    else
    {
        startNewSubPath (x, y);
    }

    if (curveTopRight)
    {
        lineTo (x2 - csx, y);
        cubicTo (x2 - cs45x, y, x2, y + cs45y, x2, y + csy);
    }
    else
    {
        lineTo (x2, y);
    }

    if (curveBottomRight)
    {
        lineTo (x2, y2 - csy);
        cubicTo (x2, y2 - cs45y, x2 - cs45x, y2, x2 - csx, y2);
    }
    else
    {
        lineTo (x2, y2);
    }

    if (curveBottomLeft)
    {
        lineTo (x + csx, y2);
        cubicTo (x + cs45x, y2, x, y2 - cs45y, x, y2 - csy);
    }
    else
    {
        lineTo (x, y2);
    }

    closeSubPath();
}
Ejemplo n.º 2
0
 void Path::addRectangle(const double x, const double y, const double w, const double h,
                         double rx, double ry, const char corner) noexcept
 {
     rx = clip(rx, 0., w * 0.5f);
     ry = clip(ry, 0., h * 0.5f);
     const double r45x = rx * 0.45f;
     const double r45y = ry * 0.45f;
     const double x2 = x + w;
     const double y2 = y + h;
     
     if (corner & Rectangle::TopLeft)
     {
         addNode(Node(Point(x, y + ry), Move));
         cubicTo(Point(x, y + r45y), Point(x + r45x, y), Point(x + rx, y));
     }
     else
     {
         addNode(Node(Point(x, y), Move));
     }
     
     if (corner & Rectangle::TopRight)
     {
         lineTo(Point(x2 - rx, y));
         cubicTo(Point(x2 - r45x, y), Point(x2, y + r45y), Point(x2, y + ry));
     }
     else
     {
         lineTo(Point(x2, y));
     }
     
     if (corner & Rectangle::BottomRight)
     {
         lineTo(Point(x2, y2 - ry));
         cubicTo(Point(x2, y2 - r45y), Point(x2 - r45x, y2), Point(x2 - rx, y2));
     }
     else
     {
         lineTo(Point(x2, y2));
     }
     
     if (corner & Rectangle::BottomLeft)
     {
         lineTo(Point(x + rx, y2));
         cubicTo(Point(x + r45x, y2), Point(x, y2 - r45y), Point(x, y2 - ry));
     }
     else
     {
         lineTo(Point(x, y2));
     }
     
     close();
 }
Ejemplo n.º 3
0
void Path::addEllipse (Rectangle<float> area)
{
    const float hw = area.getWidth() * 0.5f;
    const float hw55 = hw * 0.55f;
    const float hh = area.getHeight() * 0.5f;
    const float hh55 = hh * 0.55f;
    const float cx = area.getX() + hw;
    const float cy = area.getY() + hh;

    startNewSubPath (cx, cy - hh);
    cubicTo (cx + hw55, cy - hh, cx + hw, cy - hh55, cx + hw, cy);
    cubicTo (cx + hw, cy + hh55, cx + hw55, cy + hh, cx, cy + hh);
    cubicTo (cx - hw55, cy + hh, cx - hw, cy + hh55, cx - hw, cy);
    cubicTo (cx - hw, cy - hh55, cx - hw55, cy - hh, cx, cy - hh);
    closeSubPath();
}
Ejemplo n.º 4
0
 void Path::addEllipse(Rectangle const& rect) noexcept
 {
     const double hw = rect.width() * 0.5f;
     const double hw55 = hw * 0.55f;
     const double hh = rect.height() * 0.5f;
     const double hh55 = hh * 0.55f;
     const double cx = rect.x() + hw;
     const double cy = rect.y() + hh;
     
     moveTo(Point(cx, cy - hh));
     cubicTo(Point(cx + hw55, cy - hh), Point(cx + hw, cy - hh55), Point(cx + hw, cy));
     cubicTo(Point(cx + hw, cy + hh55), Point(cx + hw55, cy + hh), Point(cx, cy + hh));
     cubicTo(Point(cx - hw55, cy + hh), Point(cx - hw, cy + hh55), Point(cx - hw, cy));
     cubicTo(Point(cx - hw, cy - hh55), Point(cx - hw55, cy - hh), Point(cx, cy - hh));
     close();
 }
Ejemplo n.º 5
0
	void ShapeMaker::cubicTo (const Bezier &cubic)
	{
		const double sqrt3 = 1.7320508075688772935274463415059;
		const double precision = 600 * 18 / (60 * factorx * sqrt3);

		// distance between control points of quadratic approximations of either end
		double D01 = (cubic.p1 - (cubic.c1 - cubic.c0) * 3 - cubic.p0).magnitude () / 2;

		double tMax3 = precision / D01;
		if (tMax3 >= 1)
		{
			curveTo (cubic.quadraticCtrl(), cubic.p1);
			return;
		}

		Bezier end(cubic);

		if (tMax3 >= 0.5 * 0.5 * 0.5)
		{
			Bezier start (end.split (0.5));
			curveTo (start.quadraticCtrl (), start.p1);
		}
		else
		{
			double tMax = pow (tMax3, 1.0/3.0);
			Bezier start (end.split (tMax));
			Bezier middle (end.split (1 - tMax / (1 - tMax)));

			curveTo (start.quadraticCtrl (), start.p1);
			cubicTo (middle);
		}

		curveTo (end.quadraticCtrl (), end.p1);
	}
void Path::addEllipse (const float x, const float y,
                       const float w, const float h)
{
    const float hw = w * 0.5f;
    const float hw55 = hw * 0.55f;
    const float hh = h * 0.5f;
    const float hh55 = hh * 0.55f;
    const float cx = x + hw;
    const float cy = y + hh;

    startNewSubPath (cx, cy - hh);
    cubicTo (cx + hw55, cy - hh, cx + hw, cy - hh55, cx + hw, cy);
    cubicTo (cx + hw, cy + hh55, cx + hw55, cy + hh, cx, cy + hh);
    cubicTo (cx - hw55, cy + hh, cx - hw, cy + hh55, cx - hw, cy);
    cubicTo (cx - hw, cy - hh55, cx - hw55, cy - hh, cx, cy - hh);
    closeSubPath();
}
Ejemplo n.º 7
0
void Path::cubicTo (const Point<float> controlPoint1,
                    const Point<float> controlPoint2,
                    const Point<float> endPoint)
{
    cubicTo (controlPoint1.x, controlPoint1.y,
             controlPoint2.x, controlPoint2.y,
             endPoint.x, endPoint.y);
}
Ejemplo n.º 8
0
void Path::addPath (const Path& other,
                    const AffineTransform& transformToApply)
{
    size_t i = 0;
    const float* const d = other.data.elements;

    while (i < other.numElements)
    {
        const float type = d [i++];

        if (type == closeSubPathMarker)
        {
            closeSubPath();
        }
        else
        {
            float x = d[i++];
            float y = d[i++];
            transformToApply.transformPoint (x, y);

            if (type == moveMarker)
            {
                startNewSubPath (x, y);
            }
            else if (type == lineMarker)
            {
                lineTo (x, y);
            }
            else if (type == quadMarker)
            {
                float x2 = d [i++];
                float y2 = d [i++];
                transformToApply.transformPoint (x2, y2);

                quadraticTo (x, y, x2, y2);
            }
            else if (type == cubicMarker)
            {
                float x2 = d [i++];
                float y2 = d [i++];
                float x3 = d [i++];
                float y3 = d [i++];
                transformToApply.transformPoints (x2, y2, x3, y3);

                cubicTo (x, y, x2, y2, x3, y3);
            }
            else
            {
                // something's gone wrong with the element list!
                jassertfalse;
            }
        }
    }
}
void Path::addRoundedRectangle (const float x, const float y,
                                const float w, const float h,
                                float csx,
                                float csy)
{
    csx = jmin (csx, w * 0.5f);
    csy = jmin (csy, h * 0.5f);
    const float cs45x = csx * 0.45f;
    const float cs45y = csy * 0.45f;
    const float x2 = x + w;
    const float y2 = y + h;

    startNewSubPath (x + csx, y);
    lineTo (x2 - csx, y);
    cubicTo (x2 - cs45x, y, x2, y + cs45y, x2, y + csy);
    lineTo (x2, y2 - csy);
    cubicTo (x2, y2 - cs45y, x2 - cs45x, y2, x2 - csx, y2);
    lineTo (x + csx, y2);
    cubicTo (x + cs45x, y2, x, y2 - cs45y, x, y2 - csy);
    lineTo (x, y + csy);
    cubicTo (x, y + cs45y, x + cs45x, y, x + csx, y);
    closeSubPath();
}
Ejemplo n.º 10
0
void Path::addPath (const Path& other)
{
    size_t i = 0;
    const float* const d = other.data.elements;

    while (i < other.numElements)
    {
        const float type = d[i++];

        if (type == moveMarker)
        {
            startNewSubPath (d[i], d[i + 1]);
            i += 2;
        }
        else if (type == lineMarker)
        {
            lineTo (d[i], d[i + 1]);
            i += 2;
        }
        else if (type == quadMarker)
        {
            quadraticTo (d[i], d[i + 1], d[i + 2], d[i + 3]);
            i += 4;
        }
        else if (type == cubicMarker)
        {
            cubicTo (d[i], d[i + 1], d[i + 2], d[i + 3], d[i + 4], d[i + 5]);
            i += 6;
        }
        else if (type == closeSubPathMarker)
        {
            closeSubPath();
        }
        else
        {
            // something's gone wrong with the element list!
            jassertfalse;
        }
    }
}
Ejemplo n.º 11
0
	void ShapeMaker::cubicTo(double x1, double y1, double x2, double y2, double ax, double ay) {
		Point a(lastx,lasty);
		Point b(x1,y1);
		Point c(x2,y2);
		Point d(ax,ay);

		Bezier cubic (a, b, c, d);

		double t0, t1;
		int cInflections = cubic.computeInflections (t0, t1);

		if (cInflections == 0)
		{
			cubicTo(cubic);
		}
		else if (cInflections == 1)
		{
			Bezier cubic0 = cubic.split (t0);
			cubicTo (cubic0);
			cubicTo (cubic);
		}
		else
		{
			Bezier cubic0 = cubic.split (t0);
			cubicTo (cubic0);

			Bezier cubic1 = cubic.split (1 - (1 - t1) / (1 - t0));
			cubicTo (cubic1);

			cubicTo (cubic);
		}

		lastx = ax; lasty = ay;
		smoothx = ax - x2;
		smoothy = ay - y2;
	}
Ejemplo n.º 12
0
void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &)
{
    const qreal *pts = path.points();
    const QPainterPath::ElementType *types = path.elements();
    int count = path.elementCount();
    if (count < 2)
        return;

    float realWidth = qpen_widthf(pen);
    if (realWidth == 0)
        realWidth = 1;

    m_width = realWidth / 2;

    bool cosmetic = pen.isCosmetic();
    if (cosmetic) {
        m_width = m_width * m_inv_scale;
    }

    m_join_style = qpen_joinStyle(pen);
    m_cap_style = qpen_capStyle(pen);
    m_vertices.reset();
    m_miter_limit = pen.miterLimit() * qpen_widthf(pen);

    // The curvyness is based on the notion that I originally wanted
    // roughly one line segment pr 4 pixels. This may seem little, but
    // because we sample at constantly incrementing B(t) E [0<t<1], we
    // will get longer segments where the curvature is small and smaller
    // segments when the curvature is high.
    //
    // To get a rough idea of the length of each curve, I pretend that
    // the curve is a 90 degree arc, whose radius is
    // qMax(curveBounds.width, curveBounds.height). Based on this
    // logic we can estimate the length of the outline edges based on
    // the radius + a pen width and adjusting for scale factors
    // depending on if the pen is cosmetic or not.
    //
    // The curvyness value of PI/14 was based on,
    // arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere
    // between 3 and 8 where 5 seemed to be give pretty good results
    // hence: Q_PI/14. Lower divisors will give more detail at the
    // direct cost of performance.

    // simplfy pens that are thin in device size (2px wide or less)
    if (realWidth < 2.5 && (cosmetic || m_inv_scale == 1)) {
        if (m_cap_style == Qt::RoundCap)
            m_cap_style = Qt::SquareCap;
        if (m_join_style == Qt::RoundJoin)
            m_join_style = Qt::MiterJoin;
        m_curvyness_add = 0.5;
        m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;
        m_roundness = 1;
    } else if (cosmetic) {
        m_curvyness_add = realWidth / 2;
        m_curvyness_mul = CURVE_FLATNESS;
        m_roundness = qMax<int>(4, realWidth * CURVE_FLATNESS);
    } else {
        m_curvyness_add = m_width;
        m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;
        m_roundness = qMax<int>(4, realWidth * m_curvyness_mul);
    }

    // Over this level of segmentation, there doesn't seem to be any
    // benefit, even for huge penWidth
    if (m_roundness > 24)
        m_roundness = 24;

    m_sin_theta = qFastSin(Q_PI / m_roundness);
    m_cos_theta = qFastCos(Q_PI / m_roundness);

    const qreal *endPts = pts + (count<<1);
    const qreal *startPts = 0;

    Qt::PenCapStyle cap = m_cap_style;

    if (!types) {
        // skip duplicate points
        while((pts + 2) < endPts && pts[0] == pts[2] && pts[1] == pts[3])
            pts += 2;
        if ((pts + 2) == endPts)
            return;

        startPts = pts;

        bool endsAtStart = startPts[0] == *(endPts-2) && startPts[1] == *(endPts-1);

        if (endsAtStart || path.hasImplicitClose())
            m_cap_style = Qt::FlatCap;
        moveTo(pts);
        m_cap_style = cap;
        pts += 2;
        lineTo(pts);
        pts += 2;
        while (pts < endPts) {
            if (m_cx != pts[0] || m_cy != pts[1]) {
                join(pts);
                lineTo(pts);
            }
            pts += 2;
        }

        endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);

    } else {
        bool endsAtStart = false;
        while (pts < endPts) {
            switch (*types) {
            case QPainterPath::MoveToElement: {
                if (pts != path.points())
                    endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);

                startPts = pts;
                int end = (endPts - pts) / 2;
                int i = 2; // Start looking to ahead since we never have two moveto's in a row
                while (i<end && types[i] != QPainterPath::MoveToElement) {
                    ++i;
                }
                endsAtStart = startPts[0] == pts[i*2 - 2] && startPts[1] == pts[i*2 - 1];
                if (endsAtStart || path.hasImplicitClose())
                    m_cap_style = Qt::FlatCap;

                moveTo(pts);
                m_cap_style = cap;
                pts+=2;
                ++types;
                break; }
            case QPainterPath::LineToElement:
                if (*(types - 1) != QPainterPath::MoveToElement)
                    join(pts);
                lineTo(pts);
                pts+=2;
                ++types;
                break;
            case QPainterPath::CurveToElement:
                if (*(types - 1) != QPainterPath::MoveToElement)
                    join(pts);
                cubicTo(pts);
                pts+=6;
                types+=3;
                break;
            default:
                Q_ASSERT(false);
                break;
            }
        }

        endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);
    }
}
Ejemplo n.º 13
0
void WPainterPath::cubicTo(const WPointF& c1, const WPointF& c2,
			   const WPointF& endPoint)
{
  cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), endPoint.x(), endPoint.y());
}
Ejemplo n.º 14
0
void ShapeMaker::smoothCubicTo( double x2, double y2, double ax, double ay ) {
	cubicTo( lastx + smoothx, lasty + smoothy, x2, y2, ax, ay );

}
Ejemplo n.º 15
0
void ShapeMaker::cubicToR( double x1, double y1, double x2, double y2, double ax, double ay ) {
	cubicTo(lastx + x1, lasty + y1,
	        lastx + x2, lasty + y2,
	        lastx + ax, lasty + ay);
}
Ejemplo n.º 16
0
void Path::restoreFromString (StringRef stringVersion)
{
    clear();
    setUsingNonZeroWinding (true);

    String::CharPointerType t (stringVersion.text);
    juce_wchar marker = 'm';
    int numValues = 2;
    float values [6];

    for (;;)
    {
        const String token (PathHelpers::nextToken (t));
        const juce_wchar firstChar = token[0];
        int startNum = 0;

        if (firstChar == 0)
            break;

        if (firstChar == 'm' || firstChar == 'l')
        {
            marker = firstChar;
            numValues = 2;
        }
        else if (firstChar == 'q')
        {
            marker = firstChar;
            numValues = 4;
        }
        else if (firstChar == 'c')
        {
            marker = firstChar;
            numValues = 6;
        }
        else if (firstChar == 'z')
        {
            marker = firstChar;
            numValues = 0;
        }
        else if (firstChar == 'a')
        {
            setUsingNonZeroWinding (false);
            continue;
        }
        else
        {
            ++startNum;
            values [0] = token.getFloatValue();
        }

        for (int i = startNum; i < numValues; ++i)
            values [i] = PathHelpers::nextToken (t).getFloatValue();

        switch (marker)
        {
            case 'm':   startNewSubPath (values[0], values[1]); break;
            case 'l':   lineTo (values[0], values[1]); break;
            case 'q':   quadraticTo (values[0], values[1], values[2], values[3]); break;
            case 'c':   cubicTo (values[0], values[1], values[2], values[3], values[4], values[5]); break;
            case 'z':   closeSubPath(); break;
            default:    jassertfalse; break; // illegal string format?
        }
    }
}
Ejemplo n.º 17
0
//==============================================================================
void Path::loadPathFromStream (InputStream& source)
{
    while (! source.isExhausted())
    {
        switch (source.readByte())
        {
        case 'm':
        {
            const float x = source.readFloat();
            const float y = source.readFloat();
            startNewSubPath (x, y);
            break;
        }

        case 'l':
        {
            const float x = source.readFloat();
            const float y = source.readFloat();
            lineTo (x, y);
            break;
        }

        case 'q':
        {
            const float x1 = source.readFloat();
            const float y1 = source.readFloat();
            const float x2 = source.readFloat();
            const float y2 = source.readFloat();
            quadraticTo (x1, y1, x2, y2);
            break;
        }

        case 'b':
        {
            const float x1 = source.readFloat();
            const float y1 = source.readFloat();
            const float x2 = source.readFloat();
            const float y2 = source.readFloat();
            const float x3 = source.readFloat();
            const float y3 = source.readFloat();
            cubicTo (x1, y1, x2, y2, x3, y3);
            break;
        }

        case 'c':
            closeSubPath();
            break;

        case 'n':
            useNonZeroWinding = true;
            break;

        case 'z':
            useNonZeroWinding = false;
            break;

        case 'e':
            return; // end of path marker

        default:
            jassertfalse; // illegal char in the stream
            break;
        }
    }
}