diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2018-03-15 21:17:16 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2018-03-15 21:17:16 +0000 |
| commit | 6a145ed63aa48944b8dced0d5a6fbcaffda507e7 (patch) | |
| tree | 1f0fd0c2b40f7441d4f8f38f53e7cf8abf5524f5 /src/drivers | |
| parent | 726cb77717e00de9cd6d9accad0a69f4ae7a6859 (diff) | |
Android: window clipping working fl_rectf.
This code is not very beautiful, but the resulting class should be
easy to use. A range-based loop can be used to find all relevant
clipping rectangles for a drawing call.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12754 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.H | 56 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 73 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | 159 |
3 files changed, 241 insertions, 47 deletions
diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H index af106785d..e20f02a19 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.H +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.H @@ -80,6 +80,7 @@ private: Fl_Rect_Region& operator = (const Fl_Rect_Region& other); }; + /** * The Fl_Complex_Region represents a clipping region of any shape. * @@ -98,32 +99,65 @@ private: */ 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, 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 set(int x, int y, int w, int h); -// virtual void set(Fl_Rect_Region*); -// void subtract(Fl_Rect_Region*); -// void intersect(Fl_Rect_Region*); -// void clone(Fl_Complex_Region*); - char is_simple() const { return pSubregion==0; } - char is_complex() const { return pSubregion!=0; } + virtual void print(const char*) const override; - Fl_Complex_Region *subregion() const { return pSubregion; } - Fl_Complex_Region *next() const { return pNext; } + Iterator begin(); + Iterator end(); - Fl_Complex_Region *add_subregion(); + Overlapping overlapping(Fl_Rect_Region &r); - virtual void print(const char*) const override; 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; diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx index 554d72e84..aa2bcd937 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx @@ -97,15 +97,46 @@ static uint16_t make565(Fl_Color crgba) void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) { - // FIXME: r must be a complex region, like pClippingRegion. +#if 1 Fl_Rect_Region r(x, y, w, h); -#if 0 - if (r.intersect_with(pClippingRegion)) { - rectf_unclipped(r.x(), r.y(), r.w(), r.h()); + for (const auto &it: pClippingRegion.overlapping(r)) { +#if 1 + Fl_Rect_Region s(it->clipped_rect()); + rectf_unclipped(s.x(), s.y(), s.w(), s.h()); +#else + if (it->is_simple()) { + Fl_Rect_Region r(x, y, w, h); + if (r.intersect_with(*it)) { + rectf_unclipped(r.x(), r.y(), r.w(), r.h()); + } + } +#endif + } + +#elif 0 + + // This is elegant code, but it is not efficient. It walks the entire tree + // and checks for intersetion, even if the parent region indicated that there + // is no intersection. + // + // Maybe we can add a parameter somewhere so that the iterator runs the tree + // based on a give rectangle. + + for (const auto &it: pClippingRegion) { + // TODO: if region is complex, but doesn't intersect, can we somehow manipulate the iterator? + if (it->is_simple()) { + Fl_Rect_Region r(x, y, w, h); + if (r.intersect_with(*it)) { + rectf_unclipped(r.x(), r.y(), r.w(), r.h()); + } + } } -#else // proof of concept - // FIXME: write iterator over tree + +#else + + // This code is massiv and ugly and has the same problem in that it does not + // optimize the number of tests for intersections. r.print("---- fl_rectf"); pClippingRegion.print("clip to"); @@ -134,36 +165,8 @@ void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float } } } -#endif - - - - - // TODO: create a complex region by intersecting r with the pClippingRegion - // TODO: walk the region and draw all rectangles - - /* - * rectf(x, y, w, h) { - * rectf(complex_window_region, drawing_rect(x, y, w, h)) - * } - * - * rectf( complexRgn, drawRgn) { - * // B: start of iterator - * if (intersect(rect_of_complexRgn, drawRgn) { - * if (complexRgn->is_complex() { - * rectf(complexRgn->subregion, drawRect); - * } else { - * rawRect = intersection(rect_of_complexRgn, drawRgn); - * rawDrawRect(rawRect); - * } - * } - * // A: recursion - * if (complexRgn->next) - * rectf(complexRgn->next, drawRgn); - * // B: end of iterator - * } - */ +#endif } void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h) diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx index 95e4ccd9a..1763a8d0f 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx @@ -156,7 +156,7 @@ void Fl_Rect_Region::print(const char *label) const Fl_Android_Application::log_i("Rect l:%d t:%d r:%d b:%d", left(), top(), right(), bottom()); } -// ----------------------------------------------------------------------------- +// ============================================================================= /** * Create an empty complex region. @@ -330,12 +330,169 @@ int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r) 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; } +// ----------------------------------------------------------------------------- + +Fl_Complex_Region::Iterator Fl_Complex_Region::begin() +{ + return Iterator(this); +} + + +Fl_Complex_Region::Iterator Fl_Complex_Region::end() +{ + return Iterator(0L); +} + + +Fl_Complex_Region::Iterator::Iterator(Fl_Complex_Region *r) : + pRegion(r) +{ +} + + +bool Fl_Complex_Region::Iterator::operator!=(const Iterator &other) const +{ + return pRegion != other.pRegion; +} + + +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; +} + + +Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const +{ + return pRegion; +} + +// ----------------------------------------------------------------------------- + +Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(Fl_Rect_Region &r) +{ + return Overlapping(this, r); +} + + +Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn, + Fl_Rect_Region &rect) : + pRegion(rgn), + pOriginalRect(rect), + pClippedRect(rect) +{ +} + + +Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::begin() +{ + find_intersecting(); + return OverlappingIterator(this); +} + + +Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end() +{ + return OverlappingIterator(0L); +} + + +Fl_Rect_Region &Fl_Complex_Region::Overlapping::clipped_rect() +{ + return pClippedRect; +} + + +bool Fl_Complex_Region::Overlapping::intersects() +{ + return (pClippedRect.intersect_with(*pRegion) != EMPTY); +} + + +bool Fl_Complex_Region::Overlapping::find_intersecting() +{ + for (;;) { + if (!pRegion) return false; + pClippedRect.set(pOriginalRect); + pRegion->print("find intersetion"); + pClippedRect.print("with"); + pOriginalRect.print("with"); + if (intersects()) { + if (!pRegion->subregion()) { + return true; + } else { + pRegion = pRegion->subregion(); + } + } else { + find_next(); + } + } +} + + +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); +} + +// ----------------------------------------------------------------------------- + + +Fl_Complex_Region::Overlapping::OverlappingIterator::OverlappingIterator( + Overlapping *ov) : + pOv(ov) +{ +} + + +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; +} + + +const Fl_Complex_Region::Overlapping::OverlappingIterator & +Fl_Complex_Region::Overlapping::OverlappingIterator::operator++() +{ + pOv->find_next(); + if (pOv->pRegion) + pOv->find_intersecting(); + return *this; +} + + +Fl_Complex_Region::Overlapping * +Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const +{ + return pOv; +} + +// ============================================================================= + #if 0 void Fl_Complex_Region::set(int x, int y, int w, int h) |
