@@ -363,6 +363,18 @@ public static function provideBasicPathConversionScenarios(): iterable
363363 '5.333333 11.333333 6.666667 11.333333 8.000000 10.000000 c ' ,
364364 ],
365365 ];
366+
367+ yield 'multiple line commands keep progress strictly increasing ' => [
368+ 'pathData ' => 'M 0 0 L 10 10 L 5 5 ' ,
369+ 'minX ' => 0.0 ,
370+ 'maxY ' => 10.0 ,
371+ 'source ' => '/tmp/progress.svg ' ,
372+ 'expectedSnippets ' => [
373+ '0.000000 10.000000 m ' ,
374+ '10.000000 0.000000 l ' ,
375+ '5.000000 5.000000 l ' ,
376+ ],
377+ ];
366378 }
367379
368380 /**
@@ -409,6 +421,18 @@ public static function provideTransformAndCoordinateConversionScenarios(): itera
409421 ],
410422 ];
411423
424+ yield 'minx offset for cubic command ' => [
425+ 'pathData ' => 'M 2 0 C 4 2 6 2 8 0 ' ,
426+ 'minX ' => 2.0 ,
427+ 'maxY ' => 10.0 ,
428+ 'transformMatrix ' => [1.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 ],
429+ 'source ' => '/tmp/minx-cubic.svg (via transform) ' ,
430+ 'expectedSnippets ' => [
431+ '0.000000 10.000000 m ' ,
432+ '2.000000 8.000000 4.000000 8.000000 6.000000 10.000000 c ' ,
433+ ],
434+ ];
435+
412436 yield 'minx offset for arc commands ' => [
413437 'pathData ' => 'M 0 10 A 6 4 0 0 1 12 10 ' ,
414438 'minX ' => 5.0 ,
@@ -717,60 +741,4 @@ public static function provideRelativeAfterClosePathScenarios(): iterable
717741 'description ' => 'S after Z should treat previous curve as non-existent ' ,
718742 ];
719743 }
720-
721- public function testConvertPathDataEnforcesIndexProgressionStrictly (): void
722- {
723- $ parser = new SvgPathCommandParser ();
724-
725- // Index must increase (strict > not <=); valid path must complete without error
726- $ result = $ parser ->convertPathData ('M 0 0 L 10 10 L 5 5 ' , 0.0 , 10.0 , 'test.svg ' , [1 , 0 , 0 , 1 , 0 , 0 ]);
727- self ::assertNotEmpty ($ result );
728- }
729-
730- public function testConvertPathDataDetectsZeroProgressNotEqualProgress (): void
731- {
732- $ parser = new SvgPathCommandParser ();
733-
734- // Boundary: <= versus < check is crucial for progress detection
735- // Valid paths with standard commands must succeed
736-
737- try {
738- // Valid path should not throw
739- $ result = $ parser ->convertPathData ('M 0 0 L 10 10 L 5 5 ' , 0.0 , 10.0 , 'test.svg ' , [1 , 0 , 0 , 1 , 0 , 0 ]);
740- self ::assertNotEmpty ($ result );
741- } catch (InvalidArgumentException $ e ) {
742- self ::fail ('Valid path should not throw: ' . $ e ->getMessage ());
743- }
744- }
745-
746- public function testCoordinateTransformSubtractsMinXNotAdds (): void
747- {
748- $ parser = new SvgPathCommandParser ();
749-
750- // Transform must subtract minX from x-coordinates
751- $ result = $ parser ->convertPathData ('M 0 0 L 10 10 ' , 5.0 , 10.0 , 'test.svg ' , [1 , 0 , 0 , 1 , 0 , 0 ]);
752-
753- // With minX=5, starting x=0 should become x=0-5=-5, NOT x=0+5=5
754- self ::assertStringContainsString ('-5.000000 10.000000 m ' , $ result );
755- self ::assertStringContainsString ('5.000000 0.000000 l ' , $ result );
756- }
757-
758- public function testCoordinateTransformMinusOperator (): void
759- {
760- $ parser = new SvgPathCommandParser ();
761-
762- // Verify the cubic bezier transform subtracts minX correctly
763- $ result = $ parser ->convertPathData (
764- 'M 2 0 C 4 2 6 2 8 0 ' ,
765- 2.0 ,
766- 10.0 ,
767- 'test.svg ' ,
768- [1 , 0 , 0 , 1 , 0 , 0 ],
769- );
770-
771- // Expected: (2-2) (10-0) = 0 10, then cubic
772- self ::assertStringContainsString ('0.000000 10.000000 m ' , $ result );
773- // Cubic control points: (4-2, 10-2) (6-2, 10-2) (8-2, 10-0)
774- self ::assertStringContainsString ('2.000000 8.000000 4.000000 8.000000 6.000000 10.000000 c ' , $ result );
775- }
776744}
0 commit comments