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 @@ -167,6 +167,17 @@ int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r) return LESS; } +/** + * 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.pLeftpRight) 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,9 +318,48 @@ 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. 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$".