@@ -72,93 +72,22 @@ def buffer_info(self):
72
72
return (self .__data , self .__size )
73
73
74
74
75
- # Mapping from Matplotlib Path codes to cairo path codes.
76
- _MPL_TO_CAIRO_PATH_TYPE = np .zeros (80 , dtype = int ) # CLOSEPOLY = 79.
77
- _MPL_TO_CAIRO_PATH_TYPE [Path .MOVETO ] = cairo .PATH_MOVE_TO
78
- _MPL_TO_CAIRO_PATH_TYPE [Path .LINETO ] = cairo .PATH_LINE_TO
79
- _MPL_TO_CAIRO_PATH_TYPE [Path .CURVE4 ] = cairo .PATH_CURVE_TO
80
- _MPL_TO_CAIRO_PATH_TYPE [Path .CLOSEPOLY ] = cairo .PATH_CLOSE_PATH
81
- # Sizes in cairo_path_data_t of each cairo path element.
82
- _CAIRO_PATH_TYPE_SIZES = np .zeros (4 , dtype = int )
83
- _CAIRO_PATH_TYPE_SIZES [cairo .PATH_MOVE_TO ] = 2
84
- _CAIRO_PATH_TYPE_SIZES [cairo .PATH_LINE_TO ] = 2
85
- _CAIRO_PATH_TYPE_SIZES [cairo .PATH_CURVE_TO ] = 4
86
- _CAIRO_PATH_TYPE_SIZES [cairo .PATH_CLOSE_PATH ] = 1
87
-
88
-
89
- def _append_paths_slow (ctx , paths , transforms , clip = None ):
90
- for path , transform in zip (paths , transforms ):
91
- for points , code in path .iter_segments (
92
- transform , remove_nans = True , clip = clip ):
93
- if code == Path .MOVETO :
94
- ctx .move_to (* points )
95
- elif code == Path .CLOSEPOLY :
96
- ctx .close_path ()
97
- elif code == Path .LINETO :
98
- ctx .line_to (* points )
99
- elif code == Path .CURVE3 :
100
- cur = np .asarray (ctx .get_current_point ())
101
- a = points [:2 ]
102
- b = points [- 2 :]
103
- ctx .curve_to (* (cur / 3 + a * 2 / 3 ), * (a * 2 / 3 + b / 3 ), * b )
104
- elif code == Path .CURVE4 :
105
- ctx .curve_to (* points )
106
-
107
-
108
- def _append_paths_fast (ctx , paths , transforms , clip = None ):
109
- # We directly convert to the internal representation used by cairo, for
110
- # which ABI compatibility is guaranteed. The layout for each item is
111
- # --CODE(4)-- -LENGTH(4)- ---------PAD(8)---------
112
- # ----------X(8)---------- ----------Y(8)----------
113
- # with the size in bytes in parentheses, and (X, Y) repeated as many times
114
- # as there are points for the current code.
115
- ffi = cairo .ffi
116
-
117
- # Convert curves to segment, so that 1. we don't have to handle
118
- # variable-sized CURVE-n codes, and 2. we don't have to implement degree
119
- # elevation for quadratic Beziers.
120
- cleaneds = [path .cleaned (transform , remove_nans = True , clip = clip )
121
- for path , transform in zip (paths , transforms )]
122
- vertices = np .concatenate ([cleaned .vertices for cleaned in cleaneds ])
123
- codes = np .concatenate ([cleaned .codes for cleaned in cleaneds ])
124
-
125
- # Remove unused vertices and convert to cairo codes. Note that unlike
126
- # cairo_close_path, we do not explicitly insert an extraneous MOVE_TO after
127
- # CLOSE_PATH, so our resulting buffer may be smaller.
128
- vertices = vertices [(codes != Path .STOP ) & (codes != Path .CLOSEPOLY )]
129
- codes = codes [codes != Path .STOP ]
130
- codes = _MPL_TO_CAIRO_PATH_TYPE [codes ]
131
-
132
- # Where are the headers of each cairo portions?
133
- cairo_type_sizes = _CAIRO_PATH_TYPE_SIZES [codes ]
134
- cairo_type_positions = np .insert (np .cumsum (cairo_type_sizes ), 0 , 0 )
135
- cairo_num_data = cairo_type_positions [- 1 ]
136
- cairo_type_positions = cairo_type_positions [:- 1 ]
137
-
138
- # Fill the buffer.
139
- buf = np .empty (cairo_num_data * 16 , np .uint8 )
140
- as_int = np .frombuffer (buf .data , np .int32 )
141
- as_int [::4 ][cairo_type_positions ] = codes
142
- as_int [1 ::4 ][cairo_type_positions ] = cairo_type_sizes
143
- as_float = np .frombuffer (buf .data , np .float64 )
144
- mask = np .ones_like (as_float , bool )
145
- mask [::2 ][cairo_type_positions ] = mask [1 ::2 ][cairo_type_positions ] = False
146
- as_float [mask ] = vertices .ravel ()
147
-
148
- # Construct the cairo_path_t, and pass it to the context.
149
- ptr = ffi .new ("cairo_path_t *" )
150
- ptr .status = cairo .STATUS_SUCCESS
151
- ptr .data = ffi .cast ("cairo_path_data_t *" , ffi .from_buffer (buf ))
152
- ptr .num_data = cairo_num_data
153
- cairo .cairo .cairo_append_path (ctx ._pointer , ptr )
154
-
155
-
156
- _append_paths = (_append_paths_fast if cairo .__name__ == "cairocffi"
157
- else _append_paths_slow )
158
-
159
-
160
75
def _append_path (ctx , path , transform , clip = None ):
161
- return _append_paths (ctx , [path ], [transform ], clip )
76
+ for points , code in path .iter_segments (
77
+ transform , remove_nans = True , clip = clip ):
78
+ if code == Path .MOVETO :
79
+ ctx .move_to (* points )
80
+ elif code == Path .CLOSEPOLY :
81
+ ctx .close_path ()
82
+ elif code == Path .LINETO :
83
+ ctx .line_to (* points )
84
+ elif code == Path .CURVE3 :
85
+ cur = np .asarray (ctx .get_current_point ())
86
+ a = points [:2 ]
87
+ b = points [- 2 :]
88
+ ctx .curve_to (* (cur / 3 + a * 2 / 3 ), * (a * 2 / 3 + b / 3 ), * b )
89
+ elif code == Path .CURVE4 :
90
+ ctx .curve_to (* points )
162
91
163
92
164
93
class RendererCairo (RendererBase ):
0 commit comments