From ca4b5d511a4a3e9c12929c7ea93b71dbe1478d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 12 Dec 2016 11:58:04 +0100 Subject: [PATCH] [apps/graph/graph] Optimize the redrawing of the graph view when only the cursor has changed Change-Id: I34fbe3d4599474ae821f508078d5236362260dc0 --- apps/curve_view.cpp | 47 ++++++++++++++++++++------------- apps/curve_view.h | 6 ++--- apps/graph/graph/graph_view.cpp | 33 +++++++++++++++++++---- apps/graph/graph/graph_view.h | 1 + 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/apps/curve_view.cpp b/apps/curve_view.cpp index d28e36f90..c204e6e9c 100644 --- a/apps/curve_view.cpp +++ b/apps/curve_view.cpp @@ -66,7 +66,10 @@ void CurveView::drawLabels(Axis axis, KDContext * ctx, KDRect rect) const { if (x == 0.0f) { origin = KDPoint(floatToPixel(Axis::Horizontal, 0.0f) + k_labelMargin, floatToPixel(Axis::Vertical, 0.0f) + k_labelMargin); } - ctx->blendString(label(axis, i++), origin, KDColorBlack); + if (rect.intersects(KDRect(origin, KDText::stringSize(label(axis, i))))) { + ctx->blendString(label(axis, i), origin, KDColorBlack); + } + i++; } } @@ -87,7 +90,9 @@ void CurveView::drawLine(KDContext * ctx, KDRect rect, Axis axis, float coordina ); break; } - ctx->fillRect(lineRect, color); + if (rect.intersects(lineRect)) { + ctx->fillRect(lineRect, color); + } } void CurveView::drawAxes(Axis axis, KDContext * ctx, KDRect rect) const { @@ -125,31 +130,38 @@ const uint8_t stampMask[stampSize+1][stampSize+1] = { #endif constexpr static int k_maxNumberOfIterations = 10; +constexpr static int k_resolution = 320.0f; void CurveView::drawExpression(Expression * expression, KDColor color, KDContext * ctx, KDRect rect) const { float xMin = min(Axis::Horizontal); float xMax = max(Axis::Horizontal); - float xStep = (xMax-xMin)/320.0f; - for (float x = xMin; x < xMax; x += xStep) { + float xStep = (xMax-xMin)/k_resolution; + float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); + float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); + for (float x = rectMin; x < rectMax; x += xStep) { float y = evaluateExpressionAtAbscissa(expression, x); float pxf = floatToPixel(Axis::Horizontal, x); float pyf = floatToPixel(Axis::Vertical, y); - stampAtLocation(pxf, pyf, color, ctx); + stampAtLocation(pxf, pyf, color, ctx, rect); if (x > xMin) { - jointDots(expression, x - xStep, evaluateExpressionAtAbscissa(expression, x-xStep), x, y, color, k_maxNumberOfIterations, ctx); + jointDots(expression, x - xStep, evaluateExpressionAtAbscissa(expression, x-xStep), x, y, color, k_maxNumberOfIterations, ctx, rect); } } } -void CurveView::stampAtLocation(float pxf, float pyf, KDColor color, KDContext * ctx) const { +void CurveView::stampAtLocation(float pxf, float pyf, KDColor color, KDContext * ctx, KDRect rect) const { // We avoid drawing when no part of the stamp is visible if (pyf < -stampSize || pyf > pixelLength(Axis::Vertical)+stampSize) { return; } - uint8_t shiftedMask[stampSize][stampSize]; - KDColor workingBuffer[stampSize*stampSize]; KDCoordinate px = pxf; KDCoordinate py = pyf; + KDRect stampRect(px-circleDiameter/2, py-circleDiameter/2, stampSize, stampSize); + if (!rect.intersects(stampRect)) { + return; + } + uint8_t shiftedMask[stampSize][stampSize]; + KDColor workingBuffer[stampSize*stampSize]; float dx = pxf - floorf(pxf); float dy = pyf - floorf(pyf); /* TODO: this could be optimized by precomputing 10 or 100 shifted masks. The @@ -161,11 +173,10 @@ void CurveView::stampAtLocation(float pxf, float pyf, KDColor color, KDContext * + (1.0f-dx) * (stampMask[i][j+1]*dy + stampMask[i+1][j+1]*(1.0f-dy)); } } - KDRect stampRect(px-circleDiameter/2, py-circleDiameter/2, stampSize, stampSize); ctx->blendRectWithMask(stampRect, color, (const uint8_t *)shiftedMask, workingBuffer); } -void CurveView::jointDots(Expression * expression, float x, float y, float u, float v, KDColor color, int maxNumberOfRecursion, KDContext * ctx) const { +void CurveView::jointDots(Expression * expression, float x, float y, float u, float v, KDColor color, int maxNumberOfRecursion, KDContext * ctx, KDRect rect) const { float pyf = floatToPixel(Axis::Vertical, y); float pvf = floatToPixel(Axis::Vertical, v); // No need to draw if both dots are outside visible area @@ -191,25 +202,25 @@ void CurveView::jointDots(Expression * expression, float x, float y, float u, fl * can draw a 'straight' line between the two */ float pxf = floatToPixel(Axis::Horizontal, x); float puf = floatToPixel(Axis::Horizontal, u); - straightJoinDots(pxf, pyf, puf, pvf, color, ctx); + straightJoinDots(pxf, pyf, puf, pvf, color, ctx, rect); return; } float pcxf = floatToPixel(Axis::Horizontal, cx); float pcyf = floatToPixel(Axis::Vertical, cy); if (maxNumberOfRecursion > 0) { - stampAtLocation(pcxf, pcyf, color, ctx); - jointDots(expression, x, y, cx, cy, color, maxNumberOfRecursion-1, ctx); - jointDots(expression, cx, cy, u, v, color, maxNumberOfRecursion-1, ctx); + stampAtLocation(pcxf, pcyf, color, ctx, rect); + jointDots(expression, x, y, cx, cy, color, maxNumberOfRecursion-1, ctx, rect); + jointDots(expression, cx, cy, u, v, color, maxNumberOfRecursion-1, ctx, rect); } } -void CurveView::straightJoinDots(float pxf, float pyf, float puf, float pvf, KDColor color, KDContext * ctx) const { +void CurveView::straightJoinDots(float pxf, float pyf, float puf, float pvf, KDColor color, KDContext * ctx, KDRect rect) const { if (pyf < pvf) { for (float pnf = pyf; pnfxGridUnit() : m_graphWindow->yGridUnit()); } @@ -87,16 +92,21 @@ void GraphView::initCursorPosition() { } void GraphView::moveCursorHorizontally(KDCoordinate xOffset) { + markRectAsDirty(KDRect(KDPoint(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition)- k_cursorSize/2), k_cursorSize, k_cursorSize)); m_xCursorPosition = m_xCursorPosition + xOffset; float x = pixelToFloat(Axis::Horizontal, m_xCursorPosition); Function * f = m_functionStore->activeFunctionAtIndex(m_indexFunctionSelectedByCursor); float y = f->evaluateAtAbscissa(x, m_evaluateContext); float xMargin = pixelToFloat(Axis::Horizontal, k_cursorMarginToBorder) - pixelToFloat(Axis::Horizontal, 0); float yMargin = pixelToFloat(Axis::Vertical, 0) - pixelToFloat(Axis::Vertical, k_cursorMarginToBorder); - m_graphWindow->panToMakePointVisible(x, y, xMargin, yMargin); + bool windowHasMoved = m_graphWindow->panToMakePointVisible(x, y, xMargin, yMargin); m_xCursorPosition = floatToPixel(Axis::Horizontal, x); m_yCursorPosition = floatToPixel(Axis::Vertical, y); - reload(); + if (windowHasMoved) { + reload(); + } else { + reloadCursor(); + } } Function * GraphView::moveCursorVertically(int direction) { @@ -120,10 +130,15 @@ Function * GraphView::moveCursorVertically(int direction) { } float xMargin = pixelToFloat(Axis::Horizontal, k_cursorMarginToBorder) - pixelToFloat(Axis::Horizontal, 0); float yMargin = pixelToFloat(Axis::Vertical, 0) - pixelToFloat(Axis::Vertical, k_cursorMarginToBorder); - m_graphWindow->panToMakePointVisible(x, nextY, xMargin, yMargin); + bool windowHasMoved = m_graphWindow->panToMakePointVisible(x, nextY, xMargin, yMargin); + markRectAsDirty(KDRect(KDPoint(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition)- k_cursorSize/2), k_cursorSize, k_cursorSize)); m_xCursorPosition = floatToPixel(Axis::Horizontal, x); m_yCursorPosition = floatToPixel(Axis::Vertical, nextY); - reload(); + if (windowHasMoved) { + reload(); + } else { + reloadCursor(); + } return nextFunction; } @@ -149,10 +164,18 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { } void GraphView::drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const { + float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); + float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); + if (axis == Axis::Vertical) { + rectMax = pixelToFloat(Axis::Vertical, rect.top()); + rectMin = pixelToFloat(Axis::Vertical, rect.bottom()); + } float start = step*((int)(min(axis)/step)); Axis otherAxis = (axis == Axis::Horizontal) ? Axis::Vertical : Axis::Horizontal; for (float x =start; x < max(axis); x += step) { - drawLine(ctx, rect, otherAxis, x, color); + if (rectMin <= x && x <= rectMax) { + drawLine(ctx, rect, otherAxis, x, color); + } } } diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index 2842b97bd..7fd4da499 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -27,6 +27,7 @@ public: Context * context() const; int indexFunctionSelectedByCursor(); void reload(); + void reloadCursor(); private: constexpr static KDColor k_gridColor = KDColor::RGB24(0xEEEEEE); constexpr static KDCoordinate k_cursorSize = 9;