def test_circle_line_overlap():
    # Draw a circle that is above one line but below the other line.
    p = Pen()

    p.stroke_mode(1.0, color=(1.0, 0.0, 0.0))
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(4)

    p.fill_mode(color=(0.0, 1.0, 0.0))
    p.move_to((2, 2))
    p.circle(2)

    p.stroke_mode(1.0, color=(0.0, 0.0, 1.0))
    p.move_to((0, 4))
    p.turn_to(0)
    p.line_forward(4)

    assert_equal(
        p.paper.svg_elements(1),
        [
            (
                '<path d="M0.0,-0.5 L0.0,0.5 L4.0,0.5 L4.0,-0.5 L0.0,-0.5 z" '
                'fill="#ff0000" />'
            ),
            (
                '<path d="M4.0,-2.0 A 2.0,2.0 0 0 0 0.0,-2.0 '
                'A 2.0,2.0 0 0 0 4.0,-2.0 z" fill="#00ff00" />'
            ),
            (
                '<path d="M0.0,-4.5 L0.0,-3.5 L4.0,-3.5 L4.0,-4.5 L0.0,-4.5 z" '
                'fill="#0000ff" />'
            ),
        ]
    )
def test_circle_line_overlap():
    # Draw a circle that is above one line but below the other line.
    p = Pen()

    p.stroke_mode(1.0, color=(1.0, 0.0, 0.0))
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(4)

    p.fill_mode(color=(0.0, 1.0, 0.0))
    p.move_to((2, 2))
    p.circle(2)

    p.stroke_mode(1.0, color=(0.0, 0.0, 1.0))
    p.move_to((0, 4))
    p.turn_to(0)
    p.line_forward(4)

    assert_equal(
        p.paper.svg_elements(1),
        [
            (
                '<path d="M0.0,-0.5 L0.0,0.5 L4.0,0.5 L4.0,-0.5 L0.0,-0.5 z" '
                'fill="#ff0000" />'
            ),
            (
                '<path d="M4.0,-2.0 A 2.0,2.0 0 0 0 0.0,-2.0 '
                'A 2.0,2.0 0 0 0 4.0,-2.0 z" fill="#00ff00" />'
            ),
            (
                '<path d="M0.0,-4.5 L0.0,-3.5 L4.0,-3.5 L4.0,-4.5 L0.0,-4.5 z" '
                'fill="#0000ff" />'
            ),
        ]
    )
def test_line_to_coordinate():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(45)
    p.line_to_y(3)
    assert_points_equal(p.position, (3, 3))

    for x, y in [
        (2, 1),
        (3, -4),
        (-7, -5),
        (-6, 6),
    ]:
        p = Pen()
        p.fill_mode()

        p.move_to((0, 0))
        p.turn_toward((x, y))
        p.line_to_y(y * 2)
        assert_points_equal(p.position, (x * 2, y * 2))

        p.move_to((0, 0))
        p.turn_toward((x, y))
        p.line_to_x(x * 3)
        assert_points_equal(p.position, (x * 3, y * 3))
def test_line_to_coordinate():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(45)
    p.line_to_y(3)
    assert_points_equal(p.position, (3, 3))

    for x, y in [
        (2, 1),
        (3, -4),
        (-7, -5),
        (-6, 6),
    ]:
        p = Pen()
        p.fill_mode()

        p.move_to((0, 0))
        p.turn_toward((x, y))
        p.line_to_y(y * 2)
        assert_points_equal(p.position, (x * 2, y * 2))

        p.move_to((0, 0))
        p.turn_toward((x, y))
        p.line_to_x(x * 3)
        assert_points_equal(p.position, (x * 3, y * 3))
def test_circle():
    p = Pen()
    p.fill_mode()
    p.circle(1)

    assert_equal(
        p.paper.svg_elements(0),
        ['<path d="M1,0 A 1,1 0 0 0 -1,0 A 1,1 0 0 0 1,0 z" fill="#000000" />']
    )
def test_circle():
    p = Pen()
    p.fill_mode()
    p.circle(1)

    assert_equal(
        p.paper.svg_elements(0),
        ['<path d="M1,0 A 1,1 0 0 0 -1,0 A 1,1 0 0 0 1,0 z" fill="#000000" />']
    )
def test_line():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        'M0,0 L5,0'
    )
def test_line():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        'M0,0 L5,0'
    )
def test_arc_normalize():
    # Arc angles larger than 360 behave correctly.
    p = Pen()
    p.fill_mode()
    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(360 + 90, radius=5)

    assert_path_data(
        p, 0,
        'M-5,0 A 5,5 0 0 0 0,-5'
    )
def test_arc_normalize():
    # Arc angles larger than 360 behave correctly.
    p = Pen()
    p.fill_mode()
    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(360 + 90, radius=5)

    assert_path_data(
        p, 0,
        'M-5,0 A 5,5 0 0 0 0,-5'
    )
def test_line_segments():
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(45)
    p.line_forward(2.0)

    assert_points_equal(p.position, (sqrt2, sqrt2))
    assert_equal(len(p.paper.paths), 1)
    segments = p.last_path().segments
    for actual, target in zip(segments, [
        ((0, 0), (sqrt2, sqrt2)),
    ]):
        assert_segments_equal(actual, target)
def test_line_segments():
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(45)
    p.line_forward(2.0)

    assert_points_equal(p.position, (sqrt2, sqrt2))
    assert_equal(len(p.paper.paths), 1)
    segments = p.last_path().segments
    for actual, target in zip(segments, [
        ((0, 0), (sqrt2, sqrt2)),
    ]):
        assert_segments_equal(actual, target)
def test_save_mode():
    p = Pen()
    p.stroke_mode(2.0, 'red')
    old_mode = p.mode
    p.line_forward(5)
    p.fill_mode('blue')
    p.square(2)
    p.set_mode(old_mode)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        [
            'M0,-1 L0,1 L5,1 L5,-1 L0,-1 z',
            'M4,1 L6,1 L6,-1 L4,-1 L4,1 z',
            'M5,-1 L5,1 L10,1 L10,-1 L5,-1 z',
        ]
    )
def test_change_mode():
    # Change mode but don't change colors. It starts a new path.
    p = Pen()
    p.move_to((0, 0))
    p.turn_to(0)

    p.stroke_mode(2.0, 'black')
    p.line_forward(5)
    p.fill_mode('black')
    p.line_forward(5)

    assert_equal(
        p.paper.svg_elements(0),
        [
            '<path d="M0,-1 L0,1 L5,1 L5,-1 L0,-1 z" fill="#000000" />',
            '<path d="M5,0 L10,0" fill="#000000" />',
        ]
    )
def test_mode():
    # Fill mode square.
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        'M0,0 L5,0 L5,-5 L0,-5 L0,0 z',
    )
def test_save_mode():
    p = Pen()
    p.stroke_mode(2.0, 'red')
    old_mode = p.mode
    p.line_forward(5)
    p.fill_mode('blue')
    p.square(2)
    p.set_mode(old_mode)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        [
            'M0,-1 L0,1 L5,1 L5,-1 L0,-1 z',
            'M4,1 L6,1 L6,-1 L4,-1 L4,1 z',
            'M5,-1 L5,1 L10,1 L10,-1 L5,-1 z',
        ]
    )
def test_mode():
    # Fill mode square.
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)
    p.turn_left(90)
    p.line_forward(5)

    assert_path_data(
        p, 0,
        'M0,0 L5,0 L5,-5 L0,-5 L0,0 z',
    )
def test_change_mode():
    # Change mode but don't change colors. It starts a new path.
    p = Pen()
    p.move_to((0, 0))
    p.turn_to(0)

    p.stroke_mode(2.0, 'black')
    p.line_forward(5)
    p.fill_mode('black')
    p.line_forward(5)

    assert_equal(
        p.paper.svg_elements(0),
        [
            '<path d="M0,-1 L0,1 L5,1 L5,-1 L0,-1 z" fill="#000000" />',
            '<path d="M5,0 L10,0" fill="#000000" />',
        ]
    )
def test_repr():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(1)
    p.arc_left(90, 1)

    path = p.paper.paths[0]
    line, arc = path.segments
    assert_equal(
        repr(line),
        'LineSegment(a=Point(x=0, y=0), b=Point(x=1.0, y=0.0))'
    )
    assert_equal(
        repr(arc),
        (
            'ArcSegment(a=Point(x=1.0, y=0.0), b=Point(x=2.0, y=0.9999999999999999), '
            'center=Point(x=1.0, y=1.0), radius=1, start_heading=0, end_heading=90)'
        )
    )
def test_repr():
    p = Pen()
    p.fill_mode()
    p.move_to((0, 0))
    p.turn_to(0)
    p.line_forward(1)
    p.arc_left(90, 1)

    path = p.paper.paths[0]
    line, arc = path.segments
    assert_equal(
        repr(line),
        'LineSegment(a=Point(x=0, y=0), b=Point(x=1.0, y=0.0))'
    )
    assert_equal(
        repr(arc),
        (
            'ArcSegment(a=Point(x=1.0, y=0.0), b=Point(x=2.0, y=0.9999999999999999), '
            'center=Point(x=1.0, y=1.0), radius=1, start_heading=0, end_heading=90)'
        )
    )
def test_arc():
    # Draw arcs with all four combinations of sweep and direction flags.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(90, radius=5)
    p.arc_right(270, radius=5)

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_right(90, radius=5)
    p.arc_left(270, radius=5)

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        )
    )
def test_arc_center():
    # Draw the same arcs as in test_arc, but using centers instead of radii.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(90, center=(-5, 5))
    p.arc_right(270, center=(5, 5))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_right(90, center=(-5, -5))
    p.arc_left(270, center=(5, -5))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc_center():
    # Draw the same arcs as in test_arc, but using centers instead of radii.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(90, center=(-5, 5))
    p.arc_right(270, center=(5, 5))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_right(90, center=(-5, -5))
    p.arc_left(270, center=(5, -5))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc():
    # Draw arcs with all four combinations of sweep and direction flags.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_left(90, radius=5)
    p.arc_right(270, radius=5)

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_right(90, radius=5)
    p.arc_left(270, radius=5)

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        )
    )
def test_arc_to():
    # Make the same arcs as test_arc, but using the destination points instead
    # of the angles.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, 5))
    p.arc_to((5, 0))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, -5))
    p.arc_to((5, 0))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc_to():
    # Make the same arcs as test_arc, but using the destination points instead
    # of the angles.
    p = Pen()
    p.fill_mode()

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, 5))
    p.arc_to((5, 0))

    p.move_to((-5, 0))
    p.turn_to(0)
    p.arc_to((0, -5))
    p.arc_to((5, 0))

    assert_path_data(
        p, 0,
        (
            'M-5,0 A 5,5 0 0 0 0,-5 A 5,5 0 1 1 5,0 '
            'M-5,0 A 5,5 0 0 1 0,5 A 5,5 0 1 0 5,0'
        ),
    )
def test_arc_start_slant_bug():
    # Some arcs are not reporting their start and end slants correctly.

    # Set up positions on a circle at angles -120 and 30
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(30)
    p.move_forward(3)
    p1 = p.position
    p.turn_left(90)
    h1 = p.heading

    p.move_to((0, 0))
    p.turn_to(-120)
    p.move_forward(3)
    p2 = p.position

    # Create an arc using arc_left.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_left(210, 3)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading, 120)
    assert_almost_equal(arc.end_heading, 330)

    # Create the same arc using arc_to.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_to(p2)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading.theta, 120)
    assert_almost_equal(arc.end_heading.theta, 330)
def test_arc_start_slant_bug():
    # Some arcs are not reporting their start and end slants correctly.

    # Set up positions on a circle at angles -120 and 30
    p = Pen()
    p.fill_mode()

    p.move_to((0, 0))
    p.turn_to(30)
    p.move_forward(3)
    p1 = p.position
    p.turn_left(90)
    h1 = p.heading

    p.move_to((0, 0))
    p.turn_to(-120)
    p.move_forward(3)
    p2 = p.position

    # Create an arc using arc_left.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_left(210, 3)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading, 120)
    assert_almost_equal(arc.end_heading, 330)

    # Create the same arc using arc_to.
    p = Pen()
    p.fill_mode()

    p.move_to(p1)
    p.turn_to(h1)
    p.arc_to(p2)
    arc = p.last_segment()
    assert_almost_equal(arc.start_heading.theta, 120)
    assert_almost_equal(arc.end_heading.theta, 330)
def test_circle_color():
    p = Pen()
    p.move_to((0, 0))

    p.turn_to(0)
    p.fill_mode((1.0, 0.0, 0.0))
    p.circle(1)
    p.move_forward(2)
    p.fill_mode((0.0, 1.0, 0.0))
    p.circle(1)
    p.move_forward(2)
    p.fill_mode((0.0, 0.0, 1.0))
    p.circle(1)

    assert_equal(
        p.paper.svg_elements(0),
        [
            '<path d="M1,0 A 1,1 0 0 0 -1,0 A 1,1 0 0 0 1,0 z" fill="#ff0000" />',
            '<path d="M3,0 A 1,1 0 0 0 1,0 A 1,1 0 0 0 3,0 z" fill="#00ff00" />',
            '<path d="M5,0 A 1,1 0 0 0 3,0 A 1,1 0 0 0 5,0 z" fill="#0000ff" />',
        ]
    )
def test_circle_color():
    p = Pen()
    p.move_to((0, 0))

    p.turn_to(0)
    p.fill_mode((1.0, 0.0, 0.0))
    p.circle(1)
    p.move_forward(2)
    p.fill_mode((0.0, 1.0, 0.0))
    p.circle(1)
    p.move_forward(2)
    p.fill_mode((0.0, 0.0, 1.0))
    p.circle(1)

    assert_equal(
        p.paper.svg_elements(0),
        [
            '<path d="M1,0 A 1,1 0 0 0 -1,0 A 1,1 0 0 0 1,0 z" fill="#ff0000" />',
            '<path d="M3,0 A 1,1 0 0 0 1,0 A 1,1 0 0 0 3,0 z" fill="#00ff00" />',
            '<path d="M5,0 A 1,1 0 0 0 3,0 A 1,1 0 0 0 5,0 z" fill="#0000ff" />',
        ]
    )