diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2018-03-16 12:48:29 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2018-03-16 12:48:29 +0000 |
| commit | bdb63b3f07cba389ce3fb584218389349561321c (patch) | |
| tree | c2a99faa16c1446eea3b2872bcd5d09c5513e3ba /src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | |
| parent | 0e4b7bbb49e89ed3808c36eeba3881dba62a2094 (diff) | |
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
Diffstat (limited to 'src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx')
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | 715 |
1 files changed, 0 insertions, 715 deletions
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 <FL/platform.H> - - -/** - * 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$". -// |
