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
This commit is contained in:
parent
726cb77717
commit
6a145ed63a
@ -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");
|
||||
|
@ -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);
|
||||
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*);
|
||||
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; }
|
||||
|
||||
Fl_Complex_Region *subregion() const { return pSubregion; }
|
||||
Fl_Complex_Region *next() const { return pNext; }
|
||||
|
||||
Fl_Complex_Region *add_subregion();
|
||||
virtual int intersect_with(const Fl_Rect_Region &r) override;
|
||||
int subtract(const Fl_Rect_Region &r);
|
||||
|
||||
virtual void print(const char*) const override;
|
||||
|
||||
Iterator begin();
|
||||
Iterator end();
|
||||
|
||||
Overlapping overlapping(Fl_Rect_Region &r);
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
}
|
||||
#else // proof of concept
|
||||
// FIXME: write iterator over tree
|
||||
|
||||
#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
|
||||
|
||||
// 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
|
||||
* }
|
||||
*/
|
||||
}
|
||||
|
||||
void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user