@@ -939,79 +939,151 @@ void cleanup_path(PathIterator &path,
939
939
}
940
940
}
941
941
942
+ void quad2cubic (double x0, double y0,
943
+ double x1, double y1,
944
+ double x2, double y2,
945
+ double *outx, double *outy)
946
+ {
947
+
948
+ outx[0 ] = x0 + 2 ./3 . * (x1 - x0);
949
+ outy[0 ] = y0 + 2 ./3 . * (y1 - y0);
950
+ outx[1 ] = outx[0 ] + 1 ./3 . * (x2 - x0);
951
+ outy[1 ] = outy[0 ] + 1 ./3 . * (y2 - y0);
952
+ outx[2 ] = x2;
953
+ outy[2 ] = y2;
954
+ }
955
+
956
+ char *__append_to_string (char *p, char *buffer, size_t buffersize,
957
+ const char *content)
958
+ {
959
+ for (const char *i = content; *i; ++i) {
960
+ if (p < buffer || p - buffer >= (int )buffersize) {
961
+ return p;
962
+ }
963
+
964
+ *p++ = *i;
965
+ }
966
+
967
+ return p;
968
+ }
969
+
942
970
template <class PathIterator >
943
- void convert_to_svg (PathIterator &path,
944
- agg::trans_affine &trans,
945
- agg::rect_d &clip_rect,
946
- bool simplify,
947
- int precision,
948
- char *buffer,
949
- size_t *buffersize)
971
+ void __convert_to_string (PathIterator &path,
972
+ int precision,
973
+ char **codes,
974
+ bool postfix,
975
+ char *buffer,
976
+ size_t *buffersize)
950
977
{
951
978
#if PY_VERSION_HEX < 0x02070000
952
979
char format[64 ];
953
980
snprintf (format, 64 , " %s.%dg" , " %" , precision);
954
981
#endif
955
982
956
- typedef agg::conv_transform<py::PathIterator> transformed_path_t ;
957
- typedef PathNanRemover<transformed_path_t > nan_removal_t ;
958
- typedef PathClipper<nan_removal_t > clipped_t ;
959
- typedef PathSimplifier<clipped_t > simplify_t ;
960
-
961
- bool do_clip = (clip_rect.x1 < clip_rect.x2 && clip_rect.y1 < clip_rect.y2 );
962
-
963
- transformed_path_t tpath (path, trans);
964
- nan_removal_t nan_removed (tpath, true , path.has_curves ());
965
- clipped_t clipped (nan_removed, do_clip, clip_rect);
966
- simplify_t simplified (clipped, simplify, path.simplify_threshold ());
967
-
968
983
char *p = buffer;
984
+ double x[3 ];
985
+ double y[3 ];
986
+ double last_x = 0.0 ;
987
+ double last_y = 0.0 ;
969
988
970
- const char codes[] = { ' M' , ' L' , ' Q' , ' C' };
971
- const int waits[] = { 1 , 1 , 2 , 3 };
972
-
973
- int wait = 0 ;
989
+ const int sizes[] = { 1 , 1 , 2 , 3 };
990
+ int size = 0 ;
974
991
unsigned code;
975
- double x = 0 , y = 0 ;
976
- while ((code = simplified.vertex (&x, &y)) != agg::path_cmd_stop) {
977
- if (wait == 0 ) {
978
- *p++ = ' \n ' ;
979
992
980
- if (code == 0x4f ) {
981
- *p++ = ' z' ;
982
- *p++ = ' \n ' ;
983
- continue ;
993
+ while ((code = path.vertex (&x[0 ], &y[0 ])) != agg::path_cmd_stop) {
994
+ if (code == 0x4f ) {
995
+ p = __append_to_string (p, buffer, *buffersize, codes[4 ]);
996
+ } else {
997
+ size = sizes[code - 1 ];
998
+
999
+ for (int i = 1 ; i < size; ++i) {
1000
+ path.vertex (&x[i], &y[i]);
984
1001
}
985
1002
986
- *p++ = codes[code - 1 ];
987
- wait = waits[code - 1 ];
988
- } else {
989
- *p++ = ' ' ;
990
- }
1003
+ /* For formats that don't support quad curves, convert to
1004
+ cubic curves */
1005
+ if (codes[code - 1 ][0 ] == ' \0 ' ) {
1006
+ quad2cubic (last_x, last_y, x[0 ], y[0 ], x[1 ], y[1 ], x, y);
1007
+ code++;
1008
+ size = 3 ;
1009
+ }
1010
+
1011
+ if (!postfix) {
1012
+ p = __append_to_string (p, buffer, *buffersize, codes[code - 1 ]);
1013
+ p = __append_to_string (p, buffer, *buffersize, " " );
1014
+ }
991
1015
1016
+ for (int i = 0 ; i < size; ++i) {
992
1017
#if PY_VERSION_HEX >= 0x02070000
993
- char *str;
994
- str = PyOS_double_to_string (x, ' g' , precision, 0 , NULL );
995
- p += snprintf (p, *buffersize - (p - buffer), " %s" , str);
996
- PyMem_Free (str);
997
- *p++ = ' ' ;
998
- str = PyOS_double_to_string (y, ' g' , precision, 0 , NULL );
999
- p += snprintf (p, *buffersize - (p - buffer), " %s" , str);
1000
- PyMem_Free (str);
1018
+ char *str;
1019
+ str = PyOS_double_to_string (x[i], ' g' , precision, 0 , NULL );
1020
+ p = __append_to_string (p, buffer, *buffersize, str);
1021
+ PyMem_Free (str);
1022
+ p = __append_to_string (p, buffer, *buffersize, " " );
1023
+ str = PyOS_double_to_string (y[i], ' g' , precision, 0 , NULL );
1024
+ p = __append_to_string (p, buffer, *buffersize, str);
1025
+ PyMem_Free (str);
1026
+ p = __append_to_string (p, buffer, *buffersize, " " );
1001
1027
#else
1002
- char str[64 ];
1003
- PyOS_ascii_formatd (str, 64 , format, x);
1004
- p += snprintf (p, *buffersize - (p - buffer), " %s" , str);
1005
- *p++ = ' ' ;
1006
- PyOS_ascii_formatd (str, 64 , format, y);
1007
- p += snprintf (p, *buffersize - (p - buffer), " %s" , str);
1028
+ char str[64 ];
1029
+ PyOS_ascii_formatd (str, 64 , format, x[i]);
1030
+ p = __append_to_string (p, buffer, *buffersize, str);
1031
+ p = __append_to_string (p, buffer, *buffersize, " " );
1032
+ PyOS_ascii_formatd (str, 64 , format, y[i]);
1033
+ p = __append_to_string (p, buffer, *buffersize, str);
1034
+ p = __append_to_string (p, buffer, *buffersize, " " );
1008
1035
#endif
1036
+ }
1037
+
1038
+ if (postfix) {
1039
+ p = __append_to_string (p, buffer, *buffersize, codes[code - 1 ]);
1040
+ }
1041
+
1042
+ last_x = x[size - 1 ];
1043
+ last_y = y[size - 1 ];
1044
+ }
1009
1045
1010
- --wait ;
1046
+ p = __append_to_string (p, buffer, *buffersize, " \n " ) ;
1011
1047
}
1012
1048
1013
1049
*p = ' \0 ' ;
1014
1050
*buffersize = p - buffer;
1015
1051
}
1016
1052
1053
+ template <class PathIterator >
1054
+ void convert_to_string (PathIterator &path,
1055
+ agg::trans_affine &trans,
1056
+ agg::rect_d &clip_rect,
1057
+ bool simplify,
1058
+ SketchParams sketch_params,
1059
+ int precision,
1060
+ char **codes,
1061
+ bool postfix,
1062
+ char *buffer,
1063
+ size_t *buffersize)
1064
+ {
1065
+ typedef agg::conv_transform<py::PathIterator> transformed_path_t ;
1066
+ typedef PathNanRemover<transformed_path_t > nan_removal_t ;
1067
+ typedef PathClipper<nan_removal_t > clipped_t ;
1068
+ typedef PathSimplifier<clipped_t > simplify_t ;
1069
+ typedef agg::conv_curve<simplify_t > curve_t ;
1070
+ typedef Sketch<curve_t > sketch_t ;
1071
+
1072
+ bool do_clip = (clip_rect.x1 < clip_rect.x2 && clip_rect.y1 < clip_rect.y2 );
1073
+
1074
+ transformed_path_t tpath (path, trans);
1075
+ nan_removal_t nan_removed (tpath, true , path.has_curves ());
1076
+ clipped_t clipped (nan_removed, do_clip, clip_rect);
1077
+ simplify_t simplified (clipped, simplify, path.simplify_threshold ());
1078
+
1079
+ if (sketch_params.scale == 0.0 ) {
1080
+ __convert_to_string (simplified, precision, codes, postfix, buffer, buffersize);
1081
+ } else {
1082
+ curve_t curve (simplified);
1083
+ sketch_t sketch (curve, sketch_params.scale , sketch_params.length , sketch_params.randomness );
1084
+ __convert_to_string (sketch, precision, codes, postfix, buffer, buffersize);
1085
+ }
1086
+
1087
+ }
1088
+
1017
1089
#endif
0 commit comments