import math import os import pytest import numpy as np import naramotion from naramotion import ( Image, Context, Format, Path, Font, Rect, Box, Point, Matrix2D, StrokeCap, StrokeJoin, StrokeTransformOrder, FlattenMode, RenderingQuality, GradientQuality, PatternQuality, LinearGradient, RadialGradient, SvgContext, export_svg ) from tests.test_font import get_system_font_path def test_context_threading(): img = Image(800, 600, Format.PRGB32) with Context(img, thread_count=4) as ctx: assert ctx.thread_count == 4 ctx.fill_all("black") for i in range(100): ctx.fill_circle(i * 8, 300, 20, "cyan") assert img.width == 800 def test_state_cookie_save_restore(): img = Image(400, 400, Format.PRGB32) with Context(img) as ctx: ctx.translate(100, 100) cookie = ctx.save_with_cookie() ctx.scale(2.0, 2.0) ctx.restore(cookie) def test_asymmetric_stroke_caps(): img = Image(300, 300, Format.PRGB32) with Context(img) as ctx: ctx.stroke_width = 10.0 ctx.set_stroke_start_cap(StrokeCap.BUTT) ctx.set_stroke_end_cap(StrokeCap.ROUND) ctx.stroke_line(50, 150, 250, 150, "white") def test_stroke_transform_order(): img = Image(300, 300, Format.PRGB32) with Context(img) as ctx: ctx.stroke_transform_order = StrokeTransformOrder.BEFORE ctx.stroke_transform_order = StrokeTransformOrder.AFTER def test_flatten_and_quality_hints(): img = Image(300, 300, Format.PRGB32) with Context(img) as ctx: ctx.rendering_quality = RenderingQuality.ANTIALIAS ctx.gradient_quality = GradientQuality.DITHER ctx.pattern_quality = PatternQuality.BILINEAR ctx.set_flatten_tolerance(0.25) assert ctx.flatten_tolerance == 0.5 or ctx.flatten_tolerance > 0 def test_chord_and_pie_primitives(): img = Image(500, 500, Format.PRGB32) with Context(img) as ctx: ctx.fill_all("#090D16") # 1. Pie slice (5 args: cx, cy, r, start, sweep) ctx.fill_pie(150, 150, 100, 0.0, math.pi * 0.75, style="#38BDF8") ctx.stroke_pie(150, 150, 100, 0.0, math.pi * 0.75, style="white") # 2. Chord segment (6 args: cx, cy, rx, ry, start, sweep) ctx.fill_chord(350, 150, 100, 80, 0.0, math.pi, style="#EC4899") ctx.stroke_chord(350, 150, 100, 80, 0.0, math.pi, style="yellow") def test_path_length_vertices_and_svg_d(): p = Path() p.move_to(0, 0) p.line_to(100, 0) p.line_to(100, 100) p.close() assert p.get_vertex_count() == 4 cmd, x, y = p.get_vertex(1) assert (x, y) == (100.0, 0.0) vertices = p.get_vertices() assert len(vertices) == 4 # Triangle perimeter = 100 + 100 + sqrt(100^2 + 100^2) ≈ 341.42 length = p.get_length() assert 340.0 <= length <= 343.0 d_str = p.to_svg_d() assert "M 0.000 0.000" in d_str assert "L 100.000 0.000" in d_str assert "Z" in d_str def test_svg_exporter_module(): svg_ctx = SvgContext(width=800, height=600, title="NaraMotion Test SVG") svg_ctx.fill_all("#0F172A") svg_ctx.fill_circle(400, 300, 150, style="#38BDF8") svg_ctx.stroke_round_rect(100, 100, 200, 120, rx=20, ry=20, style="white") p = Path() p.move_to(50, 50).line_to(200, 50).quad_to(300, 100, 200, 200).close() svg_ctx.fill_path(p, style="#EC4899") svg_str = svg_ctx.to_svg() assert "