1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2004, Haiku, Inc. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: clipping.h 23 // Author: Stefano Ceccherini (burton666@libero.it) 24 // Description: Helper methods to manipulate clipping_rects 25 //------------------------------------------------------------------------------ 26 #ifndef __CLIPPING_H 27 #define __CLIPPING_H 28 29 #include <Region.h> 30 #include <SupportDefs.h> 31 32 33 /* Some methods to manipulate clipping_rects. 34 basically you can do almost everything you do with 35 BRects, just that clipping_rects can only have integer 36 coordinates (a thing that makes these perfect for drawing 37 calculations). 38 */ 39 40 41 // Returns the union of the given rects. 42 static inline clipping_rect 43 union_rect(const clipping_rect &r1, const clipping_rect &r2) 44 { 45 clipping_rect rect; 46 47 rect.left = min_c(r1.left, r2.left); 48 rect.top = min_c(r1.top, r2.top); 49 rect.right = max_c(r1.right, r2.right); 50 rect.bottom = max_c(r1.bottom, r2.bottom); 51 52 return rect; 53 } 54 55 56 // Returns the intersection of the given rects. 57 // The caller should check if the returned rect is valid. If it isn't valid, 58 // then the two rectangles don't intersect. 59 static inline clipping_rect 60 sect_rect(const clipping_rect &r1, const clipping_rect &r2) 61 { 62 clipping_rect rect; 63 64 rect.left = max_c(r1.left, r2.left); 65 rect.top = max_c(r1.top, r2.top); 66 rect.right = min_c(r1.right, r2.right); 67 rect.bottom = min_c(r1.bottom, r2.bottom); 68 69 return rect; 70 } 71 72 73 // Adds the given offsets to the given rect. 74 static inline void 75 offset_rect(clipping_rect &rect, int32 x, int32 y) 76 { 77 rect.left += x; 78 rect.top += y; 79 rect.right += x; 80 rect.bottom += y; 81 } 82 83 84 static inline void 85 scale_rect(clipping_rect& rect, float x, float y) 86 { 87 rect.left = (int)(rect.left * x); 88 rect.top = (int)(rect.top * y); 89 rect.right = (int)((rect.right + 1) * x) - 1; 90 rect.bottom = (int)((rect.bottom + 1) * y) - 1; 91 } 92 93 94 // Converts the given clipping_rect to a BRect 95 static inline BRect 96 to_BRect(const clipping_rect &rect) 97 { 98 return BRect((float)rect.left, (float)rect.top, 99 (float)rect.right, (float)rect.bottom); 100 } 101 102 103 // Converts the given BRect to a clipping_rect. 104 static inline clipping_rect 105 to_clipping_rect(const BRect &rect) 106 { 107 clipping_rect clipRect; 108 109 // NOTE: test fractional coords BRects -> BRegion on R5 110 // and compare with this implementation... 111 // clipRect.left = (int32)floorf(rect.left); 112 // clipRect.top = (int32)floorf(rect.top); 113 // clipRect.right = (int32)ceilf(rect.right); 114 // clipRect.bottom = (int32)ceilf(rect.bottom); 115 116 // NOTE: clipping_rects are used as "pixel indices" 117 // therefor, it should be ok to convert them like this: 118 clipRect.left = (int32)rect.left; 119 clipRect.top = (int32)rect.top; 120 clipRect.right = (int32)rect.right; 121 clipRect.bottom = (int32)rect.bottom; 122 123 return clipRect; 124 } 125 126 127 // Checks if the given point lies in the given rect's area 128 static inline bool 129 point_in(const clipping_rect &rect, int32 px, int32 py) 130 { 131 if (px >= rect.left && px <= rect.right 132 && py >= rect.top && py <= rect.bottom) 133 return true; 134 return false; 135 } 136 137 138 // Same as above, but it accepts a BPoint parameter 139 static inline bool 140 point_in(const clipping_rect &rect, const BPoint &pt) 141 { 142 if (pt.x >= rect.left && pt.x <= rect.right 143 && pt.y >= rect.top && pt.y <= rect.bottom) 144 return true; 145 return false; 146 } 147 148 149 static inline bool 150 rect_contains(const clipping_rect &rect, const clipping_rect &testRect) 151 { 152 return rect.top <= testRect.top && rect.bottom >= testRect.bottom 153 && rect.left <= testRect.left && rect.right >= testRect.right; 154 } 155 156 157 // Checks if the rect is valid 158 static inline bool 159 valid_rect(const clipping_rect &rect) 160 { 161 if (rect.left <= rect.right && rect.top <= rect.bottom) 162 return true; 163 return false; 164 } 165 166 167 // Checks if the two rects intersect. 168 static inline bool 169 rects_intersect(const clipping_rect &rectA, const clipping_rect &rectB) 170 { 171 // We behave like BRect::Intersects() does: 172 // we return false if one of the two rects is not valid 173 if (!valid_rect(rectA) || !valid_rect(rectB)) 174 return false; 175 176 // TODO: Is there a better algorithm ? 177 // the one we used is faster than 178 // ' return valid_rect(sect_rect(rectA, rectB)); ', though. 179 180 return !(rectA.left > rectB.right || rectA.top > rectB.bottom 181 || rectA.right < rectB.left || rectA.bottom < rectB.top); 182 } 183 184 185 // Returns the width of the given rect. 186 static inline int32 187 rect_width(const clipping_rect &rect) 188 { 189 return rect.right - rect.left; 190 } 191 192 193 // Returns the height of the given rect. 194 static inline int32 195 rect_height(const clipping_rect &rect) 196 { 197 return rect.bottom - rect.top; 198 } 199 200 #endif // __CLIPPING_H 201