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