diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2018-03-12 12:57:28 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2018-03-12 12:57:28 +0000 |
| commit | 1b52ead802e1f3b24c33cadacb8d67dbfb209253 (patch) | |
| tree | 9db02c4ee0d18a9c937f28bb9fa80fc6584cbff2 /src | |
| parent | 371cfd1476de37c4741b6455af77bfc9a07cd9c1 (diff) | |
Android: Reinstated working simple cliping functionality based on an
improved Fl_Rect_Region class instead of Fl_Rect. Commented out
complex clipping.
Android lib and apps now use C++11 because they can (and I like it).
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12741 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.H | 75 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 28 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | 228 |
4 files changed, 187 insertions, 146 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 072fe0604..6534baea4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -296,6 +296,8 @@ elseif (ANDROID) # Android + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set (DRIVER_FILES drivers/Android/Fl_Android_Application.cxx drivers/Android/Fl_Android_System_Driver.cxx diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H index cbcf8eb37..fd23e95d6 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.H +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.H @@ -26,7 +26,6 @@ #define FL_ANDROID_GRAPHICS_DRIVER_H #include <FL/Fl_Graphics_Driver.H> -#include <FL/Fl_Rect.H> #include <limits.h> @@ -34,34 +33,53 @@ class Fl_Android_Window_Driver; /** - * The Fl_Rect_Region is based on Fl_Rect with additional functionality for clipping. + * The Fl_Rect_Region describes a rectangular clipping region. + * + * Contrary to common FLTK convention, rectangles are stored with coordinates + * instead of their width and height to accelerate calculations. The discreet + * constructor however uses the old convention for convenience. */ -class Fl_Rect_Region : public Fl_Rect +class Fl_Rect_Region { public: - enum { - EMPTY = 0, SAME, LESS, MORE + enum Type { + EMPTY = 0, SAME, LESS, MORE, INFINITE }; - /** - * Create an empty clipping region. - */ - Fl_Rect_Region() {} - - /** - * Create a clipping region based on position and size. - * @param x, y position - * @param w, h size - */ - Fl_Rect_Region(int x, int y, int w, int h) : Fl_Rect(x, y, w, h) {} - int intersect_with(Fl_Rect_Region *r); - virtual void print(); - - static int min(int a, int b) { return (a<b) ? a : b; } - static int max(int a, int b) { return (a>b) ? a : b; } -}; + Fl_Rect_Region(); + Fl_Rect_Region(int x, int y, int w, int h); + Fl_Rect_Region(const Fl_Rect_Region&); + Fl_Rect_Region(enum Type what); + virtual ~Fl_Rect_Region() { } + + int x() const { return pLeft; } + int y() const { return pTop; } + int w() const { return pRight - pLeft; } + int h() const { return pBottom - pTop; } + + int left() const { return pLeft; } + int top() const { return pTop; } + int right() const { return pRight; } + int bottom() const { return pBottom; } + bool is_empty() const; + bool is_infinite() const; + void set_empty(); + void set(int x, int y, int w, int h); + void set(const Fl_Rect_Region &r); + int intersect_with(const Fl_Rect_Region &r); + + virtual void print(const char*) const; + +protected: + int pLeft, pTop, pRight, pBottom; + +private: + Fl_Rect_Region& operator = (const Fl_Rect_Region& other); +}; + +#if 0 /** * The Fl_Complex_Region represents a clipping region of any shape. * @@ -85,9 +103,9 @@ public: Fl_Complex_Region(int x, int y, int w, int h) : Fl_Rect_Region(x, y, w, h), pSubregion(0L), pNext(0L) { } ~Fl_Complex_Region(); virtual void set(int x, int y, int w, int h); - virtual void set(Fl_Rect *rect); - void subtract(Fl_Rect*); - void intersect(Fl_Rect*); + virtual void set(Fl_Rect_Region*); + void subtract(Fl_Rect_Region*); + void intersect(Fl_Rect_Region*); void clone(Fl_Complex_Region*); char is_simple() { return pSubregion==0; } char is_complex() { return pSubregion!=0; } @@ -97,6 +115,7 @@ protected: Fl_Complex_Region *pSubregion; Fl_Complex_Region *pNext; }; +#endif /** @@ -244,10 +263,8 @@ protected: int32_t pStride; uint16_t *pBits; - // Fl_Rect_Region pScreenRegion; - Fl_Rect_Region *pWindowRegion; - Fl_Complex_Region *pDesktopRegion; - Fl_Complex_Region *pClippingRegion; + Fl_Rect_Region pWindowRegion; + Fl_Rect_Region pClippingRegion; }; diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx index dfd88e85a..817b5c0d1 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx @@ -37,10 +37,7 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() Fl_Android_Graphics_Driver::Fl_Android_Graphics_Driver() : - pStride(0), pBits(0), - pWindowRegion(new Fl_Rect_Region()), - pDesktopRegion(new Fl_Complex_Region()), - pClippingRegion(new Fl_Complex_Region()) + pStride(0), pBits(0) { } @@ -52,8 +49,6 @@ Fl_Android_Graphics_Driver::~Fl_Android_Graphics_Driver() void Fl_Android_Graphics_Driver::make_current(Fl_Window *win) { - Fl_Android_Application::log_i("------------ make current \"%s\"", win->label()); - // The Stride is the offset between lines in the graphics buffer pStride = Fl_Android_Application::graphics_buffer().stride; // Bits is the memory address of the top left corner of the window @@ -62,13 +57,10 @@ void Fl_Android_Graphics_Driver::make_current(Fl_Window *win) // TODO: set the clipping area // set the clipping area to the physical screen size in window coordinates - pWindowRegion->set(-win->x(), -win->y(), 600, 800); - Fl_Rect_Region wr(0, 0, win->w(), win->h()); - pWindowRegion->intersect_with(&wr); - pWindowRegion->print(); - - pDesktopRegion->set(pWindowRegion); + pWindowRegion.set(-win->x(), -win->y(), 600, 800); + pWindowRegion.intersect_with(Fl_Rect_Region(0, 0, win->w(), win->h())); +#if 0 // remove all window rectangles that are positioned on top of this window // TODO: this region is expensive to calculate. Cache it for each window and recalculate when windows move, show, hide, or change order Fl_Window *wTop = Fl::first_window(); @@ -78,11 +70,9 @@ void Fl_Android_Graphics_Driver::make_current(Fl_Window *win) pDesktopRegion->subtract(&r); wTop = Fl::next_window(wTop); } +#endif - // TODO: we can optimize this by using some "copy on write" system - pClippingRegion->clone(pDesktopRegion); - pClippingRegion->print(); - Fl_Android_Application::log_i("------------ make current done"); + pClippingRegion.set(pWindowRegion); } @@ -106,7 +96,7 @@ static uint16_t make565(Fl_Color crgba) void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) { Fl_Rect_Region r(x, y, w, h); - if (r.intersect_with((Fl_Rect_Region*)pClippingRegion)) { + if (r.intersect_with(pClippingRegion)) { rectf_unclipped(r.x(), r.y(), r.w(), r.h()); } // TODO: create a complex region by intersecting r with the pClippingRegion @@ -135,8 +125,8 @@ void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float */ } -void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h) { - Fl_Android_Application::log_w("rectf unclipped %g %g %g %g", x, y, w, h); +void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h) +{ if (w<=0 || h<=0) return; // TODO: clip the rectangle to the window outline diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx index 30131cf05..e3ffafc54 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx @@ -23,41 +23,132 @@ #include <FL/platform.H> -// return 0 for empty, 1 for same, 2 if intersecting -int Fl_Rect_Region::intersect_with(Fl_Rect_Region *a) +/** + * Create an empty clipping region. + */ +Fl_Rect_Region::Fl_Rect_Region() : + pLeft(0), pTop(0), pRight(0), pBottom(0) +{ +} + +/** + * Create a clipping region based on position and size. + * @param x, y position + * @param w, h size + */ +Fl_Rect_Region::Fl_Rect_Region(int x, int y, int w, int h) : + pLeft(x), pTop(y), pRight(x+w), pBottom(y+h) +{ +} + +/** + * Clone a clipping rectangle. + */ +Fl_Rect_Region::Fl_Rect_Region(const Fl_Rect_Region &r) : + pLeft(r.pLeft), pTop(r.pTop), + pRight(r.pRight), pBottom(r.pBottom) +{ +} + +/** + * Clone a clipping rectangle. + * The pointer can be NULL if an empty rectangle is needed. + */ +Fl_Rect_Region::Fl_Rect_Region(enum Type what) +{ + if (what==INFINITE) { + pLeft = pTop = INT_MIN; + pRight = pBottom = INT_MAX; + } else { + pLeft = pTop = pRight = pBottom = 0; + } +} + +/** + * If the rectangle has no width or height, it's considered empty. + * @return true, if everything will be clipped and there is nothing to draw + */ +bool Fl_Rect_Region::is_empty() const +{ + return (pRight<=pLeft || pBottom<=pTop); +} + +/** + * Return true, if the rectangle is of unlimited size and nothing should be clipped. + * @return treu, if there is no clipping + */ +bool Fl_Rect_Region::is_infinite() const +{ + return (pLeft==INT_MIN); +} + + +void Fl_Rect_Region::set_empty() +{ + pLeft = pTop = pRight = pBottom = 0; +} + + +void Fl_Rect_Region::set(int x, int y, int w, int h) +{ + pLeft = x; + pTop = y; + pRight = x+w; + pBottom = y+h; +} + + +void Fl_Rect_Region::set(const Fl_Rect_Region &r) +{ + pLeft = r.pLeft; + pTop = r.pTop; + pRight = r.pRight; + pBottom = r.pBottom; +} + + +int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r) { if (is_empty()) { return EMPTY; } - if (a->is_empty()) { - clear(); + if (r.is_empty()) { + set_empty(); return EMPTY; } - int lx = max(x(), a->x()); - int ly = max(y(), a->y()); - int lr = min(r(), a->r()); - int lb = min(b(), a->b()); - int lw = lr-lx; - int lh = lb-ly; - if (equals(lx, ly, lw, lh)) { - return SAME; + bool same = true; + if ( pLeft != r.pLeft ) { + same = false; + if ( r.pLeft > pLeft ) pLeft = r.pLeft; } - set(lx, ly, lw, lh); - if ( (w()<=0) || (h()<=0) ) { - clear(); - return EMPTY; + if ( pTop != r.pTop ) { + same = false; + if ( r.pTop > pTop ) pTop = r.pTop; + } + if ( pRight != r.pRight ) { + same = false; + if ( r.pRight < pRight ) pRight = r.pRight; + } + if ( pBottom != r.pBottom ) { + same = false; + if ( r.pBottom < pBottom ) pBottom = r.pBottom; } + if (same) + return SAME; + if (is_empty()) + return EMPTY; return LESS; } -void Fl_Rect_Region::print() +void Fl_Rect_Region::print(const char *label) const { - Fl_Android_Application::log_i("-------- begin rect"); + Fl_Android_Application::log_i("---> Fl_Rect_Region: %s", label); Fl_Android_Application::log_i("Rect %d %d %d %d", x(), y(), w(), h()); } +#if 0 Fl_Complex_Region::~Fl_Complex_Region() { @@ -151,6 +242,7 @@ void Fl_Complex_Region::print() print_data(0); } +#endif @@ -158,18 +250,12 @@ void Fl_Android_Graphics_Driver::restore_clip() { fl_clip_state_number++; - // TODO: we can optimize this by using some "copy on write" system - Fl_Android_Application::log_i("------------ restore_clip"); - pDesktopRegion->print(); - //pClippingRegion->set(pWindowRegion); - pClippingRegion->clone(pDesktopRegion); + pClippingRegion.set(pWindowRegion); Fl_Region b = rstack[rstackptr]; if (b) { - pClippingRegion->intersect_with(b); - pClippingRegion->print(); + pClippingRegion.intersect_with(*b); } - Fl_Android_Application::log_i("------------ restore_clip done"); } @@ -193,10 +279,10 @@ 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_Rect_Region(x,y,w,h); + r = new Fl_Rect_Region(x, y, w, h); Fl_Region current = rstack[rstackptr]; if (current) { - r->intersect_with(current); + r->intersect_with(*current); } } else { // make empty clip region: r = new Fl_Rect_Region(); @@ -239,19 +325,18 @@ void Fl_Android_Graphics_Driver::pop_clip() 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) { + if (r) { + Fl_Rect_Region a(x, y, w, h); + int ret = a.intersect_with(*r); + X = a.x(); + Y = a.y(); + W = a.w(); + H = a.h(); + return (ret!=Fl_Rect_Region::SAME); + } else { X = x; Y = y; W = w; H = h; return 0; } - - Fl_Rect_Region 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); } /* @@ -264,72 +349,19 @@ int Fl_Android_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int 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_Rect_Region 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; +int Fl_Android_Graphics_Driver::not_clipped(int x, int y, int w, int h) +{ + if (w <= 0 || 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; + if (r) { + Fl_Rect_Region a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting + return a.intersect_with(*r); } else { - rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; + return 1; } - return RectInRegion(r,&rect); } -#endif - - // // End of "$Id$". // |
