1 /* 2 * Copyright 2001-2009, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Stephan Aßmus, superstippi@gmx.de 7 * Marc Flerackers, mflerackers@androme.be 8 * Marcus Overhagen 9 */ 10 11 12 #include <Polygon.h> 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include <AffineTransform.h> 19 20 21 // Limit to avoid integer overflow when calculating the size to allocate 22 #define MAX_POINT_COUNT 10000000 23 24 25 BPolygon::BPolygon(const BPoint* points, int32 count) 26 : 27 fBounds(0.0f, 0.0f, -1.0f, -1.0f), 28 fCount(0), 29 fPoints(NULL) 30 { 31 _AddPoints(points, count, true); 32 } 33 34 35 BPolygon::BPolygon(const BPolygon& other) 36 : 37 fBounds(0.0f, 0.0f, -1.0f, -1.0f), 38 fCount(0), 39 fPoints(NULL) 40 { 41 *this = other; 42 } 43 44 45 BPolygon::BPolygon(const BPolygon* other) 46 : 47 fBounds(0.0f, 0.0f, -1.0f, -1.0f), 48 fCount(0), 49 fPoints(NULL) 50 { 51 *this = *other; 52 } 53 54 55 BPolygon::BPolygon() 56 : 57 fBounds(0.0f, 0.0f, -1.0f, -1.0f), 58 fCount(0), 59 fPoints(NULL) 60 { 61 } 62 63 64 BPolygon::~BPolygon() 65 { 66 free(fPoints); 67 } 68 69 70 BPolygon& 71 BPolygon::operator=(const BPolygon& other) 72 { 73 // Make sure we aren't trying to perform a "self assignment". 74 if (this == &other) 75 return *this; 76 77 free(fPoints); 78 fPoints = NULL; 79 fCount = 0; 80 fBounds.Set(0.0f, 0.0f, -1.0f, -1.0f); 81 82 if (_AddPoints(other.fPoints, other.fCount, false)) 83 fBounds = other.fBounds; 84 85 return *this; 86 } 87 88 89 BRect 90 BPolygon::Frame() const 91 { 92 return fBounds; 93 } 94 95 96 void 97 BPolygon::AddPoints(const BPoint* points, int32 count) 98 { 99 _AddPoints(points, count, true); 100 } 101 102 103 int32 104 BPolygon::CountPoints() const 105 { 106 return fCount; 107 } 108 109 110 void 111 BPolygon::MapTo(BRect source, BRect destination) 112 { 113 for (uint32 i = 0; i < fCount; i++) 114 _MapPoint(fPoints + i, source, destination); 115 116 _MapRectangle(&fBounds, source, destination); 117 } 118 119 120 void 121 BPolygon::PrintToStream() const 122 { 123 for (uint32 i = 0; i < fCount; i++) 124 fPoints[i].PrintToStream(); 125 } 126 127 128 //void 129 //BPolygon::TransformBy(const BAffineTransform& transform) 130 //{ 131 // transform.Apply(fPoints, (int32)fCount); 132 // _ComputeBounds(); 133 //} 134 // 135 // 136 //BPolygon& 137 //BPolygon::TransformBySelf(const BAffineTransform& transform) 138 //{ 139 // TransformBy(transform); 140 // return *this; 141 //} 142 // 143 // 144 //BPolygon 145 //BPolygon::TransformByCopy(const BAffineTransform& transform) const 146 //{ 147 // BPolygon copy(this); 148 // copy.TransformBy(transform); 149 // return copy; 150 //} 151 152 153 // #pragma mark - BPolygon private methods 154 155 156 bool 157 BPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds) 158 { 159 if (points == NULL || count <= 0) 160 return false; 161 if (count > MAX_POINT_COUNT || (fCount + count) > MAX_POINT_COUNT) { 162 fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") - too many points" 163 "\n", count); 164 return false; 165 } 166 167 BPoint* newPoints = (BPoint*)realloc(fPoints, (fCount + count) 168 * sizeof(BPoint)); 169 if (newPoints == NULL) { 170 fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") out of memory\n", 171 count); 172 return false; 173 } 174 175 fPoints = newPoints; 176 memcpy(fPoints + fCount, points, count * sizeof(BPoint)); 177 fCount += count; 178 179 if (computeBounds) 180 _ComputeBounds(); 181 182 return true; 183 } 184 185 186 void 187 BPolygon::_ComputeBounds() 188 { 189 if (fCount == 0) { 190 fBounds = BRect(0.0, 0.0, -1.0f, -1.0f); 191 return; 192 } 193 194 fBounds = BRect(fPoints[0], fPoints[0]); 195 196 for (uint32 i = 1; i < fCount; i++) { 197 if (fPoints[i].x < fBounds.left) 198 fBounds.left = fPoints[i].x; 199 200 if (fPoints[i].y < fBounds.top) 201 fBounds.top = fPoints[i].y; 202 203 if (fPoints[i].x > fBounds.right) 204 fBounds.right = fPoints[i].x; 205 206 if (fPoints[i].y > fBounds.bottom) 207 fBounds.bottom = fPoints[i].y; 208 } 209 } 210 211 212 void 213 BPolygon::_MapPoint(BPoint* point, const BRect& source, 214 const BRect& destination) 215 { 216 point->x = (point->x - source.left) * destination.Width() / source.Width() 217 + destination.left; 218 point->y = (point->y - source.top) * destination.Height() / source.Height() 219 + destination.top; 220 } 221 222 223 void 224 BPolygon::_MapRectangle(BRect* rect, const BRect& source, 225 const BRect& destination) 226 { 227 BPoint leftTop = rect->LeftTop(); 228 BPoint bottomRight = rect->RightBottom(); 229 230 _MapPoint(&leftTop, source, destination); 231 _MapPoint(&bottomRight, source, destination); 232 233 *rect = BRect(leftTop, bottomRight); 234 } 235