summaryrefslogtreecommitdiff
path: root/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx')
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx263
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$".
+//