From 1108ef21dbb677c64f90cf8a8f2afbef9eb87cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 16 May 2018 17:26:40 +0200 Subject: [PATCH] [calculation] Do not memoize the expression layouts but the expressions final height to avoid overflowing the heap. The expression layouts are kept in the cell which are fewer then the number of calculations --- apps/calculation/calculation.cpp | 74 ++++++++++++------------- apps/calculation/calculation.h | 11 ++-- apps/calculation/history_controller.cpp | 11 +--- apps/calculation/history_view_cell.cpp | 37 ++++++++++++- apps/calculation/history_view_cell.h | 4 ++ 5 files changed, 80 insertions(+), 57 deletions(-) diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 5839a50b0..f51dd5eae 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -11,20 +11,14 @@ Calculation::Calculation() : m_exactOutputText(), m_approximateOutputText(), m_input(nullptr), - m_inputLayout(nullptr), m_exactOutput(nullptr), - m_exactOutputLayout(nullptr), m_approximateOutput(nullptr), - m_approximateOutputLayout(nullptr), + m_height(-1), m_equalSign(EqualSign::Unknown) { } Calculation::~Calculation() { - if (m_inputLayout != nullptr) { - delete m_inputLayout; - m_inputLayout = nullptr; - } if (m_input != nullptr) { delete m_input; m_input = nullptr; @@ -33,18 +27,10 @@ Calculation::~Calculation() { delete m_exactOutput; m_exactOutput = nullptr; } - if (m_exactOutputLayout != nullptr) { - delete m_exactOutputLayout; - m_exactOutputLayout = nullptr; - } if (m_approximateOutput != nullptr) { delete m_approximateOutput; m_approximateOutput = nullptr; } - if (m_approximateOutputLayout != nullptr) { - delete m_approximateOutputLayout; - m_approximateOutputLayout = nullptr; - } } Calculation& Calculation::operator=(const Calculation& other) { @@ -78,6 +64,27 @@ void Calculation::setContent(const char * c, Context * context, Expression * ans m_approximateOutput->writeTextInBuffer(m_approximateOutputText, sizeof(m_approximateOutputText)); } +KDCoordinate Calculation::height(Context * context) { + if (m_height < 0) { + ExpressionLayout * inputLayout = createInputLayout(); + KDCoordinate inputHeight = inputLayout->size().height(); + delete inputLayout; + Poincare::ExpressionLayout * approximateLayout = createApproximateOutputLayout(context); + KDCoordinate approximateOutputHeight = approximateLayout->size().height(); + if (shouldOnlyDisplayApproximateOutput(context)) { + m_height = inputHeight+approximateOutputHeight; + } else { + Poincare::ExpressionLayout * exactLayout = createExactOutputLayout(context); + KDCoordinate exactOutputHeight = exactLayout->size().height(); + KDCoordinate outputHeight = max(exactLayout->baseline(), approximateLayout->baseline()) + max(exactOutputHeight-exactLayout->baseline(), approximateOutputHeight-approximateLayout->baseline()); + delete exactLayout; + m_height = inputHeight + outputHeight; + } + delete approximateLayout; + } + return m_height; +} + const char * Calculation::inputText() { return m_inputText; } @@ -97,11 +104,11 @@ Expression * Calculation::input() { return m_input; } -ExpressionLayout * Calculation::inputLayout() { - if (m_inputLayout == nullptr && input() != nullptr) { - m_inputLayout = input()->createLayout(PrintFloat::Mode::Decimal, Expression::ComplexFormat::Cartesian); +ExpressionLayout * Calculation::createInputLayout() { + if (input() != nullptr) { + return input()->createLayout(PrintFloat::Mode::Decimal, Expression::ComplexFormat::Cartesian); } - return m_inputLayout; + return nullptr; } bool Calculation::isEmpty() { @@ -123,26 +130,15 @@ void Calculation::tidy() { delete m_input; } m_input = nullptr; - if (m_inputLayout != nullptr) { - delete m_inputLayout; - } - m_inputLayout = nullptr; if (m_exactOutput != nullptr) { delete m_exactOutput; } m_exactOutput = nullptr; - if (m_exactOutputLayout != nullptr) { - delete m_exactOutputLayout; - } - m_exactOutputLayout = nullptr; if (m_approximateOutput != nullptr) { delete m_approximateOutput; } m_approximateOutput = nullptr; - if (m_approximateOutputLayout != nullptr) { - delete m_approximateOutputLayout; - } - m_approximateOutputLayout = nullptr; + m_height = -1; m_equalSign = EqualSign::Unknown; } @@ -155,11 +151,11 @@ Expression * Calculation::exactOutput(Context * context) { return m_exactOutput; } -ExpressionLayout * Calculation::exactOutputLayout(Context * context) { - if (m_exactOutputLayout == nullptr && exactOutput(context) != nullptr) { - m_exactOutputLayout = exactOutput(context)->createLayout(); +ExpressionLayout * Calculation::createExactOutputLayout(Context * context) { + if (exactOutput(context) != nullptr) { + return exactOutput(context)->createLayout(); } - return m_exactOutputLayout; + return nullptr; } Expression * Calculation::approximateOutput(Context * context) { @@ -177,11 +173,11 @@ Expression * Calculation::approximateOutput(Context * context) { return m_approximateOutput; } -ExpressionLayout * Calculation::approximateOutputLayout(Context * context) { - if (m_approximateOutputLayout == nullptr && approximateOutput(context) != nullptr) { - m_approximateOutputLayout = approximateOutput(context)->createLayout(); +ExpressionLayout * Calculation::createApproximateOutputLayout(Context * context) { + if (approximateOutput(context) != nullptr) { + return approximateOutput(context)->createLayout(); } - return m_approximateOutputLayout; + return nullptr; } bool Calculation::shouldOnlyDisplayApproximateOutput(Context * context) { diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index 8a224cd69..68f692876 100644 --- a/apps/calculation/calculation.h +++ b/apps/calculation/calculation.h @@ -24,15 +24,16 @@ public: /* c.reset() is the equivalent of c = Calculation() without copy assingment. */ void reset(); void setContent(const char * c, Poincare::Context * context, Poincare::Expression * ansExpression); + KDCoordinate height(Poincare::Context * context); const char * inputText(); const char * exactOutputText(); const char * approximateOutputText(); Poincare::Expression * input(); - Poincare::ExpressionLayout * inputLayout(); + Poincare::ExpressionLayout * createInputLayout(); Poincare::Expression * approximateOutput(Poincare::Context * context); Poincare::Expression * exactOutput(Poincare::Context * context); - Poincare::ExpressionLayout * exactOutputLayout(Poincare::Context * context); - Poincare::ExpressionLayout * approximateOutputLayout(Poincare::Context * context); + Poincare::ExpressionLayout * createExactOutputLayout(Poincare::Context * context); + Poincare::ExpressionLayout * createApproximateOutputLayout(Poincare::Context * context); bool isEmpty(); void tidy(); bool shouldOnlyDisplayApproximateOutput(Poincare::Context * context); @@ -46,11 +47,9 @@ private: char m_exactOutputText[k_printedExpressionSize]; char m_approximateOutputText[k_printedExpressionSize]; Poincare::Expression * m_input; - Poincare::ExpressionLayout * m_inputLayout; Poincare::Expression * m_exactOutput; - Poincare::ExpressionLayout * m_exactOutputLayout; Poincare::Expression * m_approximateOutput; - Poincare::ExpressionLayout * m_approximateOutputLayout; + KDCoordinate m_height; EqualSign m_equalSign; }; diff --git a/apps/calculation/history_controller.cpp b/apps/calculation/history_controller.cpp index 90bffc092..a30e82b8c 100644 --- a/apps/calculation/history_controller.cpp +++ b/apps/calculation/history_controller.cpp @@ -158,17 +158,8 @@ KDCoordinate HistoryController::rowHeight(int j) { return 0; } Calculation * calculation = m_calculationStore->calculationAtIndex(j); - KDCoordinate inputHeight = calculation->inputLayout()->size().height(); App * calculationApp = (App *)app(); - Poincare::ExpressionLayout * approximateLayout = calculation->approximateOutputLayout(calculationApp->localContext()); - KDCoordinate approximateOutputHeight = approximateLayout->size().height(); - if (calculation->shouldOnlyDisplayApproximateOutput(calculationApp->localContext())) { - return inputHeight + approximateOutputHeight + 3*HistoryViewCell::k_digitVerticalMargin; - } - Poincare::ExpressionLayout * exactLayout = calculation->exactOutputLayout(calculationApp->localContext()); - KDCoordinate exactOutputHeight = exactLayout->size().height(); - KDCoordinate outputHeight = max(exactLayout->baseline(), approximateLayout->baseline()) + max(exactOutputHeight-exactLayout->baseline(), approximateOutputHeight-approximateLayout->baseline()); - return inputHeight + outputHeight + 3*HistoryViewCell::k_digitVerticalMargin; + return calculation->height(calculationApp->localContext()) + 3*HistoryViewCell::k_digitVerticalMargin; } KDCoordinate HistoryController::cumulatedHeightFromIndex(int j) { diff --git a/apps/calculation/history_view_cell.cpp b/apps/calculation/history_view_cell.cpp index 3b901f486..7e38a02f8 100644 --- a/apps/calculation/history_view_cell.cpp +++ b/apps/calculation/history_view_cell.cpp @@ -9,12 +9,30 @@ namespace Calculation { HistoryViewCell::HistoryViewCell(Responder * parentResponder) : Responder(parentResponder), + m_inputLayout(nullptr), + m_exactOutputLayout(nullptr), + m_approximateOutputLayout(nullptr), m_inputView(this), m_scrollableOutputView(this), m_selectedSubviewType(HistoryViewCell::SubviewType::Output) { } +HistoryViewCell::~HistoryViewCell() { + if (m_inputLayout != nullptr) { + delete m_inputLayout; + m_inputLayout = nullptr; + } + if (m_exactOutputLayout != nullptr) { + delete m_exactOutputLayout; + m_exactOutputLayout = nullptr; + } + if (m_approximateOutputLayout != nullptr) { + delete m_approximateOutputLayout; + m_approximateOutputLayout = nullptr; + } +} + OutputExpressionsView * HistoryViewCell::outputView() { return m_scrollableOutputView.outputView(); @@ -83,12 +101,27 @@ void HistoryViewCell::layoutSubviews() { } void HistoryViewCell::setCalculation(Calculation * calculation) { - m_inputView.setExpressionLayout(calculation->inputLayout()); + if (m_inputLayout) { + delete m_inputLayout; + } + m_inputLayout = calculation->createInputLayout(); + m_inputView.setExpressionLayout(m_inputLayout); App * calculationApp = (App *)app(); /* Both output expressions have to be updated at the same time. The * outputView points to deleted layouts and a call to * outputView()->layoutSubviews() is going to fail. */ - Poincare::ExpressionLayout * outputExpressions[2] = {calculation->approximateOutputLayout(calculationApp->localContext()), calculation->shouldOnlyDisplayApproximateOutput(calculationApp->localContext()) ? nullptr : calculation->exactOutputLayout(calculationApp->localContext())}; + if (m_exactOutputLayout) { + delete m_exactOutputLayout; + m_exactOutputLayout = nullptr; + } + if (!calculation->shouldOnlyDisplayApproximateOutput(calculationApp->localContext())) { + m_exactOutputLayout = calculation->createExactOutputLayout(calculationApp->localContext()); + } + if (m_approximateOutputLayout) { + delete m_approximateOutputLayout; + } + m_approximateOutputLayout = calculation->createApproximateOutputLayout(calculationApp->localContext()); + Poincare::ExpressionLayout * outputExpressions[2] = {m_approximateOutputLayout, m_exactOutputLayout}; m_scrollableOutputView.outputView()->setExpressions(outputExpressions); I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(calculationApp->localContext()) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual; m_scrollableOutputView.outputView()->setEqualMessage(equalMessage); diff --git a/apps/calculation/history_view_cell.h b/apps/calculation/history_view_cell.h index d6ca3c1d5..d99063038 100644 --- a/apps/calculation/history_view_cell.h +++ b/apps/calculation/history_view_cell.h @@ -15,6 +15,7 @@ public: Output }; HistoryViewCell(Responder * parentResponder); + ~HistoryViewCell(); void reloadCell() override; void reloadScroll(); void setEven(bool even) override; @@ -35,6 +36,9 @@ public: OutputExpressionsView * outputView(); private: constexpr static KDCoordinate k_resultWidth = 80; + Poincare::ExpressionLayout * m_inputLayout; + Poincare::ExpressionLayout * m_exactOutputLayout; + Poincare::ExpressionLayout * m_approximateOutputLayout; ScrollableExpressionView m_inputView; ScrollableOutputExpressionsView m_scrollableOutputView; SubviewType m_selectedSubviewType;