Showing
4 changed files
with
35 additions
and
166 deletions
| @@ -24,6 +24,7 @@ import 'dart:typed_data'; | @@ -24,6 +24,7 @@ import 'dart:typed_data'; | ||
| 24 | import 'package:crypto/crypto.dart'; | 24 | import 'package:crypto/crypto.dart'; |
| 25 | import 'package:image/image.dart' as im; | 25 | import 'package:image/image.dart' as im; |
| 26 | import 'package:meta/meta.dart'; | 26 | import 'package:meta/meta.dart'; |
| 27 | +import 'package:path_parsing/path_parsing.dart'; | ||
| 27 | import 'package:utf/utf.dart'; | 28 | import 'package:utf/utf.dart'; |
| 28 | import 'package:vector_math/vector_math_64.dart'; | 29 | import 'package:vector_math/vector_math_64.dart'; |
| 29 | 30 |
| @@ -514,173 +514,9 @@ class PdfGraphics { | @@ -514,173 +514,9 @@ class PdfGraphics { | ||
| 514 | } | 514 | } |
| 515 | } | 515 | } |
| 516 | 516 | ||
| 517 | - /// https://github.com/deeplook/svglib/blob/master/svglib/svglib.py#L911 | ||
| 518 | void drawShape(String d, {bool stroke = true}) { | 517 | void drawShape(String d, {bool stroke = true}) { |
| 519 | - final RegExp exp = | ||
| 520 | - RegExp(r'([MmZzLlHhVvCcSsQqTtAaE])|(-[\.0-9]+)|([\.0-9]+)'); | ||
| 521 | - final Iterable<Match> matches = exp.allMatches(d + ' E'); | ||
| 522 | - String action; | ||
| 523 | - String lastAction; | ||
| 524 | - List<double> points; | ||
| 525 | - PdfPoint lastControl = const PdfPoint(0, 0); | ||
| 526 | - PdfPoint lastPoint = const PdfPoint(0, 0); | ||
| 527 | - for (Match m in matches) { | ||
| 528 | - final String a = m.group(1); | ||
| 529 | - final String b = m.group(0); | ||
| 530 | - | ||
| 531 | - if (a == null) { | ||
| 532 | - points.add(double.parse(b)); | ||
| 533 | - continue; | ||
| 534 | - } | ||
| 535 | - | ||
| 536 | - if (action != null) { | ||
| 537 | - switch (action) { | ||
| 538 | - case 'm': // moveto relative | ||
| 539 | - lastPoint = | ||
| 540 | - PdfPoint(lastPoint.x + points[0], lastPoint.y + points[1]); | ||
| 541 | - moveTo(lastPoint.x, lastPoint.y); | ||
| 542 | - break; | ||
| 543 | - case 'M': // moveto absolute | ||
| 544 | - lastPoint = PdfPoint(points[0], points[1]); | ||
| 545 | - moveTo(lastPoint.x, lastPoint.y); | ||
| 546 | - break; | ||
| 547 | - case 'l': // lineto relative | ||
| 548 | - lastPoint = | ||
| 549 | - PdfPoint(lastPoint.x + points[0], lastPoint.y + points[1]); | ||
| 550 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 551 | - break; | ||
| 552 | - case 'L': // lineto absolute | ||
| 553 | - lastPoint = PdfPoint(points[0], points[1]); | ||
| 554 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 555 | - break; | ||
| 556 | - case 'H': // horizontal line absolute | ||
| 557 | - lastPoint = PdfPoint(points[0], lastPoint.y); | ||
| 558 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 559 | - break; | ||
| 560 | - case 'V': // vertical line absolute | ||
| 561 | - lastPoint = PdfPoint(lastPoint.x, points[0]); | ||
| 562 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 563 | - break; | ||
| 564 | - case 'h': // horizontal line relative | ||
| 565 | - lastPoint = PdfPoint(lastPoint.x + points[0], lastPoint.y); | ||
| 566 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 567 | - break; | ||
| 568 | - case 'v': // vertical line relative | ||
| 569 | - lastPoint = PdfPoint(lastPoint.x, lastPoint.y + points[0]); | ||
| 570 | - lineTo(lastPoint.x, lastPoint.y); | ||
| 571 | - break; | ||
| 572 | - case 'C': // cubic bezier, absolute | ||
| 573 | - int len = 0; | ||
| 574 | - while (len < points.length) { | ||
| 575 | - curveTo(points[len + 0], points[len + 1], points[len + 2], | ||
| 576 | - points[len + 3], points[len + 4], points[len + 5]); | ||
| 577 | - len += 6; | ||
| 578 | - } | ||
| 579 | - lastPoint = | ||
| 580 | - PdfPoint(points[points.length - 2], points[points.length - 1]); | ||
| 581 | - lastControl = | ||
| 582 | - PdfPoint(points[points.length - 4], points[points.length - 3]); | ||
| 583 | - break; | ||
| 584 | - case 'S': // smooth cubic bézier, absolute | ||
| 585 | - while (points.length >= 4) { | ||
| 586 | - PdfPoint c1; | ||
| 587 | - if ('cCsS'.contains(lastAction)) { | ||
| 588 | - c1 = PdfPoint(lastPoint.x + (lastPoint.x - lastControl.x), | ||
| 589 | - lastPoint.y + (lastPoint.y - lastControl.y)); | ||
| 590 | - } else { | ||
| 591 | - c1 = lastPoint; | ||
| 592 | - } | ||
| 593 | - lastControl = PdfPoint(points[0], points[1]); | ||
| 594 | - lastPoint = PdfPoint(points[2], points[3]); | ||
| 595 | - curveTo(c1.x, c1.y, lastControl.x, lastControl.y, lastPoint.x, | ||
| 596 | - lastPoint.y); | ||
| 597 | - points = points.sublist(4); | ||
| 598 | - lastAction = 'C'; | ||
| 599 | - } | ||
| 600 | - break; | ||
| 601 | - case 'c': // cubic bezier, relative | ||
| 602 | - int len = 0; | ||
| 603 | - while (len < points.length) { | ||
| 604 | - points[len + 0] += lastPoint.x; | ||
| 605 | - points[len + 1] += lastPoint.y; | ||
| 606 | - points[len + 2] += lastPoint.x; | ||
| 607 | - points[len + 3] += lastPoint.y; | ||
| 608 | - points[len + 4] += lastPoint.x; | ||
| 609 | - points[len + 5] += lastPoint.y; | ||
| 610 | - curveTo(points[len + 0], points[len + 1], points[len + 2], | ||
| 611 | - points[len + 3], points[len + 4], points[len + 5]); | ||
| 612 | - lastPoint = PdfPoint(points[len + 4], points[len + 5]); | ||
| 613 | - lastControl = PdfPoint(points[len + 2], points[len + 3]); | ||
| 614 | - len += 6; | ||
| 615 | - } | ||
| 616 | - break; | ||
| 617 | - case 's': // smooth cubic bézier, relative | ||
| 618 | - while (points.length >= 4) { | ||
| 619 | - PdfPoint c1; | ||
| 620 | - if ('cCsS'.contains(lastAction)) { | ||
| 621 | - c1 = PdfPoint(lastPoint.x + (lastPoint.x - lastControl.x), | ||
| 622 | - lastPoint.y + (lastPoint.y - lastControl.y)); | ||
| 623 | - } else { | ||
| 624 | - c1 = lastPoint; | ||
| 625 | - } | ||
| 626 | - lastControl = | ||
| 627 | - PdfPoint(points[0] + lastPoint.x, points[1] + lastPoint.y); | ||
| 628 | - lastPoint = | ||
| 629 | - PdfPoint(points[2] + lastPoint.x, points[3] + lastPoint.y); | ||
| 630 | - curveTo(c1.x, c1.y, lastControl.x, lastControl.y, lastPoint.x, | ||
| 631 | - lastPoint.y); | ||
| 632 | - points = points.sublist(4); | ||
| 633 | - lastAction = 'c'; | ||
| 634 | - } | ||
| 635 | - break; | ||
| 636 | - // case 'Q': // quadratic bezier, absolute | ||
| 637 | - // break; | ||
| 638 | - // case 'T': // quadratic bezier, absolute | ||
| 639 | - // break; | ||
| 640 | - // case 'q': // quadratic bezier, relative | ||
| 641 | - // break; | ||
| 642 | - // case 't': // quadratic bezier, relative | ||
| 643 | - // break; | ||
| 644 | - case 'A': // elliptical arc, absolute | ||
| 645 | - int len = 0; | ||
| 646 | - while (len < points.length) { | ||
| 647 | - bezierArc(lastPoint.x, lastPoint.y, points[len + 0], | ||
| 648 | - points[len + 1], points[len + 5], points[len + 6], | ||
| 649 | - phi: points[len + 2] * math.pi / 180.0, | ||
| 650 | - large: points[len + 3] != 0.0, | ||
| 651 | - sweep: points[len + 4] != 0.0); | ||
| 652 | - lastPoint = PdfPoint(points[len + 5], points[len + 6]); | ||
| 653 | - len += 7; | ||
| 654 | - } | ||
| 655 | - break; | ||
| 656 | - case 'a': // elliptical arc, relative | ||
| 657 | - int len = 0; | ||
| 658 | - while (len < points.length) { | ||
| 659 | - points[len + 5] += lastPoint.x; | ||
| 660 | - points[len + 6] += lastPoint.y; | ||
| 661 | - bezierArc(lastPoint.x, lastPoint.y, points[len + 0], | ||
| 662 | - points[len + 1], points[len + 5], points[len + 6], | ||
| 663 | - phi: points[len + 2] * math.pi / 180.0, | ||
| 664 | - large: points[len + 3] != 0.0, | ||
| 665 | - sweep: points[len + 4] != 0.0); | ||
| 666 | - lastPoint = PdfPoint(points[len + 5], points[len + 6]); | ||
| 667 | - len += 7; | ||
| 668 | - } | ||
| 669 | - break; | ||
| 670 | - case 'Z': // close path | ||
| 671 | - case 'z': // close path | ||
| 672 | - if (stroke) { | ||
| 673 | - closePath(); | ||
| 674 | - } | ||
| 675 | - break; | ||
| 676 | - default: | ||
| 677 | - print('Unknown path action: $action'); | ||
| 678 | - } | ||
| 679 | - } | ||
| 680 | - lastAction = action; | ||
| 681 | - action = a; | ||
| 682 | - points = <double>[]; | ||
| 683 | - } | 518 | + final proxy = _PathProxy(this, stroke); |
| 519 | + writeSvgPathDataToPath(d, proxy); | ||
| 684 | } | 520 | } |
| 685 | 521 | ||
| 686 | void setLineCap(PdfLineCap cap) { | 522 | void setLineCap(PdfLineCap cap) { |
| @@ -706,3 +542,33 @@ class PdfGraphics { | @@ -706,3 +542,33 @@ class PdfGraphics { | ||
| 706 | buf.putString(' $phase d\n'); | 542 | buf.putString(' $phase d\n'); |
| 707 | } | 543 | } |
| 708 | } | 544 | } |
| 545 | + | ||
| 546 | +class _PathProxy extends PathProxy { | ||
| 547 | + _PathProxy(this.canvas, this.stroke); | ||
| 548 | + | ||
| 549 | + final PdfGraphics canvas; | ||
| 550 | + final bool stroke; | ||
| 551 | + | ||
| 552 | + @override | ||
| 553 | + void close() { | ||
| 554 | + if (stroke) { | ||
| 555 | + canvas.closePath(); | ||
| 556 | + } | ||
| 557 | + } | ||
| 558 | + | ||
| 559 | + @override | ||
| 560 | + void cubicTo( | ||
| 561 | + double x1, double y1, double x2, double y2, double x3, double y3) { | ||
| 562 | + canvas.curveTo(x1, y1, x2, y2, x3, y3); | ||
| 563 | + } | ||
| 564 | + | ||
| 565 | + @override | ||
| 566 | + void lineTo(double x, double y) { | ||
| 567 | + canvas.lineTo(x, y); | ||
| 568 | + } | ||
| 569 | + | ||
| 570 | + @override | ||
| 571 | + void moveTo(double x, double y) { | ||
| 572 | + canvas.moveTo(x, y); | ||
| 573 | + } | ||
| 574 | +} |
-
Please register or login to post a comment