@@ -278,33 +278,25 @@ class PathNanRemover : protected EmbeddedQueue<4>
278278 clipped, but are always included in their entirety.
279279 */
280280template <class VertexSource >
281- class PathClipper
281+ class PathClipper : public EmbeddedQueue < 3 >
282282{
283283 VertexSource *m_source;
284284 bool m_do_clipping;
285285 agg::rect_base<double > m_cliprect;
286286 double m_lastX;
287287 double m_lastY;
288288 bool m_moveto;
289- double m_nextX;
290- double m_nextY;
291- bool m_has_next;
292- bool m_end_poly;
293289 double m_initX;
294290 double m_initY;
295291 bool m_has_init;
296- bool m_broke_path;
297292
298293 public:
299294 PathClipper (VertexSource &source, bool do_clipping, double width, double height)
300295 : m_source(&source),
301296 m_do_clipping (do_clipping),
302297 m_cliprect(-1.0 , -1.0 , width + 1.0 , height + 1.0 ),
303298 m_moveto(true ),
304- m_has_next(false ),
305- m_end_poly(false ),
306- m_has_init(false ),
307- m_broke_path(false )
299+ m_has_init(false )
308300 {
309301 // empty
310302 }
@@ -314,10 +306,7 @@ class PathClipper
314306 m_do_clipping(do_clipping),
315307 m_cliprect(rect),
316308 m_moveto(true ),
317- m_has_next(false ),
318- m_end_poly(false ),
319- m_has_init(false ),
320- m_broke_path(false )
309+ m_has_init(false )
321310 {
322311 m_cliprect.x1 -= 1.0 ;
323312 m_cliprect.y1 -= 1.0 ;
@@ -327,86 +316,100 @@ class PathClipper
327316
328317 inline void rewind (unsigned path_id)
329318 {
330- m_has_next = false ;
319+ m_has_init = false ;
331320 m_moveto = true ;
332321 m_source->rewind (path_id);
333322 }
334323
324+ int draw_clipped_line (double x0, double y0, double x1, double y1)
325+ {
326+ unsigned moved = agg::clip_line_segment (&x0, &y0, &x1, &y1, m_cliprect);
327+ // moved >= 4 - Fully clipped
328+ // moved & 1 != 0 - First point has been moved
329+ // moved & 2 != 0 - Second point has been moved
330+ if (moved < 4 ) {
331+ if (moved & 1 || m_moveto) {
332+ queue_push (agg::path_cmd_move_to, x0, y0);
333+ }
334+ queue_push (agg::path_cmd_line_to, x1, y1);
335+
336+ m_moveto = false ;
337+ return 1 ;
338+ }
339+
340+ return 0 ;
341+ }
342+
335343 unsigned vertex (double *x, double *y)
336344 {
337345 unsigned code;
338346
339347 if (m_do_clipping) {
340348 /* This is the slow path where we actually do clipping */
341349
342- if (m_end_poly) {
343- m_end_poly = false ;
344- return (agg::path_cmd_end_poly | agg::path_flags_close);
345- }
346-
347- if (m_has_next) {
348- m_has_next = false ;
349- *x = m_nextX;
350- *y = m_nextY;
351- return agg::path_cmd_line_to;
350+ if (queue_pop (&code, x, y)) {
351+ return code;
352352 }
353353
354354 while ((code = m_source->vertex (x, y)) != agg::path_cmd_stop) {
355- if (code == (agg::path_cmd_end_poly | agg::path_flags_close)) {
355+ switch (code) {
356+ case (agg::path_cmd_end_poly | agg::path_flags_close):
356357 if (m_has_init) {
357- *x = m_initX;
358- *y = m_initY;
359- code = agg::path_cmd_line_to;
360- m_end_poly = true ;
361- } else {
362- continue ;
358+ draw_clipped_line (m_lastX, m_lastY, m_initX, m_initY);
363359 }
364- }
365-
366- if (code == agg::path_cmd_move_to) {
367- m_initX = *x;
368- m_initY = *y;
360+ queue_push (
361+ agg::path_cmd_end_poly | agg::path_flags_close,
362+ m_lastX, m_lastY);
363+ goto exit_loop;
364+
365+ case agg::path_cmd_move_to:
366+ m_initX = m_lastX = *x;
367+ m_initY = m_lastY = *y;
369368 m_has_init = true ;
370369 m_moveto = true ;
371- }
372- if (m_moveto) {
373- m_moveto = false ;
374- code = agg::path_cmd_move_to;
375370 break ;
376- } else if (code == agg::path_cmd_line_to) {
377- double x0, y0, x1, y1;
378- x0 = m_lastX;
379- y0 = m_lastY;
380- x1 = *x;
381- y1 = *y;
371+
372+ case agg::path_cmd_line_to:
373+ if (draw_clipped_line (m_lastX, m_lastY, *x, *y)) {
374+ m_lastX = *x;
375+ m_lastY = *y;
376+ goto exit_loop;
377+ }
382378 m_lastX = *x;
383379 m_lastY = *y;
384- unsigned moved = agg::clip_line_segment (&x0, &y0, &x1, &y1, m_cliprect);
385- // moved >= 4 - Fully clipped
386- // moved & 1 != 0 - First point has been moved
387- // moved & 2 != 0 - Second point has been moved
388- if (moved < 4 ) {
389- if (moved & 1 ) {
390- *x = x0;
391- *y = y0;
392- m_nextX = x1;
393- m_nextY = y1;
394- m_has_next = true ;
395- m_broke_path = true ;
396- return agg::path_cmd_move_to;
397- }
398- *x = x1;
399- *y = y1;
400- return code;
401- }
402- } else {
403380 break ;
381+
382+ default :
383+ if (m_moveto) {
384+ queue_push (agg::path_cmd_move_to, m_lastX, m_lastY);
385+ m_moveto = false ;
386+ }
387+
388+ queue_push (code, *x, *y);
389+ m_lastX = *x;
390+ m_lastY = *y;
391+ goto exit_loop;
404392 }
405393 }
406394
407- m_lastX = *x;
408- m_lastY = *y;
409- return code;
395+ exit_loop:
396+
397+ if (queue_pop (&code, x, y)) {
398+ return code;
399+ }
400+
401+ if (m_moveto &&
402+ m_lastX >= m_cliprect.x1 &&
403+ m_lastX <= m_cliprect.x2 &&
404+ m_lastY >= m_cliprect.y1 &&
405+ m_lastY <= m_cliprect.y2 ) {
406+ *x = m_lastX;
407+ *y = m_lastY;
408+ m_moveto = false ;
409+ return agg::path_cmd_move_to;
410+ }
411+
412+ return agg::path_cmd_stop;
410413 } else {
411414 // If not doing any clipping, just pass along the vertices
412415 // verbatim
0 commit comments