summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2018-03-16 17:39:16 +0000
committerMatthias Melcher <fltk@matthiasm.com>2018-03-16 17:39:16 +0000
commitb6858cef5694f3c2aa9a9899d2516ef07ea7d85c (patch)
treebe2300053715979611f9289908b7d96b125738e6
parente0a15603dd92d4a6965a5ccc59f5485824f81038 (diff)
Android: added function to optimize complex regions
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12760 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Clipping.H31
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Clipping.cxx52
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver.cxx3
3 files changed, 78 insertions, 8 deletions
diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.H b/src/drivers/Android/Fl_Android_Graphics_Clipping.H
index 803548bab..7c88b54a5 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Clipping.H
+++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.H
@@ -69,6 +69,7 @@ public:
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);
+ void add_to_bbox(const Fl_Rect_Region &r);
virtual void print(const char*) const;
@@ -87,14 +88,29 @@ private:
* 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.
+ * If a more complex representation is needed, subregions are created which are
+ * guaranteed to lie within the bounding box of the current region. Subregions
+ * themselves can again contain sub-subregions to describe the entire clipping
+ * region, effectively creating a tree where the leafs contain the rectangles
+ * that together describe the clipping area.
+ *
+ * To make life easier, Fl_Complex_Region provides two types of iterator to
+ * travers the entire tree.
+ *
+ * 1. Fl_Complex_Region itself is compatible to C++11 range-based loops and
+ * can bewalked simply by writing ``for (auto &&it: rgn) { ... }``.
+ *
+ * 2. Fl_Complex_Region provides an alternative iterator that loop only through
+ * leafs that intersects with a given rectangle. The returned object
+ * provides access to the readily clipped rectangle.
+ *
+ * @code
+ * Fl_Complex_Region rgn(something);
+ * for (auto &&it: rgn.iterate(Fl_Rect_Region(0, 0, 100, 100)) {
+ * draw_something(it->rect());
+ * }
+ * @endcode
*
- * When reading, the tree can be easily walked using recursion.
*/
class Fl_Complex_Region : public Fl_Rect_Region
{
@@ -156,6 +172,7 @@ protected:
void print_data(int indent) const;
int subtract_smaller_region(const Fl_Rect_Region &r);
Fl_Complex_Region *add_subregion();
+ void compress();
Fl_Complex_Region *pSubregion = 0L;
Fl_Complex_Region *pParent = 0L;
diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx
index 000ef929f..022acea86 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx
+++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx
@@ -168,6 +168,17 @@ int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r)
}
/**
+ * Use rectangle as a bounding box and add the outline of another rect.
+ */
+void Fl_Rect_Region::add_to_bbox(const Fl_Rect_Region &r)
+{
+ if (r.pLeft<pLeft) pLeft = r.pLeft;
+ if (r.pTop<pTop) pTop = r.pTop;
+ if (r.pRight>pRight) pRight = r.pRight;
+ if (r.pBottom>pBottom) pBottom = r.pBottom;
+}
+
+/**
* Print the coordinates of the rect to the log.
* @param label some text that is logged with this message.
*/
@@ -237,8 +248,8 @@ void Fl_Complex_Region::print_data(int indent) const
*/
void Fl_Complex_Region::set(const Fl_Rect_Region &r)
{
- delete pSubregion; pSubregion = 0;
Fl_Rect_Region::set(r);
+ delete pSubregion; pSubregion = 0;
}
/**
@@ -307,10 +318,49 @@ int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
pNext->subtract(r);
}
}
+ compress();
return 0;
}
/**
+ * Compress the subregion of this region if possible and update the bounding
+ * box of this region.
+ *
+ * Does not recurse down the tree!
+ */
+void Fl_Complex_Region::compress()
+{
+ // Can't compress anything that does not have a subregion
+ if (!pSubregion) return;
+
+ // remove all empty regions, because the really don't add anything (literally)
+ Fl_Complex_Region *rgn = pSubregion, **rgnPtr = &pSubregion;
+ while (rgn) {
+ if (rgn->is_empty()) {
+ *rgnPtr = rgn->pNext;
+ delete rgn;
+ }
+ rgnPtr = &rgn->pNext;
+ rgn = *rgnPtr;
+ }
+ if (!pSubregion) return;
+
+ // find rectangles that can be merged into a single new rectangle
+
+ // if there is only a single subregion left, merge it into this region
+ if (pSubregion->pNext==nullptr) {
+ set((Fl_Rect_Region&)*pSubregion); // deletes subregion for us
+ }
+ if (!pSubregion) return;
+
+ // finally, update the boudning box
+ Fl_Rect_Region::set((Fl_Rect_Region&)*pSubregion);
+ for (rgn=pSubregion->pNext; rgn; rgn=rgn->pNext) {
+ add_to_bbox(*rgn);
+ }
+}
+
+/**
* 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.
diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
index e3dde7d06..c19e05ce1 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
+++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
@@ -544,6 +544,9 @@ void Fl_GDI_Graphics_Driver::set_current_() {
#endif
+/*
+
+ */
//
// End of "$Id$".