[apps/graph] Faster cursor scrolling on device

This commit is quite dirty but works well
This commit is contained in:
Léa Saviot
2019-09-06 16:27:52 +02:00
parent 2d9eeaedd6
commit e67160b878
18 changed files with 70 additions and 50 deletions

View File

@@ -8,7 +8,7 @@ using namespace Shared;
namespace Graph {
GraphView::GraphView(CartesianFunctionStore * functionStore, InteractiveCurveViewRange * graphRange,
CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) :
FunctionGraphView(graphRange, cursor, bannerView, cursorView),
m_functionStore(functionStore),
m_tangent(false)

View File

@@ -9,7 +9,7 @@ namespace Graph {
class GraphView : public Shared::FunctionGraphView {
public:
GraphView(CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * graphRange,
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView);
void reload() override;
void drawRect(KDContext * ctx, KDRect rect) const override;
void drawTangent(bool tangent) { m_tangent = tangent; }

View File

@@ -82,9 +82,9 @@ void GraphController::viewWillAppear() {
/* Since *m_selectedDotIndex is altered by initCursorParameters(),
* the following must absolutely come at the end. */
if (*m_selectedDotIndex >= 0) {
m_view.setCursorView(static_cast<View *>(&m_crossCursorView));
m_view.setCursorView(static_cast<Shared::CursorView *>(&m_crossCursorView));
} else {
m_view.setCursorView(static_cast<View *>(&m_roundCursorView));
m_view.setCursorView(static_cast<Shared::CursorView *>(&m_roundCursorView));
m_roundCursorView.setColor(Palette::DataColor[*m_selectedSeriesIndex]);
}
}

View File

@@ -8,7 +8,7 @@ using namespace Shared;
namespace Regression {
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, Shared::CursorView * cursorView) :
CurveView(store, cursor, bannerView, cursorView),
m_store(store),
m_xLabels{},

View File

@@ -9,7 +9,7 @@ namespace Regression {
class GraphView : public Shared::CurveView {
public:
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
char * label(Axis axis, int index) const override;

View File

@@ -6,7 +6,7 @@ using namespace Shared;
namespace Sequence {
GraphView::GraphView(SequenceStore * sequenceStore, InteractiveCurveViewRange * graphRange,
CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) :
FunctionGraphView(graphRange, cursor, bannerView, cursorView),
m_sequenceStore(sequenceStore)
{

View File

@@ -9,7 +9,7 @@ namespace Sequence {
class GraphView : public Shared::FunctionGraphView {
public:
GraphView(SequenceStore * sequenceStore, Shared::InteractiveCurveViewRange * graphRange,
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
SequenceStore * m_sequenceStore;

View File

@@ -19,7 +19,6 @@ app_shared_src = $(addprefix apps/shared/,\
buffer_function_title_cell.cpp \
buffer_text_view_with_text_field.cpp \
button_with_separator.cpp \
cursor_view.cpp \
curve_view.cpp \
curve_view_cursor.cpp \
editable_cell_table_view_controller.cpp \

View File

@@ -1,16 +0,0 @@
#include "cursor_view.h"
namespace Shared {
void CursorView::drawRect(KDContext * ctx, KDRect rect) const {
KDCoordinate width = bounds().width();
KDCoordinate height = bounds().height();
ctx->fillRect(KDRect((width-1)/2, 0, 1, height), KDColorBlack);
ctx->fillRect(KDRect(0, (height-1)/2, width, 1), KDColorBlack);
}
KDSize CursorView::minimalSizeForOptimalDisplay() const {
return KDSize(k_size, k_size);
}
}

View File

@@ -5,12 +5,9 @@
namespace Shared {
class CursorView : public TransparentView {
class CursorView : public View {
public:
void drawRect(KDContext * ctx, KDRect rect) const override;
KDSize minimalSizeForOptimalDisplay() const override;
private:
constexpr static KDCoordinate k_size = 19;
virtual void setCursorFrame(KDRect frame) { View::setFrame(frame); }
};
}

View File

@@ -16,7 +16,7 @@ static inline float minFloat(float x, float y) { return x < y ? x : y; }
static inline float maxFloat(float x, float y) { return x > y ? x : y; }
CurveView::CurveView(CurveViewRange * curveViewRange, CurveViewCursor * curveViewCursor, BannerView * bannerView,
View * cursorView, View * okView, bool displayBanner) :
CursorView * cursorView, View * okView, bool displayBanner) :
View(),
m_bannerView(bannerView),
m_curveViewCursor(curveViewCursor),
@@ -68,7 +68,7 @@ void CurveView::setCurveViewRange(CurveViewRange * curveViewRange) {
* might be identical to the previous one and in that case layoutSubviews will
* do nothing). */
void CurveView::setCursorView(View * cursorView) {
void CurveView::setCursorView(CursorView * cursorView) {
markRectAsDirty(cursorFrame());
m_cursorView = cursorView;
markRectAsDirty(cursorFrame());
@@ -709,7 +709,7 @@ void CurveView::stampAtLocation(KDContext * ctx, KDRect rect, float pxf, float p
void CurveView::layoutSubviews() {
if (m_curveViewCursor != nullptr && m_cursorView != nullptr) {
m_cursorView->setFrame(cursorFrame());
m_cursorView->setCursorFrame(cursorFrame());
}
if (m_bannerView != nullptr) {
m_bannerView->setFrame(bannerFrame());

View File

@@ -4,6 +4,7 @@
#include "banner_view.h"
#include "curve_view_range.h"
#include "curve_view_cursor.h"
#include "cursor_view.h"
#include <poincare/preferences.h>
#include <poincare/coordinate_2D.h>
#include <cmath>
@@ -24,15 +25,15 @@ public:
CurveView(CurveViewRange * curveViewRange = nullptr,
CurveViewCursor * curveViewCursor = nullptr,
BannerView * bannerView = nullptr,
View * cursorView = nullptr,
CursorView * cursorView = nullptr,
View * okView = nullptr,
bool displayBanner = true);
virtual void reload();
// When the main view is selected, the banner view is visible
bool isMainViewSelected() const;
void selectMainView(bool mainViewSelected);
View * cursorView() { return m_cursorView; }
void setCursorView(View * cursorView);
CursorView * cursorView() { return m_cursorView; }
void setCursorView(Shared::CursorView * cursorView);
View * bannerView() { return m_bannerView; }
void setBannerView(View * bannerView);
void setOkView(View * okView);
@@ -104,7 +105,7 @@ private:
float labelValueAtIndex(Axis axis, int i) const;
bool bannerIsVisible() const;
CurveViewRange * m_curveViewRange;
View * m_cursorView;
CursorView * m_cursorView;
View * m_okView;
bool m_forceOkDisplay;
bool m_mainViewSelected;

View File

@@ -7,7 +7,7 @@ using namespace Poincare;
namespace Shared {
FunctionGraphView::FunctionGraphView(InteractiveCurveViewRange * graphRange,
CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) :
CurveView(graphRange, cursor, bannerView, cursorView),
m_selectedRecord(),
m_highlightedStart(NAN),

View File

@@ -12,7 +12,7 @@ namespace Shared {
class FunctionGraphView : public CurveView {
public:
FunctionGraphView(InteractiveCurveViewRange * graphRange, CurveViewCursor * cursor,
BannerView * bannerView, View * cursorView);
BannerView * bannerView, CursorView * cursorView);
void drawRect(KDContext * ctx, KDRect rect) const override;
void setContext(Poincare::Context * context);
Poincare::Context * context() const;

View File

@@ -2,11 +2,6 @@
namespace Shared {
RoundCursorView::RoundCursorView(KDColor color) :
m_color(color)
{
}
static constexpr KDCoordinate cursorSize = 10;
static const uint8_t cursorMask[cursorSize][cursorSize] = {
{0xFF, 0xFF, 0xFF, 0xED, 0xB6, 0xB6, 0xED, 0xFF, 0xFF, 0xFF},
@@ -24,7 +19,10 @@ static const uint8_t cursorMask[cursorSize][cursorSize] = {
static KDColor s_cursorWorkingBuffer[cursorSize*cursorSize];
void RoundCursorView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->blendRectWithMask(bounds(), m_color, (const uint8_t *)cursorMask, s_cursorWorkingBuffer);
KDRect r = bounds();
ctx->getPixels(r, m_underneathPixelBuffer);
m_underneathPixelBufferLoaded = true;
ctx->blendRectWithMask(r, m_color, (const uint8_t *)cursorMask, s_cursorWorkingBuffer);
}
KDSize RoundCursorView::minimalSizeForOptimalDisplay() const {
@@ -36,4 +34,36 @@ void RoundCursorView::setColor(KDColor color) {
markRectAsDirty(bounds());
}
#define GRAPH_CURSOR_SPEEDUP 1
void RoundCursorView::setCursorFrame(KDRect f) {
#if GRAPH_CURSOR_SPEEDUP
/* TODO This is quite dirty (we are out of the dirty tracking and we assume
* the cursor is the upmost view) but it works well. */
if (m_frame == f) {
return;
}
const KDRect previousRelativeFrame = m_frame;
/* We want to avoid drawing the curve just because the cursor has been
* repositioned, as it is very slow for non cartesian curves.*/
if (m_underneathPixelBufferLoaded && !previousRelativeFrame.isEmpty()) {
const KDRect previousFrame = absoluteVisibleFrame();
// Erase the cursor
KDContext * ctx = KDIonContext::sharedContext();
ctx->setOrigin(previousFrame.origin());
ctx->setClippingRect(previousFrame);
ctx->fillRectWithPixels(KDRect(0,0,k_cursorSize, k_cursorSize), m_underneathPixelBuffer, s_cursorWorkingBuffer);
// Set the frame
m_frame = f;
// Draw the cursor
KDPoint translation = f.origin().translatedBy(previousRelativeFrame.origin().opposite());
ctx->setOrigin(previousFrame.origin().translatedBy(translation));
ctx->setClippingRect(previousFrame.translatedBy(translation));
drawRect(ctx, f);
return;
}
#endif
CursorView::setCursorFrame(f);
}
}

View File

@@ -1,18 +1,22 @@
#ifndef SHARED_ROUND_CURSOR_VIEW_H
#define SHARED_ROUND_CURSOR_VIEW_H
#include <escher.h>
#include "cursor_view.h"
namespace Shared {
class RoundCursorView : public TransparentView {
class RoundCursorView : public CursorView {
public:
RoundCursorView(KDColor color = KDColorBlack);
RoundCursorView(KDColor color = KDColorBlack) : m_color(color), m_underneathPixelBufferLoaded(false) {}
void drawRect(KDContext * ctx, KDRect rect) const override;
KDSize minimalSizeForOptimalDisplay() const override;
void setColor(KDColor color);
void setCursorFrame(KDRect frame) override;
private:
constexpr static int k_cursorSize = 10;
mutable KDColor m_underneathPixelBuffer[k_cursorSize*k_cursorSize];
KDColor m_color;
mutable bool m_underneathPixelBufferLoaded;
};
}

View File

@@ -2,12 +2,12 @@
#define SHARED_VERTICAL_CURSOR_VIEW_H
#include <escher.h>
#include "cursor_view.h"
namespace Shared {
class VerticalCursorView : public View {
class VerticalCursorView : public CursorView {
public:
using View::View;
void drawRect(KDContext * ctx, KDRect rect) const override;
KDSize minimalSizeForOptimalDisplay() const override;
};

View File

@@ -20,10 +20,15 @@ extern "C" {
class Window;
namespace Shared {
class RoundCursorView;
}
class View {
// We only want Window to be able to invoke View::redraw
friend class Window;
friend class TransparentView;
friend class Shared::RoundCursorView;
public:
View();
virtual ~View() {