Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
Classes | Macros | Functions
OOPolygonSprite.m File Reference
import "OOPolygonSprite.h"
import "OOCollectionExtractors.h"
import "OOMacroOpenGL.h"
import "OOMaths.h"
import "OOPointMaths.h"
import "OOGraphicsResetManager.h"
import "ResourceManager.h"
import "legacy_random.h"
+ Include dependency graph for OOPolygonSprite.m:

Go to the source code of this file.

Classes

category  OOPolygonSprite(Private)
 
struct  TessPolygonData
 

Macros

#define APIENTRY
 
#define kCosMitreLimit   0.866f
 

Functions

static NSArray * DataArrayToPoints (TessPolygonData *data, NSArray *dataArray)
 
static NSArray * BuildOutlineContour (NSArray *dataArray, GLfloat width, BOOL inner)
 
static void SubmitVertices (GLUtesselator *tesselator, TessPolygonData *polygonData, NSArray *contour)
 
static BOOL GrowTessPolygonData (TessPolygonData *data, size_t capacityHint)
 
static BOOL AppendVertex (TessPolygonData *data, NSPoint vertex)
 
static void SVGDumpBegin (TessPolygonData *data)
 
static void SVGDumpEnd (TessPolygonData *data)
 
static void SVGDumpBeginGroup (TessPolygonData *data, NSString *name)
 
static void SVGDumpEndGroup (TessPolygonData *data)
 
static void SVGDumpAppendBaseContour (TessPolygonData *data, NSArray *points)
 
static void SVGDumpBeginPrimitive (TessPolygonData *data)
 
static void SVGDumpEndPrimitive (TessPolygonData *data)
 
static void SVGDumpAppendTriangle (TessPolygonData *data, NSPoint v0, NSPoint v1, NSPoint v2)
 
static void APIENTRY TessBeginCallback (GLenum type, void *polygonData)
 
static void APIENTRY TessVertexCallback (void *vertexData, void *polygonData)
 
static void APIENTRY TessCombineCallback (GLdouble coords[3], void *vertexData[4], GLfloat weight[4], void **outData, void *polygonData)
 
static void APIENTRY TessEndCallback (void *polygonData)
 
static void APIENTRY ErrorCallback (GLenum error, void *polygonData)
 

Macro Definition Documentation

◆ APIENTRY

#define APIENTRY

Definition at line 51 of file OOPolygonSprite.m.

◆ kCosMitreLimit

#define kCosMitreLimit   0.866f

Definition at line 55 of file OOPolygonSprite.m.

Referenced by BuildOutlineContour().

Function Documentation

◆ AppendVertex()

static BOOL AppendVertex ( TessPolygonData * data,
NSPoint vertex )
static

Definition at line 644 of file OOPolygonSprite.m.

645{
646 NSCParameterAssert(data != NULL);
647
648 if (data->capacity == data->count && !GrowTessPolygonData(data, data->capacity * 2)) return NO;
649
650 data->data[data->count * 2] = vertex.x;
651 data->data[data->count * 2 + 1] = vertex.y;
652 data->count++;
653 return YES;
654}
static BOOL GrowTessPolygonData(TessPolygonData *data, size_t capacityHint)

References TessPolygonData::capacity, TessPolygonData::count, TessPolygonData::data, and GrowTessPolygonData().

Referenced by TessVertexCallback().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ BuildOutlineContour()

static NSArray * BuildOutlineContour ( NSArray * dataArray,
GLfloat width,
BOOL inner )
static

Definition at line 508 of file OOPolygonSprite.m.

509{
510 NSUInteger i, count = [dataArray count];
511 if (count < 2) return dataArray;
512
513 /*
514 Generate inner or outer boundary for a contour, offset by the specified
515 width inwards/outwards from the line. At anticlockwise (convex) corners
516 sharper than acos(kCosMitreLimit), the corner is mitred, i.e. an
517 additional line segment is generated so the outline doesn't protrude
518 arbitratrily far.
519
520 Overview of the maths:
521 For each vertex, we consider a normalized vector A from the previous
522 vertex and a normalized vector B to the next vertex. (These are always
523 defined since the polygons are closed.)
524
525 The dot product of A and B is the cosine of the angle, which we compare
526 to kCosMitreLimit to determine mitreing. If the dot product is exactly
527 1, the vectors are antiparallel and we have a cap; the mitreing case
528 handles this implicitly. (The non-mitreing case would result in a
529 divide-by-zero.)
530
531 Non-mitreing case:
532 To position the vertex, we need a vector N normal to the corner.
533 We observe that A + B is tangent to the corner, and a 90 degree
534 rotation in 2D is trivial. The offset along this line is
535 proportional to the secant of the angle between N and the 90 degree
536 rotation of A (or B; the angle is by definition the same), or
537 width / (N dot rA).
538 Since both N and rA are rotated by ninety degrees in the same
539 direction, we can cut out both rotations (i.e., using the tangent
540 and A) and get the same result.
541
542 Mitreing case:
543 The two new vertices are the original vertex offset by scale along
544 the ninety-degree rotation of A and B respectively.
545 */
546
547 NSPoint prev, current, next;
548 if (inner)
549 {
550 prev = [[dataArray objectAtIndex:0] pointValue];
551 current = [[dataArray objectAtIndex:count -1] pointValue];
552 next = [[dataArray objectAtIndex:count - 2] pointValue];
553 }
554 else
555 {
556 prev = [[dataArray objectAtIndex:count - 1] pointValue];
557 current = [[dataArray objectAtIndex:0] pointValue];
558 next = [[dataArray objectAtIndex:1] pointValue];
559 }
560
561 NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
562
563 for (i = 0; i < count; i++)
564 {
565 NSPoint a = PtNormal(PtSub(current, prev));
566 NSPoint b = PtNormal(PtSub(next, current));
567
568 CGFloat dot = PtDot(a, b);
569 BOOL clockwise = PtCross(a, b) < 0.0f;
570
571 if (-dot < kCosMitreLimit || !clockwise)
572 {
573 // Non-mitreing case.
574 NSPoint t = PtNormal(PtAdd(a, b));
575 NSPoint v = PtScale(PtRotACW(t), width / PtDot(t, a));
576
577 if (!isnan(v.x) && !isnan(v.y))
578 {
579 [result addObject:[NSValue valueWithPoint:PtAdd(v, current)]];
580 }
581 }
582 else
583 {
584 // Mitreing case.
585 NSPoint v1 = PtScale(PtAdd(PtRotACW(a), a), width);
586 NSPoint v2 = PtScale(PtSub(PtRotACW(b), b), width);
587
588 if (!isnan(v1.x) && !isnan(v1.y))
589 {
590 [result addObject:[NSValue valueWithPoint:PtAdd(v1, current)]];
591 }
592 if (!isnan(v2.x) && !isnan(v2.y))
593 {
594 [result addObject:[NSValue valueWithPoint:PtAdd(v2, current)]];
595 }
596 }
597
598 prev = current;
599 current = next;
600
601 if (inner)
602 {
603 next = [[dataArray objectAtIndex:(count * 2 - 3 - i) % count] pointValue];
604 }
605 else
606 {
607 next = [[dataArray objectAtIndex:(i + 2) % count] pointValue];
608 }
609 }
610
611 return result;
612}
unsigned count
OOINLINE CGFloat PtDot(NSPoint a, NSPoint b)
OOINLINE NSPoint PtScale(NSPoint p, CGFloat scale)
OOINLINE NSPoint PtSub(NSPoint a, NSPoint b)
OOINLINE NSPoint PtRotACW(NSPoint p)
OOINLINE NSPoint PtNormal(NSPoint p)
OOINLINE CGFloat PtCross(NSPoint a, NSPoint b)
OOINLINE NSPoint PtAdd(NSPoint a, NSPoint b)
Definition OOPointMaths.h:6
#define kCosMitreLimit

References count, kCosMitreLimit, PtAdd(), PtCross(), PtDot(), PtNormal(), PtRotACW(), PtScale(), and PtSub().

+ Here is the call graph for this function:

◆ DataArrayToPoints()

static NSArray * DataArrayToPoints ( TessPolygonData * data,
NSArray * dataArray )
static

Definition at line 439 of file OOPolygonSprite.m.

440{
441 /* This converts an icon definition in the form of an array of array of
442 numbers to internal data in the form of an array of arrays of NSValues
443 containing NSPoint data. In addition to repacking the data, it performs
444 the following data processing:
445 * Sequences of duplicate vertices are removed (including across the
446 beginning and end, in case of manually closed contours).
447 * Vertices containing nans or infinities are skipped, Just In Case.
448 * The signed area of each contour is calculated; if it is negative,
449 the contour is clockwise, and we need to flip it.
450 */
451
452 SVGDumpBeginGroup(data, @"Base contours");
453
454 NSUInteger polyIter, polyCount = [dataArray count];
455 NSArray *subArrays[polyCount];
456
457 for (polyIter = 0; polyIter < polyCount; polyIter++)
458 {
459 NSArray *polyDef = [dataArray objectAtIndex:polyIter];
460 NSUInteger vertIter, vertCount = [polyDef count] / 2;
461 NSMutableArray *newPolyDef = [NSMutableArray arrayWithCapacity:vertCount];
462 CGFloat area = 0;
463
464 CGFloat oldX = [polyDef oo_doubleAtIndex:(vertCount -1) * 2];
465 CGFloat oldY = [polyDef oo_doubleAtIndex:(vertCount -1) * 2 + 1];
466
467 for (vertIter = 0; vertIter < vertCount; vertIter++)
468 {
469 CGFloat x = [polyDef oo_doubleAtIndex:vertIter * 2];
470 CGFloat y = [polyDef oo_doubleAtIndex:vertIter * 2 + 1];
471
472 // Skip bad or duplicate vertices.
473 if (x == oldX && y == oldY) continue;
474 if (isnan(x) || isnan(y)) continue;
475 if (!isfinite(x) || !isfinite(y)) continue;
476
477 area += x * oldY - oldX * y;
478
479 oldX = x;
480 oldY = y;
481
482 [newPolyDef addObject:[NSValue valueWithPoint:NSMakePoint(x, y)]];
483 }
484
485 // Eliminate duplicates at ends - the initialization of oldX and oldY will catch one pair, but not extra-silly cases.
486 while ([newPolyDef count] > 1 && [[newPolyDef objectAtIndex:0] isEqual:[newPolyDef lastObject]])
487 {
488 [newPolyDef removeLastObject];
489 }
490
491 if (area >= 0)
492 {
493 subArrays[polyIter] = newPolyDef;
494 }
495 else
496 {
497 subArrays[polyIter] = [[newPolyDef reverseObjectEnumerator] allObjects];
498 }
499
500 SVGDumpAppendBaseContour(data, subArrays[polyIter]);
501 }
502
503 SVGDumpEndGroup(data);
504 return [NSArray arrayWithObjects:subArrays count:polyCount];
505}
static void SVGDumpBeginGroup(TessPolygonData *data, NSString *name)
static void SVGDumpAppendBaseContour(TessPolygonData *data, NSArray *points)
static void SVGDumpEndGroup(TessPolygonData *data)
float y
float x

References count, SVGDumpAppendBaseContour(), SVGDumpBeginGroup(), SVGDumpEndGroup(), x, and y.

+ Here is the call graph for this function:

◆ ErrorCallback()

static void APIENTRY ErrorCallback ( GLenum error,
void * polygonData )
static

Definition at line 777 of file OOPolygonSprite.m.

778{
779 TessPolygonData *data = polygonData;
780 NSCParameterAssert(data != NULL);
781
782 NSString *name = @"";
783#ifndef NDEBUG
784 name = [NSString stringWithFormat:@" \"%@\"", data->name];
785#endif
786
787 char *errStr = (char *)gluErrorString(error);
788
789 OOLog(@"polygonSprite.tesselate.error", @"Error %s (%u) while tesselating polygon%@.", errStr, error, name);
790 data->OK = NO;
791}
#define OOLog(class, format,...)
Definition OOLogging.h:88

References TessPolygonData::OK, and OOLog.

◆ GrowTessPolygonData()

static BOOL GrowTessPolygonData ( TessPolygonData * data,
size_t capacityHint )
static

Definition at line 615 of file OOPolygonSprite.m.

616{
617 NSCParameterAssert(data != NULL);
618
619 size_t minCapacity = data->capacity + 1;
620 size_t desiredCapacity = MAX(capacityHint, minCapacity);
621 size_t newCapacity = 0;
622 GLfloat *newData = realloc(data->data, desiredCapacity * sizeof (GLfloat) * 2);
623 if (newData != NULL)
624 {
625 newCapacity = desiredCapacity;
626 }
627 else
628 {
629 desiredCapacity = minCapacity;
630 newData = realloc(data->data, desiredCapacity * sizeof (GLfloat) * 2);
631 if (newData != NULL) newCapacity = desiredCapacity;
632 }
633
634 if (newData == NULL) return NO;
635
636 NSCAssert(newCapacity > data->capacity, @"Buffer regrow logic error");
637
638 data->data = newData;
639 data->capacity = newCapacity;
640 return YES;
641}
#define MAX(A, B)
Definition OOMaths.h:114

References TessPolygonData::capacity, TessPolygonData::data, and MAX.

Referenced by AppendVertex().

+ Here is the caller graph for this function:

◆ SubmitVertices()

static void SubmitVertices ( GLUtesselator * tesselator,
TessPolygonData * polygonData,
NSArray * contour )
static

Definition at line 418 of file OOPolygonSprite.m.

419{
420 NSUInteger vertexCount = [contour count], vertexIndex;
421 if (vertexCount > 2)
422 {
423 gluTessBeginContour(tesselator);
424
425 for (vertexIndex = 0; vertexIndex < vertexCount && polygonData->OK; vertexIndex++)
426 {
427 NSValue *pointValue = [contour objectAtIndex:vertexIndex];
428 NSPoint p = [pointValue pointValue];
429 GLdouble vert[3] = { p.x, p.y, 0.0 };
430
431 gluTessVertex(tesselator, vert, pointValue);
432 }
433
434 gluTessEndContour(tesselator);
435 }
436}

References TessPolygonData::OK.

◆ SVGDumpAppendBaseContour()

static void SVGDumpAppendBaseContour ( TessPolygonData * data,
NSArray * points )
static

Definition at line 835 of file OOPolygonSprite.m.

836{
837 if (data->debugSVG == nil) return;
838
839 NSString *groupName = [NSString stringWithFormat:@"contour %u", data->svgID++];
840 [data->debugSVG appendFormat:@"\t\t<g id=\"%@\" stroke=\"#BBB\" fill=\"none\">\n\t\t<path stroke-width=\"0.05\" d=\"", groupName];
841
842 NSUInteger i, count = [points count];
843 for (i = 0; i < count; i++)
844 {
845 NSPoint p = [[points objectAtIndex:i] pointValue];
846 [data->debugSVG appendFormat:@"%c %f %f ", (i == 0) ? 'M' : 'L', p.x, -p.y];
847 }
848
849 // Close and add a circle at the first vertex. (SVG has support for end markers, but this isn’t reliable across implementations.)
850 NSPoint p = [[points objectAtIndex:0] pointValue];
851 [data->debugSVG appendFormat:@"z\"/>\n\t\t\t<circle cx=\"%f\" cy=\"%f\" r=\"0.1\" fill=\"#BBB\" stroke=\"none\"/>\n\t\t</g>\n", p.x, -p.y];
852}
return nil
NSMutableString * debugSVG

References count, TessPolygonData::debugSVG, and nil.

Referenced by DataArrayToPoints().

+ Here is the caller graph for this function:

◆ SVGDumpAppendTriangle()

static void SVGDumpAppendTriangle ( TessPolygonData * data,
NSPoint v0,
NSPoint v1,
NSPoint v2 )
static

Definition at line 898 of file OOPolygonSprite.m.

899{
900 if (data->debugSVG == nil) return;
901 [data->debugSVG appendFormat:@"\t\t\t<path d=\"M %f %f L %f %f L %f %f z\"/>\n", v0.x, -v0.y, v1.x, -v1.y, v2.x, -v2.y];
902}

References TessPolygonData::debugSVG, and nil.

Referenced by TessVertexCallback().

+ Here is the caller graph for this function:

◆ SVGDumpBegin()

static void SVGDumpBegin ( TessPolygonData * data)
static

Definition at line 797 of file OOPolygonSprite.m.

798{
799 DESTROY(data->debugSVG);
800 data->debugSVG = [[NSMutableString alloc] initWithString:
801 @"<?xml version=\"1.0\" standalone=\"no\"?>\n"
802 "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
803 "<svg viewBox=\"-5 -5 10 10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"
804 "\t<desc>Oolite polygon sprite debug dump.</desc>\n"
805 "\t\n"
806 ];
807}
#define DESTROY(x)
Definition OOCocoa.h:77

References TessPolygonData::debugSVG, and DESTROY.

◆ SVGDumpBeginGroup()

static void SVGDumpBeginGroup ( TessPolygonData * data,
NSString * name )
static

Definition at line 820 of file OOPolygonSprite.m.

821{
822 if (data->debugSVG == nil) return;
823
824 [data->debugSVG appendFormat:@"\t<g id=\"%@ %u\">\n", name, data->svgID++];
825}

References TessPolygonData::debugSVG, and nil.

Referenced by DataArrayToPoints().

+ Here is the caller graph for this function:

◆ SVGDumpBeginPrimitive()

static void SVGDumpBeginPrimitive ( TessPolygonData * data)
static

Definition at line 855 of file OOPolygonSprite.m.

856{
857 if (data->debugSVG == nil) return;
858
859 NSString *groupName = @"Unknown primitive";
860 switch (data->mode)
861 {
862 case GL_TRIANGLES:
863 groupName = @"Triangle soup";
864 break;
865
866 case GL_TRIANGLE_FAN:
867 groupName = @"Triangle fan";
868 break;
869
870 case GL_TRIANGLE_STRIP:
871 groupName = @"Triangle strip";
872 break;
873 }
874 groupName = [groupName stringByAppendingFormat:@" %u", data->svgID++];
875
876 // Pick random colour for the primitive.
877 uint8_t red = (Ranrot() & 0x3F) + 0x20;
878 uint8_t green = (Ranrot() & 0x3F) + 0x20;
879 uint8_t blue = (Ranrot() & 0x3F) + 0x20;
880 if (!data->generatingOutline)
881 {
882 red += 0x80;
883 green += 0x80;
884 blue += 0x80;
885 }
886
887 [data->debugSVG appendFormat:@"\t\t<g id=\"%@\" fill=\"#%2X%2X%2X\" fill-opacity=\"0.3\" stroke=\"%@\" stroke-width=\"0.01\">\n", groupName, red, green, blue, data->generatingOutline ? @"#060" : @"#008"];
888}
unsigned Ranrot(void)

References TessPolygonData::debugSVG, TessPolygonData::generatingOutline, TessPolygonData::mode, nil, and Ranrot().

Referenced by TessBeginCallback().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SVGDumpEnd()

static void SVGDumpEnd ( TessPolygonData * data)
static

Definition at line 810 of file OOPolygonSprite.m.

811{
812 if (data->debugSVG == nil) return;
813
814 [data->debugSVG appendString:@"</svg>\n"];
815 [ResourceManager writeDiagnosticString:data->debugSVG toFileNamed:[NSString stringWithFormat:@"Polygon Sprites/%@.svg", data->name]];
816 DESTROY(data->debugSVG);
817}

References TessPolygonData::debugSVG, DESTROY, nil, and ResourceManager::writeDiagnosticString:toFileNamed:.

+ Here is the call graph for this function:

◆ SVGDumpEndGroup()

static void SVGDumpEndGroup ( TessPolygonData * data)
static

Definition at line 828 of file OOPolygonSprite.m.

829{
830 if (data->debugSVG == nil) return;
831 [data->debugSVG appendString:@"\t</g>\n"];
832}

References TessPolygonData::debugSVG, and nil.

Referenced by DataArrayToPoints().

+ Here is the caller graph for this function:

◆ SVGDumpEndPrimitive()

static void SVGDumpEndPrimitive ( TessPolygonData * data)
static

Definition at line 891 of file OOPolygonSprite.m.

892{
893 if (data->debugSVG == nil) return;
894 [data->debugSVG appendString:@"\t\t</g>\n"];
895}

References TessPolygonData::debugSVG, and nil.

Referenced by TessEndCallback().

+ Here is the caller graph for this function:

◆ TessBeginCallback()

static void APIENTRY TessBeginCallback ( GLenum type,
void * polygonData )
static

Definition at line 657 of file OOPolygonSprite.m.

658{
659 TessPolygonData *data = polygonData;
660 NSCParameterAssert(data != NULL);
661
662 data->mode = type;
663 data->vCount = 0;
664
666}
static void SVGDumpBeginPrimitive(TessPolygonData *data)

References TessPolygonData::mode, SVGDumpBeginPrimitive(), and TessPolygonData::vCount.

+ Here is the call graph for this function:

◆ TessCombineCallback()

static void APIENTRY TessCombineCallback ( GLdouble coords[3],
void * vertexData[4],
GLfloat weight[4],
void ** outData,
void * polygonData )
static

Definition at line 758 of file OOPolygonSprite.m.

759{
760 NSPoint point = { coords[0], coords[1] };
761 *outData = [NSValue valueWithPoint:point];
762}

◆ TessEndCallback()

static void APIENTRY TessEndCallback ( void * polygonData)
static

Definition at line 765 of file OOPolygonSprite.m.

766{
767 TessPolygonData *data = polygonData;
768 NSCParameterAssert(data != NULL);
769
770 data->mode = 0;
771 data->vCount = 0;
772
774}
static void SVGDumpEndPrimitive(TessPolygonData *data)

References TessPolygonData::mode, SVGDumpEndPrimitive(), and TessPolygonData::vCount.

+ Here is the call graph for this function:

◆ TessVertexCallback()

static void APIENTRY TessVertexCallback ( void * vertexData,
void * polygonData )
static

Definition at line 669 of file OOPolygonSprite.m.

670{
671 TessPolygonData *data = polygonData;
672 NSValue *vertValue = vertexData;
673 NSCParameterAssert(vertValue != NULL && data != NULL);
674 if (!data->OK) return;
675
676 NSPoint p = [vertValue pointValue];
677 NSPoint vertex = { p.x, p.y };
678 size_t vCount = data->vCount++;
679
680 switch (data->mode)
681 {
682 case GL_TRIANGLES:
683 data->OK = AppendVertex(data, vertex);
684#ifndef NDEBUG
685 switch (vCount % 3)
686 {
687 case 0:
688 data->pending0 = vertex;
689 break;
690
691 case 1:
692 data->pending1 = vertex;
693 break;
694
695 case 2:
696 SVGDumpAppendTriangle(data, data->pending0, data->pending1, vertex);
697 }
698#endif
699 break;
700
701 case GL_TRIANGLE_FAN:
702 if (vCount == 0) data->pending0 = vertex;
703 else if (vCount == 1) data->pending1 = vertex;
704 else
705 {
706 data->OK = AppendVertex(data, data->pending0) &&
707 AppendVertex(data, data->pending1) &&
708 AppendVertex(data, vertex);
709 SVGDumpAppendTriangle(data, data->pending0, data->pending1, vertex);
710 data->pending1 = vertex;
711 }
712 break;
713
714 case GL_TRIANGLE_STRIP:
715 if (vCount == 0) data->pending0 = vertex;
716 else if (vCount == 1) data->pending1 = vertex;
717 else
718 {
719 /* In order to produce consistent winding, the vertex->triangle
720 order for GL_TRIANGLE_STRIP is:
721 0, 1, 2
722 2, 1, 3
723 2, 3, 4
724 4, 3, 5
725 4, 5, 6
726 6, 5, 7
727 6, 7, 8
728
729 Vertices 0 and 1 are special-cased above, and the first
730 time we get here it's time for the first triangle, which
731 is pending0, pending1, v. v (i.e., vertex 2) then goes into
732 pending0.
733 For the second triangle, the triangle is again pending0,
734 pending1, v, and we then put v (i.e., vertex 3) into
735 pending1.
736 The third triangle follows the same pattern as the first,
737 and the fourthe the same as the second.
738 In other words, after storing each triangle, v goes into
739 pending0 for even vertex indicies, and pending1 for odd
740 vertex indices.
741 */
742 data->OK = AppendVertex(data, data->pending0) &&
743 AppendVertex(data, data->pending1) &&
744 AppendVertex(data, vertex);
745 SVGDumpAppendTriangle(data, data->pending0, data->pending1, vertex);
746 if ((vCount % 2) == 0) data->pending0 = vertex;
747 else data->pending1 = vertex;
748 }
749 break;
750
751 default:
752 OOLog(@"polygonSprite.tesselate.error", @"Unexpected tesselator primitive mode %u.", data->mode);
753 data->OK = NO;
754 }
755}
static BOOL AppendVertex(TessPolygonData *data, NSPoint vertex)
static void SVGDumpAppendTriangle(TessPolygonData *data, NSPoint v0, NSPoint v1, NSPoint v2)

References AppendVertex(), TessPolygonData::mode, TessPolygonData::OK, OOLog, TessPolygonData::pending0, TessPolygonData::pending1, SVGDumpAppendTriangle(), and TessPolygonData::vCount.

+ Here is the call graph for this function: