diff options
Diffstat (limited to 'src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx')
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx new file mode 100644 index 000000000..107a6e708 --- /dev/null +++ b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx @@ -0,0 +1,263 @@ +// +// "$Id$" +// +// Clipping region routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2018 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + + +#include "../../config_lib.h" +#include "Fl_Android_Graphics_Driver.H" +#include "Fl_Android_Application.H" +#include <FL/platform.H> + + +Fl_Clip_Rect Fl_Android_Graphics_Driver::pClipRect; + + +// return 0 for empty, 1 for same, 2 if intersecting +int Fl_Clip_Rect::intersect_with(Fl_Clip_Rect *a) +{ + if (pRect.is_empty()) { + return 0; + } + if (a->pRect.is_empty()) { + pRect.clear(); + return 0; + } + int x = max(pRect.x(), a->pRect.x()); + int y = max(pRect.y(), a->pRect.y()); + int r = min(pRect.r(), a->pRect.r()); + int b = min(pRect.b(), a->pRect.b()); + int w = r-x; + int h = b-y; + if (pRect.equals(x, y, w, h)) { + return 1; + } + pRect.set(x, y, w, h); + if ( (pRect.w()<=0) || (pRect.h()<=0) ) { + pRect.clear(); + return 0; + } + return 2; +} + + + +void Fl_Android_Graphics_Driver::clip_region(Fl_Region r) +{ + Fl_Region oldr = rstack[rstackptr]; + if (oldr) + ::free(oldr); + rstack[rstackptr] = r; + restore_clip(); +} + +Fl_Region Fl_Android_Graphics_Driver::clip_region() +{ + return rstack[rstackptr]; +} + +void Fl_Android_Graphics_Driver::restore_clip() +{ + fl_clip_state_number++; + Fl_Window *win = Fl_Window::current(); + Fl_Clip_Rect a(0, 0, win->w(), win->h()); + + Fl_Region b = rstack[rstackptr]; + if (b) { + // FIXME: scaling! + a.intersect_with(b); + } + pClipRect = a; +} + +void Fl_Android_Graphics_Driver::push_clip(int x, int y, int w, int h) +{ + Fl_Region r; + if (w > 0 && h > 0) { + r = new Fl_Clip_Rect(x,y,w,h); + Fl_Region current = rstack[rstackptr]; + if (current) { + r->intersect_with(current); + } + } else { // make empty clip region: + r = new Fl_Clip_Rect(); + } + if (rstackptr < region_stack_max) rstack[++rstackptr] = r; + else Fl::warning("Fl_Android_Graphics_Driver::push_clip: clip stack overflow!\n"); + restore_clip(); +} + +void Fl_Android_Graphics_Driver::push_no_clip() +{ + if (rstackptr < region_stack_max) rstack[++rstackptr] = 0; + else Fl::warning("Fl_Android_Graphics_Driver::push_no_clip: clip stack overflow!\n"); + restore_clip(); +} + +void Fl_Android_Graphics_Driver::pop_clip() +{ + if (rstackptr > 0) { + Fl_Region oldr = rstack[rstackptr--]; + if (oldr) + ::free(oldr); + } else Fl::warning("Fl_Android_Graphics_Driver::pop_clip: clip stack underflow!\n"); + restore_clip(); +} + +/* + Intersects the rectangle with the current clip region and returns the + bounding box of the result. + + Returns non-zero if the resulting rectangle is different to the original. + This can be used to limit the necessary drawing to a rectangle. + \p W and \p H are set to zero if the rectangle is completely outside the region. + \param[in] x,y,w,h position and size of rectangle + \param[out] X,Y,W,H position and size of resulting bounding box. + \returns Non-zero if the resulting rectangle is different to the original. + */ +int Fl_Android_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) +{ + Fl_Region r = rstack[rstackptr]; + if (!r) { + X = x; Y = y; W = w; H = h; + return 0; + } + + Fl_Clip_Rect a(x, y, w, h); + int ret = a.intersect_with(r); // return 0 for empty, 1 for same, 2 if intersecting + X = a.x(); + Y = a.y(); + W = a.w(); + H = a.h(); + + return (ret!=1); +} + +/* + Does the rectangle intersect the current clip region? + \param[in] x,y,w,h position and size of rectangle + \returns non-zero if any of the rectangle intersects the current clip + region. If this returns 0 you don't have to draw the object. + + \note + Under X this returns 2 if the rectangle is partially clipped, + and 1 if it is entirely inside the clip region. + */ +int Fl_Android_Graphics_Driver::not_clipped(int x, int y, int w, int h) { + if (x+w <= 0 || y+h <= 0) return 0; + Fl_Region r = rstack[rstackptr]; + if (!r) return 1; + + Fl_Clip_Rect a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting + return a.intersect_with(r); +} + +#if 0 + +// --- clipping + +int Fl_GDI_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ + X = x; Y = y; W = w; H = h; + Fl_Region r = rstack[rstackptr]; + if (!r) return 0; + // The win32 API makes no distinction between partial and complete + // intersection, so we have to check for partial intersection ourselves. + // However, given that the regions may be composite, we have to do + // some voodoo stuff... + Fl_Region rr = XRectangleRegion(x,y,w,h); + Fl_Region temp = CreateRectRgn(0,0,0,0); + int ret; + if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint + W = H = 0; + ret = 2; + } else if (EqualRgn(temp, rr)) { // complete + ret = 0; + } else { // partial intersection + RECT rect; + GetRgnBox(temp, &rect); + if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if print context, convert coords from device to logical + POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} }; + DPtoLP(gc_, pt, 2); + X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y; + } + else { + X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; + } + ret = 1; + } + DeleteObject(temp); + DeleteObject(rr); + return ret; +} + +int Fl_GDI_Graphics_Driver::not_clipped(int x, int y, int w, int h) { + if (x+w <= 0 || y+h <= 0) return 0; + Fl_Region r = rstack[rstackptr]; + if (!r) return 1; + RECT rect; + if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device + POINT pt[2] = { {x, y}, {x + w, y + h} }; + LPtoDP(gc_, pt, 2); + rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y; + } else { + rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; + } + return RectInRegion(r,&rect); +} + + +#endif + + +/* + - Pushes an empty clip region onto the stack so nothing will be clipped. +virtual void push_no_clip() {} + - Intersects the current clip region with a rectangle and pushes this new region onto the stack. +virtual void push_clip(int x, int y, int w, int h) {} + - Restores the previous clip region. +virtual void pop_clip() {} + - Does the rectangle intersect the current clip region? 0=no, 1=all, 2=partially +virtual int not_clipped(int x, int y, int w, int h) {return 1;} + - Intersects the rectangle with the current clip region and returns the bounding box of the result. + Returns 1 if rect changed, W and H are 0 if there is no rect +virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) {return 0;} + - Undoes any clobbering of clip done by your program +virtual void restore_clip(); + +virtual Fl_Region clip_region(); // has default implementation +virtual void clip_region(Fl_Region r); // has default implementation + + fl_push_clip(x,y,w,h) -> driver + fl_pop_clip() -> driver + fl_push_no_clip() -> driver + fl_not_clipped(int x, int y, int w, int h) -> driver + fl_clip_box(int x , int y, int w, int h, int& X, int& Y, int& W, int& H) -> driver + fl_restore_clip() -> driver + + fl_clip_region(Fl_Region r) -> driver + fl_clip_region() -> driver + +virtual Fl_Region scale_clip(float f) { return 0; } +void unscale_clip(Fl_Region r); + + + */ + + + +// +// End of "$Id$". +// |
