From bdb63b3f07cba389ce3fb584218389349561321c Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Fri, 16 Mar 2018 12:48:29 +0000 Subject: Android: clipping regions code grew so big, they moved into their own header and source file. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12758 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- src/CMakeLists.txt | 3 +- src/drivers/Android/Fl_Android_Graphics_Clipping.H | 170 +++++ .../Android/Fl_Android_Graphics_Clipping.cxx | 715 +++++++++++++++++++++ src/drivers/Android/Fl_Android_Graphics_Driver.H | 133 +--- .../Android/Fl_Android_Graphics_Driver_region.cxx | 715 --------------------- 5 files changed, 888 insertions(+), 848 deletions(-) create mode 100644 src/drivers/Android/Fl_Android_Graphics_Clipping.H create mode 100644 src/drivers/Android/Fl_Android_Graphics_Clipping.cxx delete mode 100644 src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6534baea4..619f5bb45 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -305,7 +305,7 @@ elseif (ANDROID) drivers/Android/Fl_Android_Window_Driver.cxx drivers/Android/Fl_Android_Image_Surface_Driver.cxx drivers/Android/Fl_Android_Graphics_Driver.cxx - drivers/Android/Fl_Android_Graphics_Driver_region.cxx + drivers/Android/Fl_Android_Graphics_Clipping.cxx ) set (DRIVER_HEADER_FILES drivers/Android/Fl_Android_Application.H @@ -313,6 +313,7 @@ elseif (ANDROID) drivers/Android/Fl_Android_Screen_Driver.H drivers/Android/Fl_Android_Window_Driver.H drivers/Android/Fl_Android_Graphics_Driver.H + drivers/Android/Fl_Android_Graphics_Clipping.H drivers/Android/Fl_Font.H ) diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.H b/src/drivers/Android/Fl_Android_Graphics_Clipping.H new file mode 100644 index 000000000..803548bab --- /dev/null +++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.H @@ -0,0 +1,170 @@ +// +// "$Id$" +// +// Graphics regions and clipping for the Fast Light Tool Kit (FLTK). +// +// Copyright 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 +// + +/** + \file Fl_Android_Graphics_Clipping.H + \brief Graphics regions and clipping for the Fast Light Tool Kit (FLTK). + */ + +#ifndef FL_ANDROID_GRAPHICS_CLIPPING_H +#define FL_ANDROID_GRAPHICS_CLIPPING_H + +#include +#include + + +class Fl_Android_Window_Driver; + + +/** + * 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: + enum Type { + EMPTY = 0, SAME, LESS, MORE, INFINITE + }; + + 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_ltrb(int l, int t, int r, int b); + virtual void set(const Fl_Rect_Region &r); + virtual 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); +}; + + +/** + * The Fl_Complex_Region represents a clipping region of any shape. + * + * This class is organized in a tree-like structure. If the region is + * rectangular, is_simple() returns 1 and the rectangle can be used just + * as in Fl_Rect_Region. + * + * If a more complex representation is needed, the first list of + * subregions is organizen in horizontal strips. The root region rect + * will contain the outline of all subregions, and the subregions + * will either be simple rectangles, or they will contain a second + * level of subregions, subdividing the horizontal region into vertical + * columns. + * + * When reading, the tree can be easily walked using recursion. + */ +class Fl_Complex_Region : public Fl_Rect_Region +{ + class Iterator { + public: + Iterator(Fl_Complex_Region *r); + bool operator!= (const Iterator& other) const; + const Iterator& operator++ (); + Fl_Complex_Region *operator* () const; + Fl_Complex_Region *pRegion; + }; + + class Overlapping { + class OverlappingIterator { + public: + OverlappingIterator(Overlapping *ov); + bool operator!= (const OverlappingIterator& other) const; + const OverlappingIterator& operator++ (); + Overlapping *operator* () const; + Overlapping *pOv; + }; + public: + Overlapping(Fl_Complex_Region *rgn, const Fl_Rect_Region &rect); + OverlappingIterator begin(); + OverlappingIterator end(); + Fl_Rect_Region &clipped_rect(); + bool intersects(); + bool find_intersecting(); + bool find_next(); + Fl_Complex_Region *pRegion; + Fl_Rect_Region pOriginalRect; + Fl_Rect_Region pClippedRect; + }; + +public: + Fl_Complex_Region(); + Fl_Complex_Region(const Fl_Rect_Region&); + virtual ~Fl_Complex_Region() override; + + virtual void set(const Fl_Rect_Region &r) override; + void set(const Fl_Complex_Region &r); + Fl_Complex_Region *subregion() const { return pSubregion; } + Fl_Complex_Region *next() const { return pNext; } + Fl_Complex_Region *parent() const { return pParent; } + char is_simple() const { return pSubregion==0; } + char is_complex() const { return pSubregion!=0; } + + virtual int intersect_with(const Fl_Rect_Region &r) override; + int subtract(const Fl_Rect_Region &r); + + virtual void print(const char*) const override; + + Iterator begin(); + Iterator end(); + + Overlapping overlapping(const Fl_Rect_Region &r); + +protected: + void print_data(int indent) const; + int subtract_smaller_region(const Fl_Rect_Region &r); + Fl_Complex_Region *add_subregion(); + + Fl_Complex_Region *pSubregion = 0L; + Fl_Complex_Region *pParent = 0L; + Fl_Complex_Region *pNext = 0L; +}; + + +#endif // FL_ANDROID_GRAPHICS_CLIPPING_H + +// +// End of "$Id$". +// diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx new file mode 100644 index 000000000..000ef929f --- /dev/null +++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx @@ -0,0 +1,715 @@ +// +// "$Id$" +// +// Clipping region routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 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 + + +/** + * 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); +} + +/** + * Set an empty clipping rect. + */ +void Fl_Rect_Region::set_empty() +{ + pLeft = pTop = pRight = pBottom = 0; +} + +/** + * Set a clipping rect using position and size + * @param x, y position + * @param w, h size + */ +void Fl_Rect_Region::set(int x, int y, int w, int h) +{ + pLeft = x; + pTop = y; + pRight = x+w; + pBottom = y+h; +} + +/** + * Set a rectangle using the coordinates of two points, top left and bottom right. + * @param l, t left and top coordinate + * @param r, b right and bottom coordinate + */ +void Fl_Rect_Region::set_ltrb(int l, int t, int r, int b) +{ + pLeft = l; + pTop = t; + pRight = r; + pBottom = b; +} + +/** + * Copy the corrdinates from another rect. + * @param r source rectangle + */ +void Fl_Rect_Region::set(const Fl_Rect_Region &r) +{ + pLeft = r.pLeft; + pTop = r.pTop; + pRight = r.pRight; + pBottom = r.pBottom; +} + +/** + * Set this rect to be the intersecting area between the original rect and another rect. + * @param r another rectangular region + * @return EMPTY, if rectangles are not intersecting, SAME if this and rect are + * equal, LESS if the new rect is smaller than the original rect + */ +int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r) +{ + if (is_empty()) { + return EMPTY; + } + if (r.is_empty()) { + set_empty(); + return EMPTY; + } + bool same = true; + if ( pLeft != r.pLeft ) { + same = false; + if ( r.pLeft > pLeft ) pLeft = r.pLeft; + } + 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; +} + +/** + * Print the coordinates of the rect to the log. + * @param label some text that is logged with this message. + */ +void Fl_Rect_Region::print(const char *label) const +{ + Fl_Android_Application::log_i("---> Fl_Rect_Region: %s", label); + Fl_Android_Application::log_i("Rect l:%d t:%d r:%d b:%d", left(), top(), right(), bottom()); +} + +// ============================================================================= + +/** + * Create an empty complex region. + */ +Fl_Complex_Region::Fl_Complex_Region() : + Fl_Rect_Region() +{ +} + +/** + * Create a complex region with the same bounds as the give rect. + * @param r region size + */ +Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) : + Fl_Rect_Region(r) +{ +} + +/** + * Delete this region, all subregions recursively, and all following regions. + */ +Fl_Complex_Region::~Fl_Complex_Region() +{ + delete pSubregion; // recursively delete all subregions + delete pNext; // recursively delete all following regions +} + +/** + * Print the entire content of this region recursively. + */ +void Fl_Complex_Region::print(const char *label) const +{ + Fl_Android_Application::log_i("---> Fl_Complex_Region: %s", label); + print_data(0); +} + +/* + * Print the rectangular data only. + */ +void Fl_Complex_Region::print_data(int indent) const +{ + static const char *space = " "; + if (pSubregion) { + Fl_Android_Application::log_i("%sBBox l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom()); + pSubregion->print_data(indent+1); + } else { + Fl_Android_Application::log_i("%sRect l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom()); + } + if (pNext) { + pNext->print_data(indent); + } +} + +/** + * Replace this region with a rectangle. + * @param r the source rectangle + */ +void Fl_Complex_Region::set(const Fl_Rect_Region &r) +{ + delete pSubregion; pSubregion = 0; + Fl_Rect_Region::set(r); +} + +/** + * Replace this region with a copy of another region. + * This operation can be expensive for very complex regions. + * @param r the source region + */ +void Fl_Complex_Region::set(const Fl_Complex_Region &r) +{ + // outline: + // clear this region and copy the coordinates from r + delete pSubregion; pSubregion = 0; + Fl_Rect_Region::set((const Fl_Rect_Region&)r); + if (r.pSubregion) { + pSubregion = new Fl_Complex_Region(); + pSubregion->set(*r.subregion()); + } + if (r.pNext) { + pNext = new Fl_Complex_Region(); + pNext->set(*r.next()); + } +} + +/** + * Set this region to the intersection of the original region and some rect. + * @param r intersect with this rectangle + * @return EMPTY, SAME, LESS + */ +int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r) +{ + delete pSubregion; pSubregion = 0; + // FIXME: handle complex regions! + int ret = Fl_Rect_Region::intersect_with(r); + return ret; +} + +/** + * Subtract a rectangular region from this region. + * @param r the rect that we want removed + * @return currently 0, but could return something meaningful + */ +int Fl_Complex_Region::subtract(const Fl_Rect_Region &r) +{ + if (pSubregion) { + pSubregion->subtract(r); + } else { + // Check if we overlap at all + Fl_Rect_Region s(r); + int intersects = s.intersect_with(*this); + switch (intersects) { + case EMPTY: + // nothing to do + break; + case SAME: + set_empty(); // FIXME: delete this Rect! + break; + case LESS: + // split this rect into 1, 2, 3, or 4 new ones + subtract_smaller_region(s); + break; + default: + Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__); + break; + } + if (pNext) { + pNext->subtract(r); + } + } + return 0; +} + +/** + * Subtract a rect from another rect, potentially creating four new rectangles. + * This assumes that the calling region is NOT complex. + * @param r subtract the area of this rectangle. + * @return currently 0, but this may change + */ +int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r) +{ + // subtract a smaller rect from a larger rect and create subrects as needed + // FIXME: make sure that the bbox of the parent region is shrunk to the size of all children + // if there is only one single coordinte different, we can reuse this container + if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) { + // this should not happen + set_empty(); + } else if (left()!=r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) { + pRight = r.left(); + } else if (left()==r.left() && top()!=r.top() && right()==r.right() && bottom()==r.bottom()) { + pBottom = r.top(); + } else if (left()==r.left() && top()==r.top() && right()!=r.right() && bottom()==r.bottom()) { + pLeft = r.right(); + } else if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()!=r.bottom()) { + pTop = r.bottom(); + } else { + // create multiple regions + if (pTop!=r.top()) { + Fl_Complex_Region *s = add_subregion(); + s->set_ltrb(pLeft, pTop, pRight, r.top()); + } + if (pBottom!=r.bottom()) { + Fl_Complex_Region *s = add_subregion(); + s->set_ltrb(pLeft, r.bottom(), pRight, pBottom); + } + if (pLeft!=r.left()) { + Fl_Complex_Region *s = add_subregion(); + s->set_ltrb(pLeft, r.top(), r.left(), r.bottom()); + } + if (pRight!=r.right()) { + Fl_Complex_Region *s = add_subregion(); + s->set_ltrb(r.right(), r.top(), pRight, r.bottom()); + } + } + return 0; +} + +/** + * Add an empty subregion to the current region. + * @return a pointer to the newly created region. + */ +Fl_Complex_Region *Fl_Complex_Region::add_subregion() +{ + Fl_Complex_Region *r = new Fl_Complex_Region(); + r->pParent = this; + r->pNext = pSubregion; + pSubregion = r; + return r; +} + + +// ----------------------------------------------------------------------------- + +/** + * Returns an interator object for loops that traverse the entire region tree. + * C++11 interface to range-based loops. + * @return Iterator pointing to the first element. + */ +Fl_Complex_Region::Iterator Fl_Complex_Region::begin() +{ + return Iterator(this); +} + +/** + * Returns an interator object to mark the end of travesing the tree. + * C++11 interface to range-based loops. + * @return + */ +Fl_Complex_Region::Iterator Fl_Complex_Region::end() +{ + return Iterator(0L); +} + +/** + * Create an iterator to walk the entire tree. + * @param r Iterate through this region, r must not have a parent(). + */ +Fl_Complex_Region::Iterator::Iterator(Fl_Complex_Region *r) : + pRegion(r) +{ +} + +/** + * Compare two iterators. + * C++11 needs this to find the end of a for loop. + * @param other + * @return + */ +bool Fl_Complex_Region::Iterator::operator!=(const Iterator &other) const +{ + return pRegion != other.pRegion; +} + +/** + * Set the iterator to the next object in the tree, down first. + * C++11 needs this to iterate in a for loop. + * @return + */ +const Fl_Complex_Region::Iterator &Fl_Complex_Region::Iterator::operator++() +{ + if (pRegion->subregion()) { + pRegion = pRegion->subregion(); + } else if (pRegion->next()) { + pRegion = pRegion->next(); + } else { + pRegion = pRegion->parent(); + } + return *this; +} + +/** + * Return the current object while iterating through the tree. + * @return + */ +Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const +{ + return pRegion; +} + +// ----------------------------------------------------------------------------- + +/** + * Use this to iterate through a region, hitting only nodes that intersect with this rect. + * @param r find all parts of the region that intersect with this rect. + * @return an object that can be used in range-based for loops in C++11. + */ +Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(const Fl_Rect_Region &r) +{ + return Overlapping(this, r); +} + +/** + * A helper object for iterating through a region, finding only overlapping rects. + * @param rgn + * @param rect + */ +Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn, + const Fl_Rect_Region &rect) : + pRegion(rgn), + pOriginalRect(rect), + pClippedRect(rect) +{ +} + +/** + * Return an itertor for the first clipping rectangle inside the region. + * @return + */ +Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::begin() +{ + find_intersecting(); + return OverlappingIterator(this); +} + +/** + * Return an iterator for the end of forward iteration. + * @return + */ +Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end() +{ + return OverlappingIterator(0L); +} + +/** + * Return the result of intersecting the original rect with this iterator. + * @return + */ +Fl_Rect_Region &Fl_Complex_Region::Overlapping::clipped_rect() +{ + return pClippedRect; +} + +/** + * Store the intersection in pClippedRect and return true if there was an intersection. + * @return + */ +bool Fl_Complex_Region::Overlapping::intersects() +{ + return (pClippedRect.intersect_with(*pRegion) != EMPTY); +} + +/** + * Find the next element in the tree that actually intersects with the initial rect. + * Starting the search at the current object, NOT the next object. + * @return + */ +bool Fl_Complex_Region::Overlapping::find_intersecting() +{ + for (;;) { + if (!pRegion) return false; + pClippedRect.set(pOriginalRect); + if (intersects()) { + if (!pRegion->subregion()) { + return true; + } else { + pRegion = pRegion->subregion(); + } + } else { + find_next(); + } + } +} + +/** + * Find the next object in the tree, complex, simple, intersecting or not. + * @return + */ +bool Fl_Complex_Region::Overlapping::find_next() +{ + if (pRegion->subregion()) { + pRegion = pRegion->subregion(); + } else if (pRegion->next()) { + pRegion = pRegion->next(); + } else { + pRegion = pRegion->parent(); // can be NULL + } + return (pRegion != 0L); +} + +// ----------------------------------------------------------------------------- + +/** + * Create the actual iterator for finding true clipping rects. + * @see Fl_Complex_Region::Overlapping + * @param ov + */ +Fl_Complex_Region::Overlapping::OverlappingIterator::OverlappingIterator( + Overlapping *ov) : + pOv(ov) +{ +} + +/** + * Compare two iterator. + * This is used by C++11 range0based for loops to find the end of the range. + * @param other + * @return + */ +bool Fl_Complex_Region::Overlapping::OverlappingIterator::operator!=( + const OverlappingIterator &other) const +{ + auto thisRegion = pOv ? pOv->pRegion : nullptr; + auto otherRegion = other.pOv ? other.pOv->pRegion : nullptr; + return thisRegion != otherRegion; +} + +/** + * Wrapper to find and set the next intersecting rectangle. + * @see Fl_Complex_Region::Overlapping::find_intersecting + * @see Fl_Complex_Region::Overlapping::find_next + * @return + */ +const Fl_Complex_Region::Overlapping::OverlappingIterator & +Fl_Complex_Region::Overlapping::OverlappingIterator::operator++() +{ + pOv->find_next(); + if (pOv->pRegion) + pOv->find_intersecting(); + return *this; +} + +/** + * Return the Fl_Complex_Region::Overlapping state for this iterator. + * This gives the user access to the current rectangular fragment of + * the clipping region. + * @return + */ +Fl_Complex_Region::Overlapping * +Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const +{ + return pOv; +} + +// ============================================================================= + + +void Fl_Android_Graphics_Driver::restore_clip() +{ + fl_clip_state_number++; + + pClippingRegion.set(pDesktopWindowRegion); + + + Fl_Region b = rstack[rstackptr]; + if (b) { + // FIXME: pClippingRegion.intersect_with(*b); + } +} + + +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::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); + Fl_Region current = rstack[rstackptr]; + if (current) { + r->intersect_with(*current); + } + } else { // make empty clip region: + r = new Fl_Rect_Region(); + } + 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) { + 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; + } +} + +/* + 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 (w <= 0 || h <= 0) return 0; + Fl_Region r = rstack[rstackptr]; + 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 { + return 1; + } +} + + +// +// End of "$Id$". +// diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H index 53118dc15..db8984c4c 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.H +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.H @@ -26,144 +26,13 @@ #define FL_ANDROID_GRAPHICS_DRIVER_H #include +#include "Fl_Android_Graphics_Clipping.H" #include class Fl_Android_Window_Driver; -/** - * 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: - enum Type { - EMPTY = 0, SAME, LESS, MORE, INFINITE - }; - - 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_ltrb(int l, int t, int r, int b); - virtual void set(const Fl_Rect_Region &r); - virtual 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); -}; - - -/** - * The Fl_Complex_Region represents a clipping region of any shape. - * - * This class is organized in a tree-like structure. If the region is - * rectangular, is_simple() returns 1 and the rectangle can be used just - * as in Fl_Rect_Region. - * - * If a more complex representation is needed, the first list of - * subregions is organizen in horizontal strips. The root region rect - * will contain the outline of all subregions, and the subregions - * will either be simple rectangles, or they will contain a second - * level of subregions, subdividing the horizontal region into vertical - * columns. - * - * When reading, the tree can be easily walked using recursion. - */ -class Fl_Complex_Region : public Fl_Rect_Region -{ - class Iterator { - public: - Iterator(Fl_Complex_Region *r); - bool operator!= (const Iterator& other) const; - const Iterator& operator++ (); - Fl_Complex_Region *operator* () const; - Fl_Complex_Region *pRegion; - }; - - class Overlapping { - class OverlappingIterator { - public: - OverlappingIterator(Overlapping *ov); - bool operator!= (const OverlappingIterator& other) const; - const OverlappingIterator& operator++ (); - Overlapping *operator* () const; - Overlapping *pOv; - }; - public: - Overlapping(Fl_Complex_Region *rgn, const Fl_Rect_Region &rect); - OverlappingIterator begin(); - OverlappingIterator end(); - Fl_Rect_Region &clipped_rect(); - bool intersects(); - bool find_intersecting(); - bool find_next(); - Fl_Complex_Region *pRegion; - Fl_Rect_Region pOriginalRect; - Fl_Rect_Region pClippedRect; - }; - -public: - Fl_Complex_Region(); - Fl_Complex_Region(const Fl_Rect_Region&); - virtual ~Fl_Complex_Region() override; - - virtual void set(const Fl_Rect_Region &r) override; - void set(const Fl_Complex_Region &r); - Fl_Complex_Region *subregion() const { return pSubregion; } - Fl_Complex_Region *next() const { return pNext; } - Fl_Complex_Region *parent() const { return pParent; } - char is_simple() const { return pSubregion==0; } - char is_complex() const { return pSubregion!=0; } - - virtual int intersect_with(const Fl_Rect_Region &r) override; - int subtract(const Fl_Rect_Region &r); - - virtual void print(const char*) const override; - - Iterator begin(); - Iterator end(); - - Overlapping overlapping(const Fl_Rect_Region &r); - -protected: - void print_data(int indent) const; - int subtract_smaller_region(const Fl_Rect_Region &r); - Fl_Complex_Region *add_subregion(); - - Fl_Complex_Region *pSubregion = 0L; - Fl_Complex_Region *pParent = 0L; - Fl_Complex_Region *pNext = 0L; -}; - - /** \brief The Windows-specific graphics driver class. diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx deleted file mode 100644 index 1bf05d0af..000000000 --- a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx +++ /dev/null @@ -1,715 +0,0 @@ -// -// "$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 - - -/** - * 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); -} - -/** - * Set an empty clipping rect. - */ -void Fl_Rect_Region::set_empty() -{ - pLeft = pTop = pRight = pBottom = 0; -} - -/** - * Set a clipping rect using position and size - * @param x, y position - * @param w, h size - */ -void Fl_Rect_Region::set(int x, int y, int w, int h) -{ - pLeft = x; - pTop = y; - pRight = x+w; - pBottom = y+h; -} - -/** - * Set a rectangle using the coordinates of two points, top left and bottom right. - * @param l, t left and top coordinate - * @param r, b right and bottom coordinate - */ -void Fl_Rect_Region::set_ltrb(int l, int t, int r, int b) -{ - pLeft = l; - pTop = t; - pRight = r; - pBottom = b; -} - -/** - * Copy the corrdinates from another rect. - * @param r source rectangle - */ -void Fl_Rect_Region::set(const Fl_Rect_Region &r) -{ - pLeft = r.pLeft; - pTop = r.pTop; - pRight = r.pRight; - pBottom = r.pBottom; -} - -/** - * Set this rect to be the intersecting area between the original rect and another rect. - * @param r another rectangular region - * @return EMPTY, if rectangles are not intersecting, SAME if this and rect are - * equal, LESS if the new rect is smaller than the original rect - */ -int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r) -{ - if (is_empty()) { - return EMPTY; - } - if (r.is_empty()) { - set_empty(); - return EMPTY; - } - bool same = true; - if ( pLeft != r.pLeft ) { - same = false; - if ( r.pLeft > pLeft ) pLeft = r.pLeft; - } - 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; -} - -/** - * Print the coordinates of the rect to the log. - * @param label some text that is logged with this message. - */ -void Fl_Rect_Region::print(const char *label) const -{ - Fl_Android_Application::log_i("---> Fl_Rect_Region: %s", label); - Fl_Android_Application::log_i("Rect l:%d t:%d r:%d b:%d", left(), top(), right(), bottom()); -} - -// ============================================================================= - -/** - * Create an empty complex region. - */ -Fl_Complex_Region::Fl_Complex_Region() : - Fl_Rect_Region() -{ -} - -/** - * Create a complex region with the same bounds as the give rect. - * @param r region size - */ -Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) : - Fl_Rect_Region(r) -{ -} - -/** - * Delete this region, all subregions recursively, and all following regions. - */ -Fl_Complex_Region::~Fl_Complex_Region() -{ - delete pSubregion; // recursively delete all subregions - delete pNext; // recursively delete all following regions -} - -/** - * Print the entire content of this region recursively. - */ -void Fl_Complex_Region::print(const char *label) const -{ - Fl_Android_Application::log_i("---> Fl_Complex_Region: %s", label); - print_data(0); -} - -/* - * Print the rectangular data only. - */ -void Fl_Complex_Region::print_data(int indent) const -{ - static const char *space = " "; - if (pSubregion) { - Fl_Android_Application::log_i("%sBBox l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom()); - pSubregion->print_data(indent+1); - } else { - Fl_Android_Application::log_i("%sRect l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom()); - } - if (pNext) { - pNext->print_data(indent); - } -} - -/** - * Replace this region with a rectangle. - * @param r the source rectangle - */ -void Fl_Complex_Region::set(const Fl_Rect_Region &r) -{ - delete pSubregion; pSubregion = 0; - Fl_Rect_Region::set(r); -} - -/** - * Replace this region with a copy of another region. - * This operation can be expensive for very complex regions. - * @param r the source region - */ -void Fl_Complex_Region::set(const Fl_Complex_Region &r) -{ - // outline: - // clear this region and copy the coordinates from r - delete pSubregion; pSubregion = 0; - Fl_Rect_Region::set((const Fl_Rect_Region&)r); - if (r.pSubregion) { - pSubregion = new Fl_Complex_Region(); - pSubregion->set(*r.subregion()); - } - if (r.pNext) { - pNext = new Fl_Complex_Region(); - pNext->set(*r.next()); - } -} - -/** - * Set this region to the intersection of the original region and some rect. - * @param r intersect with this rectangle - * @return EMPTY, SAME, LESS - */ -int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r) -{ - delete pSubregion; pSubregion = 0; - // FIXME: handle complex regions! - int ret = Fl_Rect_Region::intersect_with(r); - return ret; -} - -/** - * Subtract a rectangular region from this region. - * @param r the rect that we want removed - * @return currently 0, but could return something meaningful - */ -int Fl_Complex_Region::subtract(const Fl_Rect_Region &r) -{ - if (pSubregion) { - pSubregion->subtract(r); - } else { - // Check if we overlap at all - Fl_Rect_Region s(r); - int intersects = s.intersect_with(*this); - switch (intersects) { - case EMPTY: - // nothing to do - break; - case SAME: - set_empty(); // FIXME: delete this Rect! - break; - case LESS: - // split this rect into 1, 2, 3, or 4 new ones - subtract_smaller_region(s); - break; - default: - Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__); - break; - } - if (pNext) { - pNext->subtract(r); - } - } - return 0; -} - -/** - * Subtract a rect from another rect, potentially creating four new rectangles. - * This assumes that the calling region is NOT complex. - * @param r subtract the area of this rectangle. - * @return currently 0, but this may change - */ -int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r) -{ - // subtract a smaller rect from a larger rect and create subrects as needed - // FIXME: make sure that the bbox of the parent region is shrunk to the size of all children - // if there is only one single coordinte different, we can reuse this container - if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) { - // this should not happen - set_empty(); - } else if (left()!=r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) { - pRight = r.left(); - } else if (left()==r.left() && top()!=r.top() && right()==r.right() && bottom()==r.bottom()) { - pBottom = r.top(); - } else if (left()==r.left() && top()==r.top() && right()!=r.right() && bottom()==r.bottom()) { - pLeft = r.right(); - } else if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()!=r.bottom()) { - pTop = r.bottom(); - } else { - // create multiple regions - if (pTop!=r.top()) { - Fl_Complex_Region *s = add_subregion(); - s->set_ltrb(pLeft, pTop, pRight, r.top()); - } - if (pBottom!=r.bottom()) { - Fl_Complex_Region *s = add_subregion(); - s->set_ltrb(pLeft, r.bottom(), pRight, pBottom); - } - if (pLeft!=r.left()) { - Fl_Complex_Region *s = add_subregion(); - s->set_ltrb(pLeft, r.top(), r.left(), r.bottom()); - } - if (pRight!=r.right()) { - Fl_Complex_Region *s = add_subregion(); - s->set_ltrb(r.right(), r.top(), pRight, r.bottom()); - } - } - return 0; -} - -/** - * Add an empty subregion to the current region. - * @return a pointer to the newly created region. - */ -Fl_Complex_Region *Fl_Complex_Region::add_subregion() -{ - Fl_Complex_Region *r = new Fl_Complex_Region(); - r->pParent = this; - r->pNext = pSubregion; - pSubregion = r; - return r; -} - - -// ----------------------------------------------------------------------------- - -/** - * Returns an interator object for loops that traverse the entire region tree. - * C++11 interface to range-based loops. - * @return Iterator pointing to the first element. - */ -Fl_Complex_Region::Iterator Fl_Complex_Region::begin() -{ - return Iterator(this); -} - -/** - * Returns an interator object to mark the end of travesing the tree. - * C++11 interface to range-based loops. - * @return - */ -Fl_Complex_Region::Iterator Fl_Complex_Region::end() -{ - return Iterator(0L); -} - -/** - * Create an iterator to walk the entire tree. - * @param r Iterate through this region, r must not have a parent(). - */ -Fl_Complex_Region::Iterator::Iterator(Fl_Complex_Region *r) : - pRegion(r) -{ -} - -/** - * Compare two iterators. - * C++11 needs this to find the end of a for loop. - * @param other - * @return - */ -bool Fl_Complex_Region::Iterator::operator!=(const Iterator &other) const -{ - return pRegion != other.pRegion; -} - -/** - * Set the iterator to the next object in the tree, down first. - * C++11 needs this to iterate in a for loop. - * @return - */ -const Fl_Complex_Region::Iterator &Fl_Complex_Region::Iterator::operator++() -{ - if (pRegion->subregion()) { - pRegion = pRegion->subregion(); - } else if (pRegion->next()) { - pRegion = pRegion->next(); - } else { - pRegion = pRegion->parent(); - } - return *this; -} - -/** - * Return the current object while iterating through the tree. - * @return - */ -Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const -{ - return pRegion; -} - -// ----------------------------------------------------------------------------- - -/** - * Use this to iterate through a region, hitting only nodes that intersect with this rect. - * @param r find all parts of the region that intersect with this rect. - * @return an object that can be used in range-based for loops in C++11. - */ -Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(const Fl_Rect_Region &r) -{ - return Overlapping(this, r); -} - -/** - * A helper object for iterating through a region, finding only overlapping rects. - * @param rgn - * @param rect - */ -Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn, - const Fl_Rect_Region &rect) : - pRegion(rgn), - pOriginalRect(rect), - pClippedRect(rect) -{ -} - -/** - * Return an itertor for the first clipping rectangle inside the region. - * @return - */ -Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::begin() -{ - find_intersecting(); - return OverlappingIterator(this); -} - -/** - * Return an iterator for the end of forward iteration. - * @return - */ -Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end() -{ - return OverlappingIterator(0L); -} - -/** - * Return the result of intersecting the original rect with this iterator. - * @return - */ -Fl_Rect_Region &Fl_Complex_Region::Overlapping::clipped_rect() -{ - return pClippedRect; -} - -/** - * Store the intersection in pClippedRect and return true if there was an intersection. - * @return - */ -bool Fl_Complex_Region::Overlapping::intersects() -{ - return (pClippedRect.intersect_with(*pRegion) != EMPTY); -} - -/** - * Find the next element in the tree that actually intersects with the initial rect. - * Starting the search at the current object, NOT the next object. - * @return - */ -bool Fl_Complex_Region::Overlapping::find_intersecting() -{ - for (;;) { - if (!pRegion) return false; - pClippedRect.set(pOriginalRect); - if (intersects()) { - if (!pRegion->subregion()) { - return true; - } else { - pRegion = pRegion->subregion(); - } - } else { - find_next(); - } - } -} - -/** - * Find the next object in the tree, complex, simple, intersecting or not. - * @return - */ -bool Fl_Complex_Region::Overlapping::find_next() -{ - if (pRegion->subregion()) { - pRegion = pRegion->subregion(); - } else if (pRegion->next()) { - pRegion = pRegion->next(); - } else { - pRegion = pRegion->parent(); // can be NULL - } - return (pRegion != 0L); -} - -// ----------------------------------------------------------------------------- - -/** - * Create the actual iterator for finding true clipping rects. - * @see Fl_Complex_Region::Overlapping - * @param ov - */ -Fl_Complex_Region::Overlapping::OverlappingIterator::OverlappingIterator( - Overlapping *ov) : - pOv(ov) -{ -} - -/** - * Compare two iterator. - * This is used by C++11 range0based for loops to find the end of the range. - * @param other - * @return - */ -bool Fl_Complex_Region::Overlapping::OverlappingIterator::operator!=( - const OverlappingIterator &other) const -{ - auto thisRegion = pOv ? pOv->pRegion : nullptr; - auto otherRegion = other.pOv ? other.pOv->pRegion : nullptr; - return thisRegion != otherRegion; -} - -/** - * Wrapper to find and set the next intersecting rectangle. - * @see Fl_Complex_Region::Overlapping::find_intersecting - * @see Fl_Complex_Region::Overlapping::find_next - * @return - */ -const Fl_Complex_Region::Overlapping::OverlappingIterator & -Fl_Complex_Region::Overlapping::OverlappingIterator::operator++() -{ - pOv->find_next(); - if (pOv->pRegion) - pOv->find_intersecting(); - return *this; -} - -/** - * Return the Fl_Complex_Region::Overlapping state for this iterator. - * This gives the user access to the current rectangular fragment of - * the clipping region. - * @return - */ -Fl_Complex_Region::Overlapping * -Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const -{ - return pOv; -} - -// ============================================================================= - - -void Fl_Android_Graphics_Driver::restore_clip() -{ - fl_clip_state_number++; - - pClippingRegion.set(pDesktopWindowRegion); - - - Fl_Region b = rstack[rstackptr]; - if (b) { - // FIXME: pClippingRegion.intersect_with(*b); - } -} - - -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::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); - Fl_Region current = rstack[rstackptr]; - if (current) { - r->intersect_with(*current); - } - } else { // make empty clip region: - r = new Fl_Rect_Region(); - } - 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) { - 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; - } -} - -/* - 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 (w <= 0 || h <= 0) return 0; - Fl_Region r = rstack[rstackptr]; - 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 { - return 1; - } -} - - -// -// End of "$Id$". -// -- cgit v1.2.3