From d252801a319deb371bba3bdf1adb760f50514ac9 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sun, 18 Mar 2018 14:58:25 +0000 Subject: [PATCH] Android: Fixed another bug when deleting complex clipping areas Better complex region cleanup - should be compete now... git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12772 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- .../Android/Fl_Android_Graphics_Clipping.H | 1 + .../Android/Fl_Android_Graphics_Clipping.cxx | 112 ++++++++---------- .../Android/Fl_Android_Graphics_Font.cxx | 12 +- .../Android/Fl_Android_Screen_Driver.cxx | 12 +- 4 files changed, 65 insertions(+), 72 deletions(-) diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.H b/src/drivers/Android/Fl_Android_Graphics_Clipping.H index 7f6d43f96..349be87e1 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Clipping.H +++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.H @@ -149,6 +149,7 @@ public: Fl_Complex_Region(); Fl_Complex_Region(const Fl_Rect_Region&); virtual ~Fl_Complex_Region() override; + void delete_all_subregions(); virtual void set(const Fl_Rect_Region &r) override; void set(const Fl_Complex_Region &r); diff --git a/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx index 1ea7cdb08..f25f61976 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Clipping.cxx @@ -212,6 +212,19 @@ Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) : * Delete this region, all subregions recursively, and all following regions. */ Fl_Complex_Region::~Fl_Complex_Region() +{ + delete_all_subregions(); +} + +/** + * Delete all subregions of this region. + * The pSubregion pointer should always be seen as a list of subregions, rather + * than a single region and some pNext pointer. So everything we do, we should + * probably do for every object in that list. + * + * Also note, that the top level region never has pNext pointing to anything. + */ +void Fl_Complex_Region::delete_all_subregions() { // Do NOT delete the chain in pNext! The caller has to that job. // A top-level coplex region has pNext always set to NULL, and it does @@ -219,7 +232,7 @@ Fl_Complex_Region::~Fl_Complex_Region() while (pSubregion) { Fl_Complex_Region *rgn = pSubregion; pSubregion = rgn->pNext; - delete rgn; + delete rgn; rgn = 0; } } @@ -256,7 +269,7 @@ void Fl_Complex_Region::print_data(int indent) const void Fl_Complex_Region::set(const Fl_Rect_Region &r) { Fl_Rect_Region::set(r); - delete pSubregion; pSubregion = 0; + delete_all_subregions(); } /** @@ -266,17 +279,21 @@ void Fl_Complex_Region::set(const Fl_Rect_Region &r) */ void Fl_Complex_Region::set(const Fl_Complex_Region &r) { - // outline: - // clear this region and copy the coordinates from r - delete pSubregion; pSubregion = 0; Fl_Rect_Region::set((const Fl_Rect_Region&)r); - if (r.pSubregion) { - pSubregion = new Fl_Complex_Region(); - pSubregion->set(*r.subregion()); - } - if (r.pNext) { - pNext = new Fl_Complex_Region(); - pNext->set(*r.next()); + delete_all_subregions(); + + Fl_Complex_Region *srcRgn = r.pSubregion; + if (srcRgn) { + // copy first subregion + Fl_Complex_Region *dstRgn = pSubregion = new Fl_Complex_Region(); + pSubregion->set(*srcRgn); + // copy rest of list + while (srcRgn) { + dstRgn->pNext = new Fl_Complex_Region(); + dstRgn = dstRgn->next(); + dstRgn->set(*srcRgn); + srcRgn = srcRgn->next(); + } } } @@ -288,28 +305,15 @@ void Fl_Complex_Region::set(const Fl_Complex_Region &r) int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r) { if (pSubregion) { - pSubregion->intersect_with(r); + Fl_Complex_Region *rgn = pSubregion; + while (rgn) { + rgn->intersect_with(r); + rgn = rgn->next(); + } + compress(); } else { - int intersects = Fl_Rect_Region::intersect_with(r); - switch (intersects) { - case EMPTY: - // Will be deleted by compress() - break; - case SAME: - // nothing to do - break; - case LESS: - // nothing to do - break; - default: - Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__); - break; - } - if (pNext) { - pNext->intersect_with(r); - } + Fl_Rect_Region::intersect_with(r); } - compress(); return 0; } @@ -321,7 +325,12 @@ int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r) int Fl_Complex_Region::subtract(const Fl_Rect_Region &r) { if (pSubregion) { - pSubregion->subtract(r); + Fl_Complex_Region *rgn = pSubregion; + while (rgn) { + rgn->subtract(r); + rgn = rgn->next(); + } + compress(); } else { // Check if we overlap at all Fl_Rect_Region s(r); @@ -341,11 +350,8 @@ int Fl_Complex_Region::subtract(const Fl_Rect_Region &r) Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__); break; } - if (pNext) { - pNext->subtract(r); - } + if (pSubregion) compress(); // because intersecting this may have created subregions } - compress(); return 0; } @@ -365,41 +371,27 @@ void Fl_Complex_Region::compress() Fl_Complex_Region *rgn = pSubregion; while (rgn && rgn->is_empty()) { pSubregion = rgn->next(); - delete rgn; - rgn = pSubregion; - } - - -#if 0 - // FIXME: remove emty rectangles and lift single rectangles - // TODO: merging rectangles may take much too much time with little benefit - print("compress"); - while (rgn && rgn->is_empty()) { - pSubregion = rgn->next(); - delete rgn; - rgn = pSubregion; + delete rgn; rgn = pSubregion; } if (!pSubregion) return; + rgn = pSubregion; while (rgn) { - Fl_Complex_Region *nextRgn = rgn->next(); - if (nextRgn && nextRgn->is_empty()) { - rgn->pNext = nextRgn->next(); - delete nextRgn; - nextRgn = rgn->pNext; + while (rgn->pNext && rgn->pNext->is_empty()) { + Fl_Complex_Region *nextNext = rgn->pNext->pNext; + delete rgn->pNext; rgn->pNext = nextNext; } rgn = rgn->next(); } - if (!pSubregion) return; // find rectangles that can be merged into a single new rectangle + // (Too much work for much too little benefit) // 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; -#endif // finally, update the boudning box Fl_Rect_Region::set((Fl_Rect_Region&)*pSubregion); @@ -484,7 +476,7 @@ Fl_Complex_Region::Iterator Fl_Complex_Region::begin() */ Fl_Complex_Region::Iterator Fl_Complex_Region::end() { - return Iterator(0L); + return Iterator(nullptr); } /** @@ -574,7 +566,7 @@ Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlappi */ Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end() { - return OverlappingIterator(0L); + return OverlappingIterator(nullptr); } /** @@ -630,7 +622,7 @@ bool Fl_Complex_Region::Overlapping::find_next() } else { pRegion = pRegion->parent(); // can be NULL } - return (pRegion != 0L); + return (pRegion != nullptr); } // ----------------------------------------------------------------------------- diff --git a/src/drivers/Android/Fl_Android_Graphics_Font.cxx b/src/drivers/Android/Fl_Android_Graphics_Font.cxx index 55136e73e..53021c063 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Font.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Font.cxx @@ -69,7 +69,7 @@ static const char *old_font_names[] = { * Create an empty Bytemap. */ Fl_Android_Bytemap::Fl_Android_Bytemap() : - pBytes(0L) + pBytes(nullptr) { } @@ -90,7 +90,7 @@ Fl_Android_Bytemap::~Fl_Android_Bytemap() * @param fnum the index into the fl_fonts table */ Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) : - pFileBuffer(0L), + pFileBuffer(nullptr), pName(fname), pFontIndex(fnum), pError(false) @@ -133,7 +133,7 @@ bool Fl_Android_Font_Source::load_font_asset(const char *name) errno = 0; AAssetManager *aMgr = Fl_Android_Application::get_asset_manager(); AAsset *aFile = AAssetManager_open(aMgr, name, AASSET_MODE_STREAMING); - if (aFile == NULL) { + if (aFile == nullptr) { Fl_Android_Application::log_w("Can't open font asset at '%s': ", name, strerror(errno)); return false; @@ -173,7 +173,7 @@ bool Fl_Android_Font_Source::load_font_file(const char *name) strcpy(buf, name); } FILE *f = fopen(buf, "rb"); - if (f == NULL) { + if (f == nullptr) { Fl_Android_Application::log_w("Can't open font file at '%s': ", name, strerror(errno)); return false; @@ -242,7 +242,7 @@ void Fl_Android_Font_Source::load_font() Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size) { if (pFileBuffer==0) load_font(); - if (pError) return 0L; + if (pError) return nullptr; Fl_Android_Bytemap *bm = new Fl_Android_Bytemap(); @@ -330,7 +330,7 @@ Fl_Android_Font_Descriptor::~Fl_Android_Font_Descriptor() { // Life is easy in C++11. for (auto &i: pBytemapTable) { - delete i.second; + delete i.second; i.second = nullptr; } } diff --git a/src/drivers/Android/Fl_Android_Screen_Driver.cxx b/src/drivers/Android/Fl_Android_Screen_Driver.cxx index e9458c9c7..e713f5b95 100644 --- a/src/drivers/Android/Fl_Android_Screen_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Screen_Driver.cxx @@ -77,7 +77,7 @@ int Fl_Android_Screen_Driver::handle_app_command() // call all registered FLTK system handlers Fl::e_number = ((uint32_t)(cmd-Fl_Android_Application::APP_CMD_INPUT_CHANGED)) + FL_ANDROID_EVENT_INPUT_CHANGED; - fl_send_system_handlers(0L); + fl_send_system_handlers(nullptr); // fixup and finalize application wide command handling Fl_Android_Application::post_exec_cmd(cmd); @@ -87,7 +87,7 @@ int Fl_Android_Screen_Driver::handle_app_command() int Fl_Android_Screen_Driver::handle_input_event() { AInputQueue *queue = Fl_Android_Application::input_event_queue(); - AInputEvent *event = NULL; + AInputEvent *event = nullptr; if (AInputQueue_getEvent(queue, &event) >= 0) { if (AInputQueue_preDispatchEvent(queue, event)==0) { @@ -179,7 +179,7 @@ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait) struct android_poll_source *source; for (;;) { - ident = ALooper_pollAll(Fl::damage() ? 0 : -1, NULL, &events, (void **) &source); + ident = ALooper_pollAll(Fl::damage() ? 0 : -1, nullptr, &events, (void **) &source); switch (ident) { // FIXME: ALOOPER_POLL_WAKE = -1, ALOOPER_POLL_CALLBACK = -2, ALOOPER_POLL_TIMEOUT = -3, ALOOPER_POLL_ERROR = -4 case Fl_Android_Application::LOOPER_ID_MAIN: @@ -718,7 +718,7 @@ struct TimerData bool triggered; struct itimerspec timeout; }; -static TimerData* timerData = 0L; +static TimerData* timerData = nullptr; static int NTimerData = 0; static int nTimerData = 0; @@ -818,7 +818,7 @@ void Fl_Android_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb { 0, 0 }, { (time_t)floor(time), (long)(modf(time, &ff)*1000000000) } }; - ret = timer_settime(t.handle, 0, &t.timeout, 0L); + ret = timer_settime(t.handle, 0, &t.timeout, nullptr); if (ret==-1) { Fl_Android_Application::log_e("Can't launch timer: %s", strerror(errno)); return; @@ -843,7 +843,7 @@ void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data) { for (int i = 0; i < nTimerData; ++i) { TimerData& t = timerData[i]; - if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==NULL) ) ) { + if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==nullptr) ) ) { if (t.used) timer_delete(t.handle); t.triggered = t.used = false;