1 /* 2 * Copyright 2001-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers, mflerackers@androme.be 7 * Marcus Overhagen 8 */ 9 10 11 #include <Polygon.h> 12 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <string.h> 16 17 18 // Limit to avoid integer overflow when calculating the size to allocate 19 #define MAX_POINT_COUNT 10000000 20 21 22 BPolygon::BPolygon(const BPoint *ptArray, int32 numPoints) 23 : 24 fBounds(0.0, 0.0, 0.0, 0.0), 25 fCount(numPoints), 26 fPoints(NULL) 27 { 28 if (fCount) { 29 if (fCount > MAX_POINT_COUNT) 30 debugger("BPolygon::BPolygon too many points"); 31 32 // Note the use of memcpy here. The assumption is that an array of BPoints can 33 // be copied bit by bit and not use a copy constructor or an assignment 34 // operator. This breaks the containment of BPoint but will result in better 35 // performance. An example where the memcpy will fail would be if BPoint begins 36 // to do lazy copying through reference counting. By copying the bits, we will 37 // copy reference counting state which will not be relevant at the destination. 38 // Luckily, BPoint is a very simple class which isn't likely to change much. 39 // 40 // Similar use of memcpy appears later in this implementation also. 41 size_t size = fCount * sizeof(BPoint); 42 fPoints = (BPoint *)malloc(size); 43 if (!fPoints) { 44 fprintf(stderr, "BPolygon::BPolygon out of memory\n"); 45 fCount = 0; 46 return; 47 } 48 memcpy(fPoints, ptArray, size); 49 _ComputeBounds(); 50 } 51 } 52 53 54 BPolygon::BPolygon(const BPolygon *poly) 55 : 56 fBounds(0.0, 0.0, 0.0, 0.0), 57 fCount(0), 58 fPoints(NULL) 59 { 60 *this = *poly; 61 } 62 63 64 BPolygon::BPolygon() 65 : 66 fBounds(0.0, 0.0, 0.0, 0.0), 67 fCount(0), 68 fPoints(NULL) 69 { 70 } 71 72 73 BPolygon::~BPolygon() 74 { 75 free(fPoints); 76 } 77 78 79 BPolygon & 80 BPolygon::operator=(const BPolygon &from) 81 { 82 // Make sure we aren't trying to perform a "self assignment". 83 if (this != &from) { 84 free(fPoints); 85 fBounds = from.fBounds; 86 fCount = from.fCount; 87 if (fCount) { 88 if (fCount > MAX_POINT_COUNT) 89 debugger("BPolygon::operator= too many points"); 90 fPoints = (BPoint *)malloc(fCount * sizeof(BPoint)); 91 if (!fPoints) { 92 fprintf(stderr, "BPolygon::operator= out of memory\n"); 93 fCount = 0; 94 } else { 95 memcpy(fPoints, from.fPoints, fCount * sizeof(BPoint)); 96 } 97 } else { 98 fPoints = NULL; 99 } 100 } 101 return *this; 102 } 103 104 105 BRect 106 BPolygon::Frame() const 107 { 108 return fBounds; 109 } 110 111 112 void 113 BPolygon::AddPoints(const BPoint *ptArray, int32 numPoints) 114 { 115 if (numPoints < 0) 116 debugger("BPolygon::AddPoints negative points"); 117 if (numPoints > MAX_POINT_COUNT || (fCount + numPoints) > MAX_POINT_COUNT) 118 debugger("BPolygon::AddPoints too many points"); 119 120 if (numPoints > 0) { 121 BPoint *points = (BPoint *)realloc(fPoints, (fCount + numPoints) * sizeof(BPoint)); 122 if (!points) { 123 fprintf(stderr, "BPolygon::AddPoints out of memory\n"); 124 } else { 125 fPoints = points; 126 memcpy(fPoints + fCount, ptArray, numPoints * sizeof(BPoint)); 127 fCount += numPoints; 128 _ComputeBounds(); 129 } 130 } 131 } 132 133 134 int32 135 BPolygon::CountPoints() const 136 { 137 return fCount; 138 } 139 140 141 void 142 BPolygon::MapTo(BRect srcRect, BRect dstRect) 143 { 144 for (uint32 i = 0; i < fCount; i++) 145 _MapPoint(fPoints + i, srcRect, dstRect); 146 _MapRectangle(&fBounds, srcRect, dstRect); 147 } 148 149 150 void 151 BPolygon::PrintToStream () const 152 { 153 for (uint32 i = 0; i < fCount; i++) 154 fPoints[i].PrintToStream(); 155 } 156 157 158 void 159 BPolygon::_ComputeBounds() 160 { 161 if (fCount == 0) { 162 fBounds = BRect(0.0, 0.0, 0.0, 0.0); 163 return; 164 } 165 166 fBounds = BRect(fPoints[0], fPoints[0]); 167 168 for (uint32 i = 1; i < fCount; i++) { 169 if (fPoints[i].x < fBounds.left) 170 fBounds.left = fPoints[i].x; 171 if (fPoints[i].y < fBounds.top) 172 fBounds.top = fPoints[i].y; 173 if (fPoints[i].x > fBounds.right) 174 fBounds.right = fPoints[i].x; 175 if (fPoints[i].y > fBounds.bottom) 176 fBounds.bottom = fPoints[i].y; 177 } 178 } 179 180 181 void 182 BPolygon::_MapPoint(BPoint *point, BRect srcRect, BRect dstRect) 183 { 184 point->x = (point->x - srcRect.left) * dstRect.Width() / srcRect.Width() 185 + dstRect.left; 186 point->y = (point->y - srcRect.top) * dstRect.Height() / srcRect.Height() 187 + dstRect.top; 188 } 189 190 191 void 192 BPolygon::_MapRectangle(BRect *rect, BRect srcRect, BRect dstRect) 193 { 194 BPoint leftTop = rect->LeftTop(); 195 BPoint bottomRight = rect->RightBottom(); 196 197 _MapPoint(&leftTop, srcRect, dstRect); 198 _MapPoint(&bottomRight, srcRect, dstRect); 199 200 *rect = BRect(leftTop, bottomRight); 201 } 202