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 */ 8 9 10 #include <Polygon.h> 11 12 #include <stdlib.h> 13 #include <string.h> 14 15 16 BPolygon::BPolygon(const BPoint *ptArray, int32 numPoints) 17 : 18 fBounds(0.0, 0.0, 0.0, 0.0), 19 fCount(numPoints), 20 fPoints(NULL) 21 { 22 if (fCount > 0) { 23 fPoints = (BPoint*)malloc(numPoints * sizeof(BPoint)); 24 25 // Note the use of memcpy here. The assumption is that an array of BPoints can 26 // be copied bit by bit and not use a copy constructor or an assignment 27 // operator. This breaks the containment of BPoint but will result in better 28 // performance. An example where the memcpy will fail would be if BPoint begins 29 // to do lazy copying through reference counting. By copying the bits, we will 30 // copy reference counting state which will not be relevant at the destination. 31 // Luckily, BPoint is a very simple class which isn't likely to change much. 32 // 33 // Similar use of memcpy appears later in this implementation also. 34 35 memcpy(fPoints, ptArray, numPoints * sizeof(BPoint)); 36 _ComputeBounds(); 37 } 38 } 39 40 41 BPolygon::BPolygon(const BPolygon *poly) 42 { 43 *this = *poly; 44 } 45 46 47 BPolygon::BPolygon() 48 : 49 fBounds(0.0, 0.0, 0.0, 0.0), 50 fCount(0), 51 fPoints(NULL) 52 { 53 } 54 55 56 BPolygon::~BPolygon() 57 { 58 free(fPoints); 59 } 60 61 62 BPolygon & 63 BPolygon::operator=(const BPolygon &from) 64 { 65 // Make sure we aren't trying to perform a "self assignment". 66 if (this != &from) { 67 fBounds = from.fBounds; 68 fCount = from.fCount; 69 if (fCount > 0) { 70 fPoints = (BPoint*)malloc(fCount * sizeof(BPoint)); 71 memcpy(fPoints, from.fPoints, fCount * sizeof(BPoint)); 72 } 73 } 74 return *this; 75 } 76 77 78 BRect 79 BPolygon::Frame() const 80 { 81 return fBounds; 82 } 83 84 85 void 86 BPolygon::AddPoints(const BPoint *ptArray, int32 numPoints) 87 { 88 if (numPoints > 0) { 89 fPoints = (BPoint*)realloc(fPoints, (fCount + numPoints) * sizeof(BPoint)); 90 memcpy(fPoints + fCount + numPoints, ptArray, numPoints * sizeof(BPoint)); 91 fCount += numPoints; 92 _ComputeBounds(); 93 } 94 } 95 96 97 int32 98 BPolygon::CountPoints() const 99 { 100 return fCount; 101 } 102 103 104 void 105 BPolygon::MapTo(BRect srcRect, BRect dstRect) 106 { 107 for (int32 i = 0; i < fCount; i++) 108 _MapPoint(fPoints + i, srcRect, dstRect); 109 _MapRectangle(&fBounds, srcRect, dstRect); 110 } 111 112 113 void 114 BPolygon::PrintToStream () const 115 { 116 for (int32 i = 0; i < fCount; i++) 117 fPoints[i].PrintToStream(); 118 } 119 120 121 void 122 BPolygon::_ComputeBounds() 123 { 124 if (fCount == 0) { 125 fBounds = BRect(0.0, 0.0, 0.0, 0.0); 126 return; 127 } 128 129 fBounds = BRect(fPoints[0], fPoints[0]); 130 131 for (int32 i = 1; i < fCount; i++) { 132 if (fPoints[i].x < fBounds.left) 133 fBounds.left = fPoints[i].x; 134 if (fPoints[i].y < fBounds.top) 135 fBounds.top = fPoints[i].y; 136 if (fPoints[i].x > fBounds.right) 137 fBounds.right = fPoints[i].x; 138 if (fPoints[i].y > fBounds.bottom) 139 fBounds.bottom = fPoints[i].y; 140 } 141 } 142 143 144 void 145 BPolygon::_MapPoint(BPoint *point, BRect srcRect, BRect dstRect) 146 { 147 point->x = (point->x - srcRect.left) * dstRect.Width() / srcRect.Width() 148 + dstRect.left; 149 point->y = (point->y - srcRect.top) * dstRect.Height() / srcRect.Height() 150 + dstRect.top; 151 } 152 153 154 void 155 BPolygon::_MapRectangle(BRect *rect, BRect srcRect, BRect dstRect) 156 { 157 BPoint leftTop = rect->LeftTop(); 158 BPoint bottomRight = rect->RightBottom(); 159 160 _MapPoint(&leftTop, srcRect, dstRect); 161 _MapPoint(&bottomRight, srcRect, dstRect); 162 163 *rect = BRect(leftTop, bottomRight); 164 } 165