David PHAM-VAN

Implement drawShape

@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 * Fix annotations 5 * Fix annotations
6 * Implement default fonts bounding box 6 * Implement default fonts bounding box
7 * Add Bézier Curve primitive 7 * Add Bézier Curve primitive
  8 +* Implement drawShape
8 9
9 # 1.0.8 10 # 1.0.8
10 * Fix monospace TTF font loading 11 * Fix monospace TTF font loading
@@ -206,26 +206,151 @@ class PdfGraphics { @@ -206,26 +206,151 @@ class PdfGraphics {
206 buf.putString("$x1 $y1 $x2 $y2 $x3 $y3 c\n"); 206 buf.putString("$x1 $y1 $x2 $y2 $x3 $y3 c\n");
207 } 207 }
208 208
209 - void drawShape(String d) {  
210 - var sb = StringBuffer();  
211 -  
212 - RegExp exp = RegExp(r"([MmZzLlHhVvCcSsQqTtAa])|(-[\.0-9]+)|([\.0-9]+)");  
213 - var matches = exp.allMatches(d);  
214 - var action; 209 + /// https://github.com/deeplook/svglib/blob/master/svglib/svglib.py#L911
  210 + void drawShape(String d, {stroke = true}) {
  211 + final sb = StringBuffer();
  212 + final exp = RegExp(r"([MmZzLlHhVvCcSsQqTtAaE])|(-[\.0-9]+)|([\.0-9]+)");
  213 + final matches = exp.allMatches(d + " E");
  214 + String action;
  215 + String lastAction;
  216 + List<double> points;
  217 + PdfPoint lastControl = PdfPoint(0.0, 0.0);
  218 + PdfPoint lastPoint = PdfPoint(0.0, 0.0);
215 for (var m in matches) { 219 for (var m in matches) {
216 var a = m.group(1); 220 var a = m.group(1);
217 var b = m.group(0); 221 var b = m.group(0);
218 - print("$a, $b");  
219 - if (a != null) {  
220 - if (action != null) {  
221 - sb.write("$action "); 222 +
  223 + if (a == null) {
  224 + points.add(double.parse(b));
  225 + continue;
  226 + }
  227 +
  228 + if (action != null) {
  229 + switch (action) {
  230 + case 'm': // moveto relative
  231 + lastPoint =
  232 + PdfPoint(lastPoint.x + points[0], lastPoint.y + points[1]);
  233 + sb.write("${lastPoint.x} ${lastPoint.y} m ");
  234 + break;
  235 + case 'M': // moveto absolute
  236 + lastPoint = PdfPoint(points[0], points[1]);
  237 + sb.write("${lastPoint.x} ${lastPoint.y} m ");
  238 + break;
  239 + case 'l': // lineto relative
  240 + lastPoint =
  241 + PdfPoint(lastPoint.x + points[0], lastPoint.y + points[1]);
  242 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  243 + break;
  244 + case 'L': // lineto absolute
  245 + lastPoint = PdfPoint(points[0], points[1]);
  246 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  247 + break;
  248 + case 'H': // horizontal line absolute
  249 + lastPoint = PdfPoint(points[0], lastPoint.y);
  250 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  251 + break;
  252 + case 'V': // vertical line absolute
  253 + lastPoint = PdfPoint(lastPoint.x, points[0]);
  254 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  255 + break;
  256 + case 'h': // horizontal line relative
  257 + lastPoint = PdfPoint(lastPoint.x + points[0], lastPoint.y);
  258 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  259 + break;
  260 + case 'v': // vertical line relative
  261 + lastPoint = PdfPoint(lastPoint.x, lastPoint.y + points[0]);
  262 + sb.write("${lastPoint.x} ${lastPoint.y} l ");
  263 + break;
  264 + case 'C': // cubic bezier, absolute
  265 + var len = 0;
  266 + while ((len + 1) * 6 <= points.length) {
  267 + sb.write(
  268 + points.sublist(len * 6, (len + 1) * 6).join(" ") + " c ");
  269 + len += 1;
  270 + }
  271 + lastPoint =
  272 + PdfPoint(points[points.length - 2], points[points.length - 1]);
  273 + lastControl =
  274 + PdfPoint(points[points.length - 4], points[points.length - 3]);
  275 + break;
  276 + case 'S': // smooth cubic bézier, absolute
  277 + while (points.length >= 4) {
  278 + PdfPoint c1;
  279 + if ('cCsS'.indexOf(lastAction) >= 0) {
  280 + c1 = PdfPoint(lastPoint.x + (lastPoint.x - lastControl.x),
  281 + lastPoint.y + (lastPoint.y - lastControl.y));
  282 + } else {
  283 + c1 = lastPoint;
  284 + }
  285 + lastControl = PdfPoint(points[0], points[1]);
  286 + lastPoint = PdfPoint(points[2], points[3]);
  287 + sb.write(
  288 + "${c1.x} ${c1.y} ${lastControl.x} ${lastControl.y} ${lastPoint.x} ${lastPoint.y} c ");
  289 + points = points.sublist(4);
  290 + lastAction = 'C';
  291 + }
  292 + break;
  293 + case 'c': // cubic bezier, relative
  294 + var len = 0;
  295 + while ((len + 1) * 6 <= points.length) {
  296 + points[len + 0] += lastPoint.x;
  297 + points[len + 1] += lastPoint.y;
  298 + points[len + 2] += lastPoint.x;
  299 + points[len + 3] += lastPoint.y;
  300 + points[len + 4] += lastPoint.x;
  301 + points[len + 5] += lastPoint.y;
  302 + sb.write(
  303 + points.sublist(len * 6, (len + 1) * 6).join(" ") + " c ");
  304 + len += 1;
  305 + }
  306 + lastPoint =
  307 + PdfPoint(points[points.length - 2], points[points.length - 1]);
  308 + lastControl =
  309 + PdfPoint(points[points.length - 4], points[points.length - 3]);
  310 + break;
  311 + case 's': // smooth cubic bézier, relative
  312 + while (points.length >= 4) {
  313 + PdfPoint c1;
  314 + if ('cCsS'.indexOf(lastAction) >= 0) {
  315 + c1 = PdfPoint(lastPoint.x + (lastPoint.x - lastControl.x),
  316 + lastPoint.y + (lastPoint.y - lastControl.y));
  317 + } else {
  318 + c1 = lastPoint;
  319 + }
  320 + lastControl =
  321 + PdfPoint(points[0] + lastPoint.x, points[1] + lastPoint.y);
  322 + lastPoint =
  323 + PdfPoint(points[2] + lastPoint.x, points[3] + lastPoint.y);
  324 + sb.write(
  325 + "${c1.x} ${c1.y} ${lastControl.x} ${lastControl.y} ${lastPoint.x} ${lastPoint.y} c ");
  326 + points = points.sublist(4);
  327 + lastAction = 'c';
  328 + }
  329 + break;
  330 + // case 'Q': // quadratic bezier, absolute
  331 + // break;
  332 + // case 'T': // quadratic bezier, absolute
  333 + // break;
  334 + // case 'q': // quadratic bezier, relative
  335 + // break;
  336 + // case 't': // quadratic bezier, relative
  337 + // break;
  338 + // case 'A': // elliptical arc, absolute
  339 + // break;
  340 + // case 'a': // elliptical arc, relative
  341 + // break;
  342 + case 'Z': // close path
  343 + case 'z': // close path
  344 + if (stroke) sb.write("s ");
  345 + break;
  346 + default:
  347 + print("Unknown path action: $action");
222 } 348 }
223 - action = a;  
224 - } else {  
225 - sb.write("$b ");  
226 } 349 }
  350 + lastAction = action;
  351 + action = a;
  352 + points = List<double>();
227 } 353 }
228 - print(sb);  
229 buf.putString(sb.toString()); 354 buf.putString(sb.toString());
230 } 355 }
231 356
@@ -20,12 +20,19 @@ void main() { @@ -20,12 +20,19 @@ void main() {
20 var page = PdfPage(pdf, pageFormat: const PdfPageFormat(500.0, 300.0)); 20 var page = PdfPage(pdf, pageFormat: const PdfPageFormat(500.0, 300.0));
21 21
22 var g = page.getGraphics(); 22 var g = page.getGraphics();
  23 +
23 g.saveContext(); 24 g.saveContext();
24 var tm = Matrix4.identity(); 25 var tm = Matrix4.identity();
25 - tm.translate(100.0, 700.0); 26 + tm.translate(50.0, 290.0);
  27 + tm.rotateZ(pi);
26 g.setTransform(tm); 28 g.setTransform(tm);
27 -// g.drawShape("M37 0H9C6.24 0 4 2.24 4 5v38c0 2.76 2.24 5 5 5h28c2.76 0 5-2.24 5-5V5c0-2.76-2.24-5-5-5zM23 46c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm15-8H8V6h30v32z"); 29 + g.setColor(PdfColor(0.0, 0.0, 0.0));
  30 + g.drawShape(
  31 + "M37 0H9C6.24 0 4 2.24 4 5v38c0 2.76 2.24 5 5 5h28c2.76 0 5-2.24 5-5V5c0-2.76-2.24-5-5-5zM23 46c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm15-8H8V6h30v32z",
  32 + stroke: false);
  33 + g.fillPath();
28 g.restoreContext(); 34 g.restoreContext();
  35 +
29 var font1 = g.defaultFont; 36 var font1 = g.defaultFont;
30 37
31 var font2 = PdfTtfFont( 38 var font2 = PdfTtfFont(