1 /* 2 * Copyright 2001-2004, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stefano Ceccherini, burton666@libero.it 7 */ 8 #ifndef __CLIPPING_H 9 #define __CLIPPING_H 10 11 #include <Region.h> 12 #include <SupportDefs.h> 13 14 15 /* Some methods to manipulate clipping_rects. 16 basically you can do almost everything you do with 17 BRects, just that clipping_rects can only have integer 18 coordinates (a thing that makes these perfect for drawing 19 calculations). 20 */ 21 22 23 // Returns the union of the given rects. 24 static inline clipping_rect 25 union_rect(const clipping_rect &r1, const clipping_rect &r2) 26 { 27 clipping_rect rect; 28 29 rect.left = min_c(r1.left, r2.left); 30 rect.top = min_c(r1.top, r2.top); 31 rect.right = max_c(r1.right, r2.right); 32 rect.bottom = max_c(r1.bottom, r2.bottom); 33 34 return rect; 35 } 36 37 38 // Returns the intersection of the given rects. 39 // The caller should check if the returned rect is valid. If it isn't valid, 40 // then the two rectangles don't intersect. 41 static inline clipping_rect 42 sect_rect(const clipping_rect &r1, const clipping_rect &r2) 43 { 44 clipping_rect rect; 45 46 rect.left = max_c(r1.left, r2.left); 47 rect.top = max_c(r1.top, r2.top); 48 rect.right = min_c(r1.right, r2.right); 49 rect.bottom = min_c(r1.bottom, r2.bottom); 50 51 return rect; 52 } 53 54 55 // Adds the given offsets to the given rect. 56 static inline void 57 offset_rect(clipping_rect &rect, int32 x, int32 y) 58 { 59 rect.left += x; 60 rect.top += y; 61 rect.right += x; 62 rect.bottom += y; 63 } 64 65 66 static inline void 67 scale_rect(clipping_rect& rect, float x, float y) 68 { 69 rect.left = (int)(rect.left * x); 70 rect.top = (int)(rect.top * y); 71 rect.right = (int)((rect.right + 1) * x) - 1; 72 rect.bottom = (int)((rect.bottom + 1) * y) - 1; 73 } 74 75 76 // Converts the given clipping_rect to a BRect 77 static inline BRect 78 to_BRect(const clipping_rect &rect) 79 { 80 return BRect((float)rect.left, (float)rect.top, 81 (float)rect.right, (float)rect.bottom); 82 } 83 84 85 // Converts the given BRect to a clipping_rect. 86 static inline clipping_rect 87 to_clipping_rect(const BRect &rect) 88 { 89 clipping_rect clipRect; 90 91 // NOTE: test fractional coords BRects -> BRegion on R5 92 // and compare with this implementation... 93 // clipRect.left = (int32)floorf(rect.left); 94 // clipRect.top = (int32)floorf(rect.top); 95 // clipRect.right = (int32)ceilf(rect.right); 96 // clipRect.bottom = (int32)ceilf(rect.bottom); 97 98 // NOTE: clipping_rects are used as "pixel indices" 99 // therefor, it should be ok to convert them like this: 100 clipRect.left = (int32)rect.left; 101 clipRect.top = (int32)rect.top; 102 clipRect.right = (int32)rect.right; 103 clipRect.bottom = (int32)rect.bottom; 104 105 return clipRect; 106 } 107 108 109 // Checks if the given point lies in the given rect's area 110 static inline bool 111 point_in(const clipping_rect &rect, int32 px, int32 py) 112 { 113 if (px >= rect.left && px <= rect.right 114 && py >= rect.top && py <= rect.bottom) 115 return true; 116 return false; 117 } 118 119 120 // Same as above, but it accepts a BPoint parameter 121 static inline bool 122 point_in(const clipping_rect &rect, const BPoint &pt) 123 { 124 if (pt.x >= rect.left && pt.x <= rect.right 125 && pt.y >= rect.top && pt.y <= rect.bottom) 126 return true; 127 return false; 128 } 129 130 131 static inline bool 132 rect_contains(const clipping_rect &rect, const clipping_rect &testRect) 133 { 134 return rect.top <= testRect.top && rect.bottom >= testRect.bottom 135 && rect.left <= testRect.left && rect.right >= testRect.right; 136 } 137 138 139 // Checks if the rect is valid 140 static inline bool 141 valid_rect(const clipping_rect &rect) 142 { 143 if (rect.left <= rect.right && rect.top <= rect.bottom) 144 return true; 145 return false; 146 } 147 148 149 // Checks if the two rects intersect. 150 static inline bool 151 rects_intersect(const clipping_rect &rectA, const clipping_rect &rectB) 152 { 153 // We behave like BRect::Intersects() does: 154 // we return false if one of the two rects is not valid 155 if (!valid_rect(rectA) || !valid_rect(rectB)) 156 return false; 157 158 // TODO: Is there a better algorithm ? 159 // the one we used is faster than 160 // ' return valid_rect(sect_rect(rectA, rectB)); ', though. 161 162 return !(rectA.left > rectB.right || rectA.top > rectB.bottom 163 || rectA.right < rectB.left || rectA.bottom < rectB.top); 164 } 165 166 167 // Returns the width of the given rect. 168 static inline int32 169 rect_width(const clipping_rect &rect) 170 { 171 return rect.right - rect.left; 172 } 173 174 175 // Returns the height of the given rect. 176 static inline int32 177 rect_height(const clipping_rect &rect) 178 { 179 return rect.bottom - rect.top; 180 } 181 182 #endif // __CLIPPING_H 183