From 6f3cb70f640596a528237b5b34cecbc10c52a6ad Mon Sep 17 00:00:00 2001 From: M4x1m3 Date: Mon, 15 Feb 2021 12:23:09 +0100 Subject: [PATCH] [external] Fixed memory leak #454 --- apps/home/app_cell.cpp | 12 +++++++++ apps/home/app_cell.h | 1 + apps/home/controller.cpp | 5 ++-- escher/include/escher/image_view.h | 3 +++ escher/src/image_view.cpp | 39 ++++++++++++++++++++++++------ 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/apps/home/app_cell.cpp b/apps/home/app_cell.cpp index adac67b32..a6e5a1554 100644 --- a/apps/home/app_cell.cpp +++ b/apps/home/app_cell.cpp @@ -33,9 +33,20 @@ void AppCell::layoutSubviews(bool force) { m_nameView.setFrame(KDRect((bounds().width()-nameSize.width())/2-k_nameWidthMargin, bounds().height()-nameSize.height() - 2*k_nameHeightMargin, nameSize.width()+2*k_nameWidthMargin, nameSize.height()+2*k_nameHeightMargin), force); } +void AppCell::setExtAppDescriptor(const char* name, const uint8_t *icon, size_t iconLength) { + m_external_app = true; + m_iconView.setImage(icon, iconLength); + m_iconView.setImage(nullptr); + m_nameView.setText(name); + m_nameView.setTextColor(Palette::HomeCellTextExternal); + m_nameView.setMessage(I18n::Message::Default); + layoutSubviews(); +} + void AppCell::setExtAppDescriptor(const char* name, const Image* icon) { m_external_app = true; m_iconView.setImage(icon); + m_iconView.setImage(nullptr, 0); m_nameView.setText(name); m_nameView.setTextColor(Palette::HomeCellTextExternal); m_nameView.setMessage(I18n::Message::Default); @@ -45,6 +56,7 @@ void AppCell::setExtAppDescriptor(const char* name, const Image* icon) { void AppCell::setAppDescriptor(::App::Descriptor * descriptor) { m_external_app = false; m_iconView.setImage(descriptor->icon()); + m_iconView.setImage(nullptr, 0); m_nameView.setMessage(descriptor->name()); m_nameView.setTextColor(Palette::HomeCellText); m_nameView.setText(nullptr); diff --git a/apps/home/app_cell.h b/apps/home/app_cell.h index fb4c682c7..89c22e008 100644 --- a/apps/home/app_cell.h +++ b/apps/home/app_cell.h @@ -18,6 +18,7 @@ public: void reloadCell() override; void setAppDescriptor(::App::Descriptor * appDescriptor); void setExtAppDescriptor(const char* name, const Image* icon); + void setExtAppDescriptor(const char* name, const uint8_t *icon, size_t iconLength); private: static constexpr KDCoordinate k_iconMargin = 22; static constexpr KDCoordinate k_iconWidth = 55; diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index 23e2551ba..2724bd172 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -189,9 +189,8 @@ void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { if (img_index != -1) { External::Archive::File image_file; if (External::Archive::fileAtIndex(img_index, image_file)) { - const Image* img = new Image(55, 56, image_file.data, image_file.dataLength); - appCell->setExtAppDescriptor(app_file.name, img); - + // const Image* img = new Image(55, 56, image_file.data, image_file.dataLength); + appCell->setExtAppDescriptor(app_file.name, image_file.data, image_file.dataLength); } else { appCell->setExtAppDescriptor(app_file.name, ImageStore::ExternalIcon); } diff --git a/escher/include/escher/image_view.h b/escher/include/escher/image_view.h index bd580092d..f29612b8b 100644 --- a/escher/include/escher/image_view.h +++ b/escher/include/escher/image_view.h @@ -8,9 +8,12 @@ class ImageView : public View { public: ImageView(); void setImage(const Image * image); + void setImage(const uint8_t *data, size_t dataLength); void drawRect(KDContext * ctx, KDRect rect) const override; private: const Image * m_image; + const uint8_t * m_data; + size_t m_dataLength; }; #endif diff --git a/escher/src/image_view.cpp b/escher/src/image_view.cpp index 2259c827b..7cb4ee39e 100644 --- a/escher/src/image_view.cpp +++ b/escher/src/image_view.cpp @@ -6,7 +6,9 @@ extern "C" { ImageView::ImageView() : View(), - m_image(nullptr) + m_image(nullptr), + m_data(nullptr), + m_dataLength(0) { } @@ -15,27 +17,50 @@ constexpr static int maxPixelBufferSize = 4000; // Boot logo file is 188 x 21 = 3948 void ImageView::drawRect(KDContext * ctx, KDRect rect) const { - if (m_image == nullptr) { + const uint8_t* data; + size_t size; + size_t pixelBufferSize; + + if (m_image != nullptr) { + + assert(bounds().width() == m_image->width()); + assert(bounds().height() == m_image->height()); + + data = m_image->compressedPixelData(); + size = m_image->compressedPixelDataSize(); + pixelBufferSize = m_image->width() * m_image->height(); + } else if (m_data != nullptr) { + data = m_data; + size = m_dataLength; + // We assume the external images are made properly. + // TODO: Maybe we shouldn't... + pixelBufferSize = bounds().width() * bounds().height(); + } else { return; } - assert(bounds().width() == m_image->width()); - assert(bounds().height() == m_image->height()); KDColor pixelBuffer[maxPixelBufferSize]; - int pixelBufferSize = m_image->width() * m_image->height(); assert(pixelBufferSize <= maxPixelBufferSize); assert(Ion::stackSafe()); // That's a VERY big buffer we're allocating on the stack Ion::decompress( - m_image->compressedPixelData(), + data, reinterpret_cast(pixelBuffer), - m_image->compressedPixelDataSize(), + size, pixelBufferSize * sizeof(KDColor) ); ctx->fillRectWithPixels(bounds(), pixelBuffer, nullptr); } +void ImageView::setImage(const uint8_t *data, size_t dataLength) { + if (data != m_data && dataLength != m_dataLength) { + m_data = data; + m_dataLength = dataLength; + markRectAsDirty(bounds()); + } +} + void ImageView::setImage(const Image * image) { if (image != m_image) { m_image = image;