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 25BPolygon::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 35BPolygon::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 45BPolygon::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 55BPolygon::BPolygon() 56 : 57 fBounds(0.0f, 0.0f, -1.0f, -1.0f), 58 fCount(0), 59 fPoints(NULL) 60{ 61} 62 63 64BPolygon::~BPolygon() 65{ 66 free(fPoints); 67} 68 69 70BPolygon& 71BPolygon::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 89BRect 90BPolygon::Frame() const 91{ 92 return fBounds; 93} 94 95 96void 97BPolygon::AddPoints(const BPoint* points, int32 count) 98{ 99 _AddPoints(points, count, true); 100} 101 102 103int32 104BPolygon::CountPoints() const 105{ 106 return fCount; 107} 108 109 110void 111BPolygon::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 120void 121BPolygon::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 156bool 157BPolygon::_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((void*)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((void*)(fPoints + fCount), points, count * sizeof(BPoint)); 177 fCount += count; 178 179 if (computeBounds) 180 _ComputeBounds(); 181 182 return true; 183} 184 185 186void 187BPolygon::_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 212void 213BPolygon::_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 223void 224BPolygon::_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