summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2018-03-15 21:17:16 +0000
committerMatthias Melcher <fltk@matthiasm.com>2018-03-15 21:17:16 +0000
commit6a145ed63aa48944b8dced0d5a6fbcaffda507e7 (patch)
tree1f0fd0c2b40f7441d4f8f38f53e7cf8abf5524f5
parent726cb77717e00de9cd6d9accad0a69f4ae7a6859 (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
-rw-r--r--ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx4
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver.H56
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver.cxx73
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx159
4 files changed, 243 insertions, 49 deletions
diff --git a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
index af6358fd2..ca45221b4 100644
--- a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
+++ b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
@@ -55,7 +55,7 @@ void hello_cb(void*)
int main(int argc, char **argv)
{
- win1 = new Fl_Window(10+50, 10, 200, 200, "back");
+ win1 = new Fl_Window(20+50, 10, 200, 200, "back");
win1->color(FL_RED);
win1->box(FL_DOWN_BOX);
Fl_Button *b1 = new Fl_Button(10, 10, 180, 180, "back");
@@ -79,7 +79,7 @@ int main(int argc, char **argv)
win->end();
win->show(argc, argv);
- win2 = new Fl_Window(390-50, 10, 200, 200, "front");
+ win2 = new Fl_Window(380-50, 10, 200, 200, "front");
win2->color(FL_BLUE);
win2->box(FL_UP_BOX);
Fl_Button *b2 = new Fl_Button(10, 10, 180, 180, "front");
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)