Lines 61-84
Link Here
|
61 |
|
61 |
|
62 |
#define _SV_POLY2_CXX |
62 |
#define _SV_POLY2_CXX |
63 |
|
63 |
|
64 |
#ifdef HAVE_GPC_H |
64 |
extern "C" |
65 |
|
|
|
66 |
#ifndef __gpc_h |
67 |
extern "C" |
68 |
{ |
65 |
{ |
69 |
#include <external/gpc/gpc.h> |
66 |
#if defined (HAVE_GPC_H) && !defined (__gpc_h) |
70 |
} |
67 |
# include <external/gpc/gpc.h> |
71 |
#endif |
|
|
72 |
|
73 |
#else |
68 |
#else |
74 |
|
69 |
# ifdef HAVE_LIBART_H |
75 |
// No GPC |
70 |
# include <libart_lgpl/art_misc.h> |
76 |
#define GPC_INT 0 |
71 |
# include <libart_lgpl/art_vpath.h> |
77 |
#define GPC_UNION 0 |
72 |
# include <libart_lgpl/art_svp.h> |
78 |
#define GPC_DIFF 0 |
73 |
# include <libart_lgpl/art_svp_vpath.h> |
79 |
#define GPC_XOR 0 |
74 |
# include <libart_lgpl/art_vpath_svp.h> |
80 |
|
75 |
# include <libart_lgpl/art_svp_ops.h> |
|
|
76 |
# include <libart_lgpl/art_svp_intersect.h> |
77 |
# endif |
78 |
# define GPC_INT 0 |
79 |
# define GPC_UNION 1 |
80 |
# define GPC_DIFF 2 |
81 |
# define GPC_XOR 3 |
81 |
#endif // HAVE_GPC_H |
82 |
#endif // HAVE_GPC_H |
|
|
83 |
} |
82 |
|
84 |
|
83 |
#include <cstring> |
85 |
#include <cstring> |
84 |
#include <cmath> |
86 |
#include <cmath> |
Lines 366-372
void PolyPolygon::Optimize( ULONG nOptim
Link Here
|
366 |
if( bEdges ) |
368 |
if( bEdges ) |
367 |
{ |
369 |
{ |
368 |
const Rectangle aBound( GetBoundRect() ); |
370 |
const Rectangle aBound( GetBoundRect() ); |
369 |
|
371 |
|
370 |
fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5; |
372 |
fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5; |
371 |
nPercent = pData ? pData->GetPercentValue() : 50; |
373 |
nPercent = pData ? pData->GetPercentValue() : 50; |
372 |
nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES; |
374 |
nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES; |
Lines 538-555
void PolyPolygon::ImplDoOperation( const
Link Here
|
538 |
} |
540 |
} |
539 |
|
541 |
|
540 |
#else |
542 |
#else |
541 |
// No GPC implementation |
543 |
#ifdef HAVE_LIBART_H |
542 |
|
544 |
|
543 |
void* PolyPolygon::ImplCreateGPCPolygon() const |
545 |
/* Finds the index of the upper rightmost vertex of a polygon */ |
|
|
546 |
static int |
547 |
upper_rightmost_vertex (const Polygon &poly) |
548 |
{ |
549 |
int n; |
550 |
int i; |
551 |
double x, y; |
552 |
int k; |
553 |
|
554 |
n = poly.GetSize (); |
555 |
|
556 |
k = 0; |
557 |
x = poly[0].X (); |
558 |
y = poly[0].Y (); |
559 |
|
560 |
for (i = 1; i < n; i++) |
561 |
if (poly[i].Y () < y || (poly[0].Y () == y && poly[i].X () > x)) { |
562 |
k = i; |
563 |
x = poly[i].X (); |
564 |
y = poly[i].Y (); |
565 |
} |
566 |
|
567 |
return k; |
568 |
} |
569 |
|
570 |
/* Returns whether a polygon is specified in counterclockwise order */ |
571 |
static BOOL |
572 |
poly_is_ccw (const Polygon &poly) |
573 |
{ |
574 |
int n; |
575 |
int k; |
576 |
double cross; |
577 |
|
578 |
n = poly.GetSize (); |
579 |
|
580 |
if (n == 0) |
581 |
return TRUE; |
582 |
|
583 |
k = upper_rightmost_vertex (poly); |
584 |
|
585 |
const Point &a = poly[(k + n - 1) % n]; |
586 |
const Point &b = poly[k]; |
587 |
const Point &c = poly[(k + 1) % n]; |
588 |
|
589 |
cross = -(a.X () * b.Y () - a.Y () * b.X () + |
590 |
a.Y () * c.X () - a.X () * c.Y () + |
591 |
b.X () * c.Y () - c.X () * b.Y ()); |
592 |
|
593 |
return (cross > 0); |
594 |
} |
595 |
|
596 |
void * |
597 |
PolyPolygon::ImplCreateArtVpath () const |
598 |
{ |
599 |
ArtVpath *vpath; |
600 |
int n_contours; |
601 |
int n_vertices; |
602 |
int i, v; |
603 |
|
604 |
n_contours = Count (); |
605 |
n_vertices = 0; |
606 |
for (i = 0; i < n_contours; i++) { |
607 |
const Polygon &poly = GetObject (i); |
608 |
n_vertices += poly.GetSize () + 1; /* plus 1 for if we have to close the path */ |
609 |
} |
610 |
|
611 |
n_vertices++; /* for the ART_END terminator */ |
612 |
|
613 |
vpath = art_new (ArtVpath, n_vertices); |
614 |
v = 0; |
615 |
|
616 |
for (i = 0; i < n_contours; i++) { |
617 |
int j, k; |
618 |
int n; |
619 |
const Polygon &poly = GetObject (i); |
620 |
BOOL ccw; |
621 |
|
622 |
n = poly.GetSize (); |
623 |
|
624 |
ccw = poly_is_ccw (poly); |
625 |
|
626 |
/* Holes or inside contours need to be listed out in reverse |
627 |
* clockwise direction to the main outwards contour, but OO.o |
628 |
* does not seem to handle holes at all. So we'll just list all |
629 |
* the contours as non-holes, e.g. in normal counterclockwise |
630 |
* order. |
631 |
*/ |
632 |
|
633 |
if (ccw) |
634 |
k = 0; |
635 |
else |
636 |
k = n - 1; |
637 |
|
638 |
for (j = 0; j < n; j++) { |
639 |
const Point &point = poly[k]; |
640 |
vpath[v].code = (j == 0) ? ART_MOVETO : ART_LINETO; |
641 |
vpath[v].x = point.X (); |
642 |
vpath[v].y = point.Y (); |
643 |
|
644 |
if (ccw) |
645 |
k++; |
646 |
else |
647 |
k--; |
648 |
|
649 |
v++; |
650 |
} |
651 |
|
652 |
/* Close the path if needed */ |
653 |
if (n > 0 && |
654 |
(vpath[v - 1].x != vpath[v - n].x || |
655 |
vpath[v - 1].y != vpath[v - n].y)) { |
656 |
vpath[v].code = ART_LINETO; |
657 |
vpath[v].x = vpath[v - n].x; |
658 |
vpath[v].y = vpath[v - n].y; |
659 |
v++; |
660 |
} |
661 |
} |
662 |
|
663 |
vpath[v].code = ART_END; |
664 |
|
665 |
return vpath; |
666 |
} |
667 |
|
668 |
void |
669 |
PolyPolygon::ImplSetFromArtVpath (void *_vpath) |
670 |
{ |
671 |
ArtVpath *vpath; |
672 |
|
673 |
vpath = (ArtVpath *) _vpath; |
674 |
|
675 |
Clear (); |
676 |
|
677 |
while (vpath->code != ART_END) { |
678 |
ArtVpath *p; |
679 |
int n, n_vertices; |
680 |
|
681 |
n = 0; |
682 |
for (p = vpath; n == 0 || p->code == ART_LINETO; p++) |
683 |
n++; |
684 |
|
685 |
/* Remove the last duplicated point from closed subpaths */ |
686 |
if (n > 0 && |
687 |
vpath[n - 1].x == vpath[0].x && |
688 |
vpath[n - 1].y == vpath[0].y) |
689 |
n_vertices = n - 1; |
690 |
else |
691 |
n_vertices = n; |
692 |
|
693 |
if (n_vertices != 0) { |
694 |
int i; |
695 |
|
696 |
Polygon poly (n_vertices); |
697 |
|
698 |
p = vpath; |
699 |
for (i = 0; i < n_vertices; i++) { |
700 |
Point &point = poly[i]; |
701 |
|
702 |
point.X () = FRound (p->x); |
703 |
point.Y () = FRound (p->y); |
704 |
|
705 |
p++; |
706 |
} |
707 |
|
708 |
Insert (poly); |
709 |
} |
710 |
|
711 |
vpath += n; |
712 |
} |
713 |
} |
714 |
|
715 |
/* Converts an arbitrary SVP to an even-odd SVP */ |
716 |
static ArtSVP * |
717 |
svp_to_even_odd (ArtSVP *pSvp) |
544 |
{ |
718 |
{ |
545 |
return NULL; |
719 |
ArtSVP *pResult; |
|
|
720 |
ArtSvpWriter *pSvw; |
721 |
|
722 |
pSvw = art_svp_writer_rewind_new( ART_WIND_RULE_ODDEVEN ); |
723 |
art_svp_intersector( pSvp, pSvw); |
724 |
|
725 |
pResult = art_svp_writer_rewind_reap( pSvw ); |
726 |
/* Shallow free because the result contains shared segments */ |
727 |
art_free( pSvp ); |
728 |
|
729 |
return pResult; |
546 |
} |
730 |
} |
547 |
|
731 |
|
548 |
void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const |
732 |
void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const |
|
|
733 |
{ |
734 |
ArtVpath *a, *b; |
735 |
ArtSVP *sa, *sb, *s; |
736 |
|
737 |
a = (ArtVpath *) ImplCreateArtVpath (); |
738 |
b = (ArtVpath *) rPolyPoly.ImplCreateArtVpath (); |
739 |
|
740 |
sa = svp_to_even_odd (art_svp_from_vpath (a)); |
741 |
sb = svp_to_even_odd (art_svp_from_vpath (b)); |
742 |
|
743 |
art_free (a); |
744 |
art_free (b); |
745 |
|
746 |
switch (nOperation) { |
747 |
case GPC_UNION: |
748 |
s = art_svp_union (sa, sb); |
749 |
a = art_vpath_from_svp (s); |
750 |
art_svp_free (s); |
751 |
break; |
752 |
case GPC_DIFF: |
753 |
s = art_svp_minus (sa, sb); |
754 |
a = art_vpath_from_svp (s); |
755 |
art_svp_free (s); |
756 |
break; |
757 |
case GPC_XOR: |
758 |
s = art_svp_diff (sa, sb); /* symmetric difference, *not* set difference */ |
759 |
a = art_vpath_from_svp (s); |
760 |
art_svp_free (s); |
761 |
break; |
762 |
default: |
763 |
/* Odd ... */ |
764 |
case GPC_INT: |
765 |
s = art_svp_intersect (sa, sb); |
766 |
a = art_vpath_from_svp (s); |
767 |
art_svp_free (s); |
768 |
break; |
769 |
} |
770 |
|
771 |
|
772 |
rResult.ImplSetFromArtVpath (a); |
773 |
art_free (a); |
774 |
} |
775 |
|
776 |
#else // No GPC or libart implementations |
777 |
|
778 |
void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const |
549 |
{ |
779 |
{ |
550 |
return; |
|
|
551 |
} |
780 |
} |
552 |
|
781 |
|
|
|
782 |
#endif // HAVE_LIBART_H |
553 |
#endif // HAVE_GPC_H |
783 |
#endif // HAVE_GPC_H |
554 |
|
784 |
|
555 |
// ----------------------------------------------------------------------- |
785 |
// ----------------------------------------------------------------------- |