2020-03-01 04:20:05 +03:00
|
|
|
/*
|
|
|
|
* Copyright 2001-2004, Haiku, Inc. All rights reserved.
|
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Stefano Ceccherini, burton666@libero.it
|
|
|
|
*/
|
2003-07-03 10:29:06 +04:00
|
|
|
#ifndef __CLIPPING_H
|
|
|
|
#define __CLIPPING_H
|
2003-06-26 14:09:01 +04:00
|
|
|
|
2003-07-22 16:49:49 +04:00
|
|
|
#include <Region.h>
|
|
|
|
#include <SupportDefs.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* Some methods to manipulate clipping_rects.
|
|
|
|
basically you can do almost everything you do with
|
|
|
|
BRects, just that clipping_rects can only have integer
|
|
|
|
coordinates (a thing that makes these perfect for drawing
|
|
|
|
calculations).
|
|
|
|
*/
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
|
|
|
|
// Returns the union of the given rects.
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline clipping_rect
|
2004-08-24 10:31:36 +04:00
|
|
|
union_rect(const clipping_rect &r1, const clipping_rect &r2)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
|
|
|
clipping_rect rect;
|
2020-03-01 04:20:05 +03:00
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
rect.left = min_c(r1.left, r2.left);
|
|
|
|
rect.top = min_c(r1.top, r2.top);
|
|
|
|
rect.right = max_c(r1.right, r2.right);
|
|
|
|
rect.bottom = max_c(r1.bottom, r2.bottom);
|
2020-03-01 04:20:05 +03:00
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Returns the intersection of the given rects.
|
|
|
|
// The caller should check if the returned rect is valid. If it isn't valid,
|
|
|
|
// then the two rectangles don't intersect.
|
|
|
|
static inline clipping_rect
|
2004-08-24 10:31:36 +04:00
|
|
|
sect_rect(const clipping_rect &r1, const clipping_rect &r2)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
|
|
|
clipping_rect rect;
|
2020-03-01 04:20:05 +03:00
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
rect.left = max_c(r1.left, r2.left);
|
|
|
|
rect.top = max_c(r1.top, r2.top);
|
|
|
|
rect.right = min_c(r1.right, r2.right);
|
|
|
|
rect.bottom = min_c(r1.bottom, r2.bottom);
|
2020-03-01 04:20:05 +03:00
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
|
2003-10-24 14:50:41 +04:00
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Adds the given offsets to the given rect.
|
2003-09-05 14:16:34 +04:00
|
|
|
static inline void
|
|
|
|
offset_rect(clipping_rect &rect, int32 x, int32 y)
|
|
|
|
{
|
|
|
|
rect.left += x;
|
|
|
|
rect.top += y;
|
|
|
|
rect.right += x;
|
|
|
|
rect.bottom += y;
|
|
|
|
}
|
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
|
2014-06-19 20:03:17 +04:00
|
|
|
static inline void
|
|
|
|
scale_rect(clipping_rect& rect, float x, float y)
|
|
|
|
{
|
|
|
|
rect.left = (int)(rect.left * x);
|
|
|
|
rect.top = (int)(rect.top * y);
|
2014-06-19 20:31:34 +04:00
|
|
|
rect.right = (int)((rect.right + 1) * x) - 1;
|
|
|
|
rect.bottom = (int)((rect.bottom + 1) * y) - 1;
|
2014-06-19 20:03:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Converts the given clipping_rect to a BRect
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline BRect
|
2004-08-24 10:31:36 +04:00
|
|
|
to_BRect(const clipping_rect &rect)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
2006-03-20 01:26:17 +03:00
|
|
|
return BRect((float)rect.left, (float)rect.top,
|
|
|
|
(float)rect.right, (float)rect.bottom);
|
2003-06-26 14:09:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Converts the given BRect to a clipping_rect.
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline clipping_rect
|
2004-08-24 10:31:36 +04:00
|
|
|
to_clipping_rect(const BRect &rect)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
|
|
|
clipping_rect clipRect;
|
2006-03-20 01:26:17 +03:00
|
|
|
|
|
|
|
// NOTE: test fractional coords BRects -> BRegion on R5
|
|
|
|
// and compare with this implementation...
|
|
|
|
// clipRect.left = (int32)floorf(rect.left);
|
|
|
|
// clipRect.top = (int32)floorf(rect.top);
|
|
|
|
// clipRect.right = (int32)ceilf(rect.right);
|
|
|
|
// clipRect.bottom = (int32)ceilf(rect.bottom);
|
|
|
|
|
|
|
|
// NOTE: clipping_rects are used as "pixel indices"
|
|
|
|
// therefor, it should be ok to convert them like this:
|
|
|
|
clipRect.left = (int32)rect.left;
|
|
|
|
clipRect.top = (int32)rect.top;
|
|
|
|
clipRect.right = (int32)rect.right;
|
|
|
|
clipRect.bottom = (int32)rect.bottom;
|
2020-03-01 04:20:05 +03:00
|
|
|
|
2003-06-26 14:09:01 +04:00
|
|
|
return clipRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Checks if the given point lies in the given rect's area
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline bool
|
2004-08-24 10:31:36 +04:00
|
|
|
point_in(const clipping_rect &rect, int32 px, int32 py)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
2020-03-01 04:20:05 +03:00
|
|
|
if (px >= rect.left && px <= rect.right
|
2003-06-26 14:09:01 +04:00
|
|
|
&& py >= rect.top && py <= rect.bottom)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Same as above, but it accepts a BPoint parameter
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline bool
|
2004-08-24 10:31:36 +04:00
|
|
|
point_in(const clipping_rect &rect, const BPoint &pt)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
2020-03-01 04:20:05 +03:00
|
|
|
if (pt.x >= rect.left && pt.x <= rect.right
|
2003-06-26 14:09:01 +04:00
|
|
|
&& pt.y >= rect.top && pt.y <= rect.bottom)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-03 17:12:10 +03:00
|
|
|
static inline bool
|
|
|
|
rect_contains(const clipping_rect &rect, const clipping_rect &testRect)
|
|
|
|
{
|
|
|
|
return rect.top <= testRect.top && rect.bottom >= testRect.bottom
|
|
|
|
&& rect.left <= testRect.left && rect.right >= testRect.right;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Checks if the rect is valid
|
2003-06-26 14:09:01 +04:00
|
|
|
static inline bool
|
2004-08-24 10:31:36 +04:00
|
|
|
valid_rect(const clipping_rect &rect)
|
2003-06-26 14:09:01 +04:00
|
|
|
{
|
2003-07-03 10:29:06 +04:00
|
|
|
if (rect.left <= rect.right && rect.top <= rect.bottom)
|
2003-06-26 14:09:01 +04:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2003-07-22 16:49:49 +04:00
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Checks if the two rects intersect.
|
2003-07-22 16:49:49 +04:00
|
|
|
static inline bool
|
2004-08-24 10:31:36 +04:00
|
|
|
rects_intersect(const clipping_rect &rectA, const clipping_rect &rectB)
|
2003-07-22 16:49:49 +04:00
|
|
|
{
|
2004-08-25 11:36:57 +04:00
|
|
|
// We behave like BRect::Intersects() does:
|
|
|
|
// we return false if one of the two rects is not valid
|
2004-07-01 10:16:00 +04:00
|
|
|
if (!valid_rect(rectA) || !valid_rect(rectB))
|
|
|
|
return false;
|
|
|
|
|
2020-03-01 04:20:05 +03:00
|
|
|
// TODO: Is there a better algorithm ?
|
2004-07-01 10:16:00 +04:00
|
|
|
// the one we used is faster than
|
|
|
|
// ' return valid_rect(sect_rect(rectA, rectB)); ', though.
|
|
|
|
|
2003-10-24 14:50:41 +04:00
|
|
|
return !(rectA.left > rectB.right || rectA.top > rectB.bottom
|
|
|
|
|| rectA.right < rectB.left || rectA.bottom < rectB.top);
|
2003-07-22 16:49:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Returns the width of the given rect.
|
2003-07-22 16:49:49 +04:00
|
|
|
static inline int32
|
2004-08-24 10:31:36 +04:00
|
|
|
rect_width(const clipping_rect &rect)
|
2003-07-22 16:49:49 +04:00
|
|
|
{
|
|
|
|
return rect.right - rect.left;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-07-01 10:16:00 +04:00
|
|
|
// Returns the height of the given rect.
|
2003-07-22 16:49:49 +04:00
|
|
|
static inline int32
|
2004-08-24 10:31:36 +04:00
|
|
|
rect_height(const clipping_rect &rect)
|
2003-07-22 16:49:49 +04:00
|
|
|
{
|
|
|
|
return rect.bottom - rect.top;
|
|
|
|
}
|
|
|
|
|
2003-07-03 10:29:06 +04:00
|
|
|
#endif // __CLIPPING_H
|