From b5520fcc03429502160346ad2ac0fbc039bd7d66 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Tue, 28 May 2019 18:58:13 +0200 Subject: [PATCH 1/3] [ion] Add Shift[1-9] events --- ion/include/ion/events.h | 12 ++++++++++++ ion/include/ion/keyboard/layout_B2/layout_events.h | 6 +++--- ion/include/ion/keyboard/layout_B3/layout_events.h | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index ed70f4968..1ce72c76d 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -139,6 +139,18 @@ constexpr Event Equal = Event::ShiftKey(Keyboard::Key::Pi); constexpr Event Lower = Event::ShiftKey(Keyboard::Key::Sqrt); constexpr Event Greater = Event::ShiftKey(Keyboard::Key::Square); +constexpr Event ShiftSeven = Event::ShiftKey(Keyboard::Key::Seven); +constexpr Event ShiftEight = Event::ShiftKey(Keyboard::Key::Eight); +constexpr Event ShiftNine = Event::ShiftKey(Keyboard::Key::Nine); + +constexpr Event ShiftFour = Event::ShiftKey(Keyboard::Key::Four); +constexpr Event ShiftFive = Event::ShiftKey(Keyboard::Key::Five); +constexpr Event ShiftSix = Event::ShiftKey(Keyboard::Key::Six); + +constexpr Event ShiftOne = Event::ShiftKey(Keyboard::Key::One); +constexpr Event ShiftTwo = Event::ShiftKey(Keyboard::Key::Two); +constexpr Event ShiftThree = Event::ShiftKey(Keyboard::Key::Three); + // Alpha constexpr Event Colon = Event::AlphaKey(Keyboard::Key::XNT); diff --git a/ion/include/ion/keyboard/layout_B2/layout_events.h b/ion/include/ion/keyboard/layout_B2/layout_events.h index 800cbc8d0..a0d877cd5 100644 --- a/ion/include/ion/keyboard/layout_B2/layout_events.h +++ b/ion/include/ion/keyboard/layout_B2/layout_events.h @@ -25,9 +25,9 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), U(), U(), U(), U(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), diff --git a/ion/include/ion/keyboard/layout_B3/layout_events.h b/ion/include/ion/keyboard/layout_B3/layout_events.h index 03898f223..1783ff7a3 100644 --- a/ion/include/ion/keyboard/layout_B3/layout_events.h +++ b/ion/include/ion/keyboard/layout_B3/layout_events.h @@ -25,9 +25,9 @@ static constexpr EventData s_dataForEvent[4*Event::PageSize] = { U(), U(), TL(), TL(), TL(), TL(), T("["), T("]"), T("{"), T("}"), T("_"), T("→"), T("asin(\x11)"), T("acos(\x11)"), T("atan(\x11)"), T("="), T("<"), T(">"), - U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), - U(), U(), U(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), + TL(), TL(), TL(), U(), U(), U(), U(), U(), U(), U(), U(), U(), // Alpha U(), U(), U(), U(), U(), U(), From 9a5bfb944d3a63507b293b8ee635b95fd5a16de5 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Sat, 30 Mar 2019 17:05:04 +0000 Subject: [PATCH 2/3] [kandinsky] Basics of post-processing --- escher/include/escher/window.h | 2 +- kandinsky/Makefile | 4 + kandinsky/include/kandinsky.h | 4 + kandinsky/include/kandinsky/color.h | 1 + kandinsky/include/kandinsky/context.h | 14 ++- kandinsky/include/kandinsky/ion_context.h | 31 ++++++- .../include/kandinsky/postprocess_context.h | 20 +++++ .../kandinsky/postprocess_gamma_context.h | 19 +++++ .../kandinsky/postprocess_invert_context.h | 15 ++++ .../kandinsky/postprocess_zoom_context.h | 20 +++++ kandinsky/src/ion_context.cpp | 44 +++++++++- kandinsky/src/postprocess_context.cpp | 40 +++++++++ kandinsky/src/postprocess_gamma_context.cpp | 85 +++++++++++++++++++ kandinsky/src/postprocess_invert_context.cpp | 28 ++++++ kandinsky/src/postprocess_zoom_context.cpp | 53 ++++++++++++ 15 files changed, 368 insertions(+), 12 deletions(-) create mode 100644 kandinsky/include/kandinsky/postprocess_context.h create mode 100644 kandinsky/include/kandinsky/postprocess_gamma_context.h create mode 100644 kandinsky/include/kandinsky/postprocess_invert_context.h create mode 100644 kandinsky/include/kandinsky/postprocess_zoom_context.h create mode 100644 kandinsky/src/postprocess_context.cpp create mode 100644 kandinsky/src/postprocess_gamma_context.cpp create mode 100644 kandinsky/src/postprocess_invert_context.cpp create mode 100644 kandinsky/src/postprocess_zoom_context.cpp diff --git a/escher/include/escher/window.h b/escher/include/escher/window.h index 931f07e3e..7930d64d2 100644 --- a/escher/include/escher/window.h +++ b/escher/include/escher/window.h @@ -6,7 +6,7 @@ class Window : public View { public: Window() : m_contentView(nullptr) {} - void redraw(bool force = false); + virtual void redraw(bool force = false); void setContentView(View * contentView); protected: #if ESCHER_VIEW_LOGGING diff --git a/kandinsky/Makefile b/kandinsky/Makefile index 7aaf9fca2..dfac55922 100644 --- a/kandinsky/Makefile +++ b/kandinsky/Makefile @@ -12,6 +12,10 @@ kandinsky_src += $(addprefix kandinsky/src/,\ framebuffer_context.cpp \ ion_context.cpp \ point.cpp \ + postprocess_context.cpp \ + postprocess_gamma_context.cpp \ + postprocess_invert_context.cpp \ + postprocess_zoom_context.cpp \ rect.cpp \ ) diff --git a/kandinsky/include/kandinsky.h b/kandinsky/include/kandinsky.h index bc3d951c7..26dd0be7e 100644 --- a/kandinsky/include/kandinsky.h +++ b/kandinsky/include/kandinsky.h @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include #include #include diff --git a/kandinsky/include/kandinsky/color.h b/kandinsky/include/kandinsky/color.h index a416bd2d7..8e1cafa50 100644 --- a/kandinsky/include/kandinsky/color.h +++ b/kandinsky/include/kandinsky/color.h @@ -32,6 +32,7 @@ public: } static KDColor blend(KDColor first, KDColor second, uint8_t alpha); + KDColor invert() const { return KDColor(~m_value); } operator uint16_t() const { return m_value; } private: constexpr KDColor(uint16_t value) : m_value(value) {} diff --git a/kandinsky/include/kandinsky/context.h b/kandinsky/include/kandinsky/context.h index 684be6cf3..bcfc4ee74 100644 --- a/kandinsky/include/kandinsky/context.h +++ b/kandinsky/include/kandinsky/context.h @@ -5,10 +5,15 @@ #include #include +class KDPostProcessContext; + class KDContext { + friend KDPostProcessContext; public: - void setOrigin(KDPoint origin); - void setClippingRect(KDRect clippingRect); + KDPoint origin() const { return m_origin; } + KDRect clippingRect() const { return m_clippingRect; } + virtual void setOrigin(KDPoint origin); + virtual void setClippingRect(KDRect clippingRect); // Pixel manipulation void setPixel(KDPoint p, KDColor c); @@ -28,11 +33,12 @@ public: void fillRectWithPixels(KDRect rect, const KDColor * pixels, KDColor * workingBuffer); void blendRectWithMask(KDRect rect, KDColor color, const uint8_t * mask, KDColor * workingBuffer); void strokeRect(KDRect rect, KDColor color); -protected: - KDContext(KDPoint origin, KDRect clippingRect); + virtual void pushRect(KDRect, const KDColor * pixels) = 0; virtual void pushRectUniform(KDRect rect, KDColor color) = 0; virtual void pullRect(KDRect rect, KDColor * pixels) = 0; +protected: + KDContext(KDPoint origin, KDRect clippingRect); private: KDRect absoluteFillRect(KDRect rect); KDPoint pushOrPullString(const char * text, KDPoint p, const KDFont * font, KDColor textColor, KDColor backgroundColor, int maxByteLength, bool push, int * result = nullptr); diff --git a/kandinsky/include/kandinsky/ion_context.h b/kandinsky/include/kandinsky/ion_context.h index 42eb738ad..5cfd6cd9e 100644 --- a/kandinsky/include/kandinsky/ion_context.h +++ b/kandinsky/include/kandinsky/ion_context.h @@ -2,15 +2,38 @@ #define KANDINSKY_ION_CONTEXT_H #include +#include +#include +#include -class KDIonContext : public KDContext { +class KDRealIonContext : public KDContext { public: - static KDIonContext * sharedContext(); -private: - KDIonContext(); + KDRealIonContext(); void pushRect(KDRect rect, const KDColor * pixels) override; void pushRectUniform(KDRect rect, KDColor color) override; void pullRect(KDRect rect, KDColor * pixels) override; }; +class KDIonContext : public KDContext { +public: + static KDIonContext * sharedContext(); + void updatePostProcessingEffects(); + + KDPostProcessInvertContext invert; + KDPostProcessZoomContext zoom; + KDPostProcessGammaContext gamma; + bool invertEnabled; + bool zoomEnabled; + bool zoomInhibit; + bool gammaEnabled; + int zoomPosition; +private: + KDIonContext(); + void pushRect(KDRect rect, const KDColor * pixels) override; + void pushRectUniform(KDRect rect, KDColor color) override; + void pullRect(KDRect rect, KDColor * pixels) override; + KDContext *rootContext; + KDRealIonContext m_realContext; +}; + #endif diff --git a/kandinsky/include/kandinsky/postprocess_context.h b/kandinsky/include/kandinsky/postprocess_context.h new file mode 100644 index 000000000..7c1ed6aeb --- /dev/null +++ b/kandinsky/include/kandinsky/postprocess_context.h @@ -0,0 +1,20 @@ +#ifndef KANDINSKY_POSTPROCESS_CONTEXT_H +#define KANDINSKY_POSTPROCESS_CONTEXT_H + +#include + +class KDPostProcessContext : public KDContext { +public: + virtual void setOrigin(KDPoint origin) override; + virtual void setClippingRect(KDRect clippingRect) override; + void setTarget(KDContext * context); +protected: + KDPostProcessContext(); + virtual void pushRect(KDRect rect, const KDColor * pixels) override; + virtual void pushRectUniform(KDRect rect, KDColor color) override; + virtual void pullRect(KDRect rect, KDColor * pixels) override; +private: + KDContext * m_target; +}; + +#endif diff --git a/kandinsky/include/kandinsky/postprocess_gamma_context.h b/kandinsky/include/kandinsky/postprocess_gamma_context.h new file mode 100644 index 000000000..c3195f2ff --- /dev/null +++ b/kandinsky/include/kandinsky/postprocess_gamma_context.h @@ -0,0 +1,19 @@ +#ifndef KANDINSKY_POSTPROCESS_GAMMA_CONTEXT_H +#define KANDINSKY_POSTPROCESS_GAMMA_CONTEXT_H + +#include + +class KDPostProcessGammaContext : public KDPostProcessContext { +public: + KDPostProcessGammaContext(); + void gamma(float& red, float& green, float& blue); + void gamma(int& red, int& green, int& blue); + void setGamma(int red, int green, int blue); +private: + void pushRect(KDRect rect, const KDColor * pixels) override; + void pushRectUniform(KDRect rect, KDColor color) override; + void pullRect(KDRect rect, KDColor * pixels) override; + int m_redGamma, m_greenGamma, m_blueGamma; +}; + +#endif diff --git a/kandinsky/include/kandinsky/postprocess_invert_context.h b/kandinsky/include/kandinsky/postprocess_invert_context.h new file mode 100644 index 000000000..bc976fcc5 --- /dev/null +++ b/kandinsky/include/kandinsky/postprocess_invert_context.h @@ -0,0 +1,15 @@ +#ifndef KANDINSKY_POSTPROCESS_INVERT_CONTEXT_H +#define KANDINSKY_POSTPROCESS_INVERT_CONTEXT_H + +#include + +class KDPostProcessInvertContext : public KDPostProcessContext { +public: + KDPostProcessInvertContext() = default; +private: + void pushRect(KDRect rect, const KDColor * pixels) override; + void pushRectUniform(KDRect rect, KDColor color) override; + void pullRect(KDRect rect, KDColor * pixels) override; +}; + +#endif diff --git a/kandinsky/include/kandinsky/postprocess_zoom_context.h b/kandinsky/include/kandinsky/postprocess_zoom_context.h new file mode 100644 index 000000000..028c5bdaa --- /dev/null +++ b/kandinsky/include/kandinsky/postprocess_zoom_context.h @@ -0,0 +1,20 @@ +#ifndef KANDINSKY_POSTPROCESS_ZOOM_CONTEXT_H +#define KANDINSKY_POSTPROCESS_ZOOM_CONTEXT_H + +#include + +class KDPostProcessZoomContext : public KDPostProcessContext { +public: + KDPostProcessZoomContext(); + KDRect viewingArea() const { return m_viewingArea; } + void setViewingArea(KDRect viewingArea) { m_viewingArea = viewingArea; } + KDRect targetArea() const { return m_targetArea; } + void setTargetArea(KDRect targetArea) { m_targetArea = targetArea; } +private: + void pushRect(KDRect rect, const KDColor * pixels) override; + void pushRectUniform(KDRect rect, KDColor color) override; + void pullRect(KDRect rect, KDColor * pixels) override; + KDRect m_viewingArea, m_targetArea; +}; + +#endif diff --git a/kandinsky/src/ion_context.cpp b/kandinsky/src/ion_context.cpp index ee7fcb5af..ee4e1edd4 100644 --- a/kandinsky/src/ion_context.cpp +++ b/kandinsky/src/ion_context.cpp @@ -1,11 +1,40 @@ #include #include +KDRealIonContext::KDRealIonContext() : KDContext(KDPointZero, KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)) {} +void KDRealIonContext::pushRect(KDRect rect, const KDColor * pixels) { + Ion::Display::pushRect(rect, pixels); +} +void KDRealIonContext::pushRectUniform(KDRect rect, KDColor color) { + Ion::Display::pushRectUniform(rect, color); +} +void KDRealIonContext::pullRect(KDRect rect, KDColor * pixels) { + Ion::Display::pullRect(rect, pixels); +} + KDIonContext * KDIonContext::sharedContext() { static KDIonContext context; return &context; } +void KDIonContext::updatePostProcessingEffects() { + rootContext = &m_realContext; + if (invertEnabled) { + invert.setTarget(rootContext); + rootContext = &invert; + } + if (zoomEnabled && !zoomInhibit) { + zoom.setTarget(rootContext); + zoom.setTargetArea(KDRect(0,0,320,240)); + zoom.setViewingArea(KDRect(80*(zoomPosition%3),120-60*(zoomPosition/3),160,120)); + rootContext = &zoom; + } + if (gammaEnabled) { + gamma.setTarget(rootContext); + rootContext = γ + } +} + KDIonContext::KDIonContext() : KDContext(KDPointZero, KDRect(0, 0, Ion::Display::Width, Ion::Display::Height)) @@ -13,13 +42,22 @@ KDContext(KDPointZero, } void KDIonContext::pushRect(KDRect rect, const KDColor * pixels) { - Ion::Display::pushRect(rect, pixels); + if (!rootContext) { + rootContext = &m_realContext; + } + rootContext->pushRect(rect, pixels); } void KDIonContext::pushRectUniform(KDRect rect, KDColor color) { - Ion::Display::pushRectUniform(rect, color); + if (!rootContext) { + rootContext = &m_realContext; + } + rootContext->pushRectUniform(rect, color); } void KDIonContext::pullRect(KDRect rect, KDColor * pixels) { - Ion::Display::pullRect(rect, pixels); + if (!rootContext) { + rootContext = &m_realContext; + } + rootContext->pullRect(rect, pixels); } diff --git a/kandinsky/src/postprocess_context.cpp b/kandinsky/src/postprocess_context.cpp new file mode 100644 index 000000000..db7487546 --- /dev/null +++ b/kandinsky/src/postprocess_context.cpp @@ -0,0 +1,40 @@ +#include +#include + +KDPostProcessContext::KDPostProcessContext() : +KDContext(KDPointZero, KDRectZero), +m_target(nullptr) +{ +} + +void KDPostProcessContext::setOrigin(KDPoint origin) { + KDContext::setOrigin(origin); + assert(m_target); + m_target->setOrigin(origin); +} + +void KDPostProcessContext::setClippingRect(KDRect clippingRect) { + KDContext::setClippingRect(clippingRect); + assert(m_target); + m_target->setClippingRect(clippingRect); +} + +void KDPostProcessContext::setTarget(KDContext * target) +{ + m_target = target; +} + +void KDPostProcessContext::pushRect(KDRect rect, const KDColor * pixels) +{ + m_target->pushRect(rect, pixels); +} + +void KDPostProcessContext::pushRectUniform(KDRect rect, KDColor color) +{ + m_target->pushRectUniform(rect, color); +} + +void KDPostProcessContext::pullRect(KDRect rect, KDColor * pixels) +{ + m_target->pullRect(rect, pixels); +} diff --git a/kandinsky/src/postprocess_gamma_context.cpp b/kandinsky/src/postprocess_gamma_context.cpp new file mode 100644 index 000000000..6a75e60db --- /dev/null +++ b/kandinsky/src/postprocess_gamma_context.cpp @@ -0,0 +1,85 @@ +#include +#include +#include + +constexpr int MaxGammaStates = 7; +constexpr float MaxGammaGamut = 0.75; + +constexpr float toGamma(int gamma) { + return 1.f / (1 + (float(gamma) / MaxGammaStates * MaxGammaGamut)); +} + +constexpr int clampGamma(int gamma) { + return gamma < -MaxGammaStates ? -MaxGammaStates : (gamma > MaxGammaStates ? MaxGammaStates : gamma); +} + +KDPostProcessGammaContext::KDPostProcessGammaContext() : + m_redGamma(0), m_greenGamma(0), m_blueGamma(0) {} + +void KDPostProcessGammaContext::gamma(int& red, int& green, int& blue) { + red = m_redGamma; + green = m_greenGamma; + blue = m_blueGamma; +} + +void KDPostProcessGammaContext::gamma(float& red, float& green, float& blue) { + red = (m_redGamma + MaxGammaStates) / float(MaxGammaStates*2); + green = (m_greenGamma + MaxGammaStates) / float(MaxGammaStates*2); + blue = (m_blueGamma + MaxGammaStates) / float(MaxGammaStates*2); +} + +void KDPostProcessGammaContext::setGamma(int red, int green, int blue) { + m_redGamma = clampGamma(red); + m_greenGamma = clampGamma(green); + m_blueGamma = clampGamma(blue); +} + +void KDPostProcessGammaContext::pushRect(KDRect rect, const KDColor * pixels) { + const float redGamma = toGamma(m_redGamma); + const float greenGamma = toGamma(m_greenGamma); + const float blueGamma = toGamma(m_blueGamma); + KDColor workingBuffer[rect.width()]; + + for (KDCoordinate y = 0; y < rect.height(); y++) { + KDRect workingRect(rect.x(), rect.y()+y, rect.width(), 1); + + for (KDCoordinate x = 0; x < rect.width(); x++) { + const KDColor color = pixels[y*rect.width()+x]; + const KDColor result = KDColor::RGB888( + (uint8_t)(powf(color.red()/255.f, redGamma)*255), + (uint8_t)(powf(color.green()/255.f, greenGamma)*255), + (uint8_t)(powf(color.blue()/255.f, blueGamma)*255)); + workingBuffer[x] = result; + } + KDPostProcessContext::pushRect(workingRect, workingBuffer); + } +} + +void KDPostProcessGammaContext::pushRectUniform(KDRect rect, KDColor color) { + const float redGamma = toGamma(m_redGamma); + const float greenGamma = toGamma(m_greenGamma); + const float blueGamma = toGamma(m_blueGamma); + const KDColor result = KDColor::RGB888( + (uint8_t)(powf(color.red()/255.f, redGamma)*255), + (uint8_t)(powf(color.green()/255.f, greenGamma)*255), + (uint8_t)(powf(color.blue()/255.f, blueGamma)*255)); + + KDPostProcessContext::pushRectUniform(rect, result); +} + +void KDPostProcessGammaContext::pullRect(KDRect rect, KDColor * pixels) { + const float redGamma = 1.f/toGamma(m_redGamma); + const float greenGamma = 1.f/toGamma(m_greenGamma); + const float blueGamma = 1.f/toGamma(m_blueGamma); + KDPostProcessContext::pullRect(rect, pixels); + for (KDCoordinate y = 0; y < rect.height(); y++) { + for (KDCoordinate x = 0; x < rect.width(); x++) { + const KDColor color = pixels[y*rect.width()+x]; + const KDColor result = KDColor::RGB888( + (uint8_t)(powf(color.red()/255.f, redGamma)*255), + (uint8_t)(powf(color.green()/255.f,greenGamma)*255), + (uint8_t)(powf(color.blue()/255.f, blueGamma)*255)); + pixels[y*rect.width()+x] = result; + } + } +} diff --git a/kandinsky/src/postprocess_invert_context.cpp b/kandinsky/src/postprocess_invert_context.cpp new file mode 100644 index 000000000..05471b790 --- /dev/null +++ b/kandinsky/src/postprocess_invert_context.cpp @@ -0,0 +1,28 @@ +#include +#include + +void KDPostProcessInvertContext::pushRect(KDRect rect, const KDColor * pixels) { + KDColor workingBuffer[rect.width()]; + + for (KDCoordinate y = 0; y < rect.height(); y++) { + KDRect workingRect(rect.x(), rect.y()+y, rect.width(), 1); + + for (KDCoordinate x = 0; x < rect.width(); x++) { + workingBuffer[x] = pixels[y*rect.width()+x].invert(); + } + KDPostProcessContext::pushRect(workingRect, workingBuffer); + } +} + +void KDPostProcessInvertContext::pushRectUniform(KDRect rect, KDColor color) { + KDPostProcessContext::pushRectUniform(rect, color.invert()); +} + +void KDPostProcessInvertContext::pullRect(KDRect rect, KDColor * pixels) { + KDPostProcessContext::pullRect(rect, pixels); + for (KDCoordinate y = 0; y < rect.height(); y++) { + for (KDCoordinate x = 0; x < rect.width(); x++) { + pixels[y*rect.width()+x] = pixels[y*rect.width()+x].invert(); + } + } +} diff --git a/kandinsky/src/postprocess_zoom_context.cpp b/kandinsky/src/postprocess_zoom_context.cpp new file mode 100644 index 000000000..8e626d441 --- /dev/null +++ b/kandinsky/src/postprocess_zoom_context.cpp @@ -0,0 +1,53 @@ +#include +#include + +KDPostProcessZoomContext::KDPostProcessZoomContext() : m_viewingArea(KDRectZero), m_targetArea(KDRectZero) +{ +} + +void KDPostProcessZoomContext::pushRect(KDRect rect, const KDColor * pixels) { + auto translatedRect = rect.translatedBy(KDPoint(-m_viewingArea.x(),-m_viewingArea.y())); + auto targetRect = KDRect(translatedRect.x()*2, translatedRect.y()*2, translatedRect.width()*2, translatedRect.height()*2); + auto clippedTargetRect = m_targetArea.intersectedWith(targetRect); + + KDColor targetBuffer[targetRect.width()]; + + for (int y = 0; y < rect.height(); y++) { + for (int x = 0; x < rect.width(); x++) { + targetBuffer[2*x+1] = targetBuffer[2*x] = pixels[y*rect.width()+x]; + } + + for (int i = 0; i < 2; i++) { + auto outputRect = KDRect(targetRect.x(), targetRect.y()+y*2+i, targetRect.width(), 1); + KDPostProcessContext::pushRect(m_targetArea.intersectedWith(outputRect), targetBuffer+(clippedTargetRect.x()-targetRect.x())); + } + } +} + +void KDPostProcessZoomContext::pushRectUniform(KDRect rect, KDColor color) { + auto clippedRect = m_viewingArea.intersectedWith(rect); + auto targetRect = KDRect(clippedRect.x()*2, clippedRect.y()*2, clippedRect.width()*2, clippedRect.height()*2); + targetRect = targetRect.translatedBy(KDPoint(-m_viewingArea.x()*2,-m_viewingArea.y()*2)); + targetRect = m_targetArea.intersectedWith(targetRect); + + KDPostProcessContext::pushRectUniform(targetRect, color); +} + +void KDPostProcessZoomContext::pullRect(KDRect rect, KDColor * pixels) { + auto translatedRect = rect.translatedBy(KDPoint(-m_viewingArea.x(),-m_viewingArea.y())); + auto targetRect = KDRect(translatedRect.x()*2, translatedRect.y()*2, translatedRect.width()*2, translatedRect.height()*2); + auto clippedTargetRect = m_targetArea.intersectedWith(targetRect); + + KDColor targetBuffer[targetRect.width()]; + + for (int y = 0; y < rect.height(); y++) { + memset(targetBuffer, 0x00, sizeof(targetBuffer)); + + auto outputRect = KDRect(targetRect.x(), targetRect.y()+y*2, targetRect.width(), 1).intersectedWith(m_targetArea); + KDPostProcessContext::pullRect(outputRect, targetBuffer+(clippedTargetRect.x()-targetRect.x())); + + for (int x = 0; x < rect.width(); x++) { + pixels[y*rect.width()+x] = targetBuffer[x*2]; + } + } +} From df7d552e80dd24fb92fe77daa4a63d00942b820a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Tue, 28 May 2019 18:59:46 +0200 Subject: [PATCH 3/3] [apps] Implement accessibility features --- apps/apps_container.cpp | 34 ++++- apps/apps_container.h | 2 +- apps/home/controller.cpp | 8 + apps/home/controller.h | 1 + apps/settings/Makefile | 1 + apps/settings/base.de.i18n | 7 + apps/settings/base.en.i18n | 7 + apps/settings/base.es.i18n | 7 + apps/settings/base.fr.i18n | 7 + apps/settings/base.pt.i18n | 7 + apps/settings/main_controller.cpp | 3 + apps/settings/main_controller.h | 2 + apps/settings/main_controller_prompt_beta.cpp | 4 +- apps/settings/main_controller_prompt_none.cpp | 4 +- .../main_controller_prompt_update.cpp | 4 +- .../sub_menu/accessibility_controller.cpp | 141 ++++++++++++++++++ .../sub_menu/accessibility_controller.h | 26 ++++ .../sub_menu/generic_sub_controller.h | 2 +- 18 files changed, 260 insertions(+), 7 deletions(-) create mode 100644 apps/settings/sub_menu/accessibility_controller.cpp create mode 100644 apps/settings/sub_menu/accessibility_controller.h diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp index adb666104..776153935 100644 --- a/apps/apps_container.cpp +++ b/apps/apps_container.cpp @@ -146,6 +146,36 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) { Ion::USB::clearEnumerationInterrupt(); } } else { + if (KDIonContext::sharedContext()->zoomEnabled) { + bool changedZoom = true; + + if (event == Ion::Events::ShiftOne) { + KDIonContext::sharedContext()->zoomPosition = 0; + } else if (event == Ion::Events::ShiftTwo) { + KDIonContext::sharedContext()->zoomPosition = 1; + } else if (event == Ion::Events::ShiftThree) { + KDIonContext::sharedContext()->zoomPosition = 2; + } else if (event == Ion::Events::ShiftFour) { + KDIonContext::sharedContext()->zoomPosition = 3; + } else if (event == Ion::Events::ShiftFive) { + KDIonContext::sharedContext()->zoomPosition = 4; + } else if (event == Ion::Events::ShiftSix) { + KDIonContext::sharedContext()->zoomPosition = 5; + } else if (event == Ion::Events::ShiftSeven) { + KDIonContext::sharedContext()->zoomPosition = 6; + } else if (event == Ion::Events::ShiftEight) { + KDIonContext::sharedContext()->zoomPosition = 7; + } else if (event == Ion::Events::ShiftNine) { + KDIonContext::sharedContext()->zoomPosition = 8; + } else { + changedZoom = false; + } + if (changedZoom) { + KDIonContext::sharedContext()->updatePostProcessingEffects(); + redrawWindow(true); + return true; + } + } didProcessEvent = Container::dispatchEvent(event); } @@ -312,8 +342,8 @@ OnBoarding::PopUpController * AppsContainer::promptController() { return &m_promptController; } -void AppsContainer::redrawWindow() { - m_window.redraw(); +void AppsContainer::redrawWindow(bool force) { + m_window.redraw(force); } void AppsContainer::examDeactivatingPopUpIsDismissed() { diff --git a/apps/apps_container.h b/apps/apps_container.h index bd0c8fb2c..87c0adea6 100644 --- a/apps/apps_container.h +++ b/apps/apps_container.h @@ -45,7 +45,7 @@ public: void shutdownDueToLowBattery(); void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus); OnBoarding::PopUpController * promptController(); - void redrawWindow(); + void redrawWindow(bool force = false); // Exam pop-up controller delegate void examDeactivatingPopUpIsDismissed() override; // Ion::StorageDelegate diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp index c59612d7a..42a657398 100644 --- a/apps/home/controller.cpp +++ b/apps/home/controller.cpp @@ -1,6 +1,7 @@ #include "controller.h" #include "app.h" #include "../apps_container.h" +#include "../global_preferences.h" extern "C" { #include } @@ -85,6 +86,13 @@ void Controller::didBecomeFirstResponder() { } void Controller::viewWillAppear() { + KDIonContext::sharedContext()->zoomInhibit = true; + KDIonContext::sharedContext()->updatePostProcessingEffects(); +} + +void Controller::viewDidDisappear() { + KDIonContext::sharedContext()->zoomInhibit = false; + KDIonContext::sharedContext()->updatePostProcessingEffects(); } View * Controller::view() { diff --git a/apps/home/controller.h b/apps/home/controller.h index 4c354bfb5..b30bf89d1 100644 --- a/apps/home/controller.h +++ b/apps/home/controller.h @@ -15,6 +15,7 @@ public: bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; void viewWillAppear() override; + void viewDidDisappear() override; virtual int numberOfRows() const override; virtual int numberOfColumns() const override; diff --git a/apps/settings/Makefile b/apps/settings/Makefile index d3d82d539..c60b78c21 100644 --- a/apps/settings/Makefile +++ b/apps/settings/Makefile @@ -6,6 +6,7 @@ app_settings_src = $(addprefix apps/settings/,\ main_controller.cpp \ settings_message_tree.cpp \ sub_menu/about_controller.cpp \ + sub_menu/accessibility_controller.cpp \ sub_menu/display_mode_controller.cpp \ sub_menu/exam_mode_controller.cpp \ sub_menu/generic_sub_controller.cpp \ diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n index 85cb99187..a88d9b97a 100644 --- a/apps/settings/base.de.i18n +++ b/apps/settings/base.de.i18n @@ -32,3 +32,10 @@ ColorBlue = "Blau " ColorGreen = "Grün " ColorYellow = "Gelb " Contributors = "Beiträger" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n index b44ee12cf..96455df9e 100644 --- a/apps/settings/base.en.i18n +++ b/apps/settings/base.en.i18n @@ -32,3 +32,10 @@ ColorBlue = "Blue " ColorGreen = "Green " ColorYellow = "Yellow " Contributors = "Contributors" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n index e85cfde3b..e67cf1834 100644 --- a/apps/settings/base.es.i18n +++ b/apps/settings/base.es.i18n @@ -32,3 +32,10 @@ ColorBlue = "Azul " ColorGreen = "Verde " ColorYellow = "Amarillo " Contributors = "Contribuyentes" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n index f846c1a36..e513f86da 100644 --- a/apps/settings/base.fr.i18n +++ b/apps/settings/base.fr.i18n @@ -32,3 +32,10 @@ ColorBlue = "Bleu " ColorGreen = "Vert " ColorYellow = "Jaune " Contributors = "Contributeurs" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Inverser couleurs" +AccessibilityMagnify = "Loupe" +AccessibilityGamma = "Correction gamma" +AccessibilityGammaRed = "Gamma rouge" +AccessibilityGammaGreen = "Gamma vert" +AccessibilityGammaBlue = "Gamma bleu" diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n index c922c0559..a39c61a3c 100644 --- a/apps/settings/base.pt.i18n +++ b/apps/settings/base.pt.i18n @@ -32,3 +32,10 @@ ColorBlue = "Azul " ColorGreen = "Verde " ColorYellow = "Amarelo " Contributors = "Contribuidores" +Accessibility = "Accessibility" +AccessibilityInvertColors = "Invert colors" +AccessibilityMagnify = "Magnify" +AccessibilityGamma = "Gamma correction" +AccessibilityGammaRed = "Red gamma" +AccessibilityGammaGreen = "Green gamma" +AccessibilityGammaBlue = "Blue gamma" diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp index d05289721..22bd8ba47 100644 --- a/apps/settings/main_controller.cpp +++ b/apps/settings/main_controller.cpp @@ -15,6 +15,7 @@ MainController::MainController(Responder * parentResponder, InputEventHandlerDel m_preferencesController(this), m_displayModeController(this, inputEventHandlerDelegate), m_languageController(this, 13), + m_accessibilityController(this), m_examModeController(this), m_aboutController(this), m_contributorsController(this) @@ -76,6 +77,8 @@ bool MainController::handleEvent(Ion::Events::Event event) { } else if (rowIndex == 7 + hasPrompt()) { subController = &m_aboutController; } else if (rowIndex == 9 + hasPrompt()) { + subController = &m_accessibilityController; + } else if (rowIndex == 10 + hasPrompt()) { subController = &m_contributorsController; } else { subController = &m_preferencesController; diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h index b26ff79c6..c5a75f9e9 100644 --- a/apps/settings/main_controller.h +++ b/apps/settings/main_controller.h @@ -4,6 +4,7 @@ #include #include "settings_message_tree.h" #include "sub_menu/about_controller.h" +#include "sub_menu/accessibility_controller.h" #include "sub_menu/display_mode_controller.h" #include "sub_menu/exam_mode_controller.h" #include "sub_menu/language_controller.h" @@ -40,6 +41,7 @@ private: PreferencesController m_preferencesController; DisplayModeController m_displayModeController; LanguageController m_languageController; + AccessibilityController m_accessibilityController; ExamModeController m_examModeController; AboutController m_aboutController; ContributorsController m_contributorsController; diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp index 599d12576..62ef395fd 100644 --- a/apps/settings/main_controller_prompt_beta.cpp +++ b/apps/settings/main_controller_prompt_beta.cpp @@ -10,6 +10,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::BetaPopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 12); I18n::Message MainController::promptMessage() const { return I18n::Message::BetaPopUp; diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp index 8a59de5de..87ffd9eb6 100644 --- a/apps/settings/main_controller_prompt_none.cpp +++ b/apps/settings/main_controller_prompt_none.cpp @@ -11,6 +11,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::ExamMode, s_modelExamChildren, 1), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 10); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); I18n::Message MainController::promptMessage() const { return I18n::Message::Default; diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp index c9b41b540..d3c8fff49 100644 --- a/apps/settings/main_controller_prompt_update.cpp +++ b/apps/settings/main_controller_prompt_update.cpp @@ -10,6 +10,7 @@ constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessage constexpr SettingsMessageTree s_modelExamChildren[1] = {SettingsMessageTree(I18n::Message::ActivateExamMode)}; constexpr SettingsMessageTree s_modelAboutChildren[4] = {SettingsMessageTree(I18n::Message::SoftwareVersion), SettingsMessageTree(I18n::Message::CustomSoftwareVersion), SettingsMessageTree(I18n::Message::SerialNumber), SettingsMessageTree(I18n::Message::FccId)}; constexpr SettingsMessageTree s_ledColorChildren[4] = {SettingsMessageTree(I18n::Message::ColorWhite), SettingsMessageTree(I18n::Message::ColorGreen), SettingsMessageTree(I18n::Message::ColorBlue), SettingsMessageTree(I18n::Message::ColorYellow)}; +constexpr SettingsMessageTree s_accessibilityChildren[6] = {SettingsMessageTree(I18n::Message::AccessibilityInvertColors), SettingsMessageTree(I18n::Message::AccessibilityMagnify),SettingsMessageTree(I18n::Message::AccessibilityGamma),SettingsMessageTree(I18n::Message::AccessibilityGammaRed),SettingsMessageTree(I18n::Message::AccessibilityGammaGreen),SettingsMessageTree(I18n::Message::AccessibilityGammaBlue)}; constexpr SettingsMessageTree s_contributorsChildren[4] = {SettingsMessageTree(I18n::Message::QuentinGuidee), SettingsMessageTree(I18n::Message::DannySimmons), SettingsMessageTree(I18n::Message::JoachimLeFournis), SettingsMessageTree(I18n::Message::JeanBaptisteBoric)}; constexpr SettingsMessageTree s_modelMenu[] = @@ -23,9 +24,10 @@ constexpr SettingsMessageTree s_modelMenu[] = SettingsMessageTree(I18n::Message::UpdatePopUp), SettingsMessageTree(I18n::Message::About, s_modelAboutChildren, 4), SettingsMessageTree(I18n::Message::LEDColor, s_ledColorChildren, 4), + SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren, 6), SettingsMessageTree(I18n::Message::Contributors, s_contributorsChildren, 4)}; -constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 11); +constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu, 12); I18n::Message MainController::promptMessage() const { return I18n::Message::UpdatePopUp; diff --git a/apps/settings/sub_menu/accessibility_controller.cpp b/apps/settings/sub_menu/accessibility_controller.cpp new file mode 100644 index 000000000..1df981f37 --- /dev/null +++ b/apps/settings/sub_menu/accessibility_controller.cpp @@ -0,0 +1,141 @@ +#include "accessibility_controller.h" +#include "../../global_preferences.h" +#include "../../apps_container.h" +#include + +using namespace Shared; + +namespace Settings { + +AccessibilityController::AccessibilityController(Responder * parentResponder) : + GenericSubController(parentResponder) +{ + for (int i = 0; i < k_totalNumberOfSwitchCells; i++) { + m_switchCells[i].setMessageFont(KDFont::LargeFont); + } + for (int i = 0; i < k_totalNumberOfGaugeCells; i++) { + m_gaugeCells[i].setMessageFont(KDFont::LargeFont); + } +} + +bool AccessibilityController::handleEvent(Ion::Events::Event event) { + bool invertEnabled = KDIonContext::sharedContext()->invertEnabled; + bool zoomEnabled = KDIonContext::sharedContext()->zoomEnabled; + bool gammaEnabled = KDIonContext::sharedContext()->gammaEnabled; + int redGamma, greenGamma, blueGamma; + KDIonContext::sharedContext()->gamma.gamma(redGamma, greenGamma, blueGamma); + + if (event == Ion::Events::OK || event == Ion::Events::EXE) { + if (selectedRow() == 0) { + invertEnabled = !invertEnabled; + } + else if (selectedRow() == 1) { + zoomEnabled = !zoomEnabled; + } + else if (selectedRow() == 2) { + gammaEnabled = !gammaEnabled; + } + else { + GenericSubController::handleEvent(event); + } + } + else if (event == Ion::Events::Right || event == Ion::Events::Left || event == Ion::Events::Plus || event == Ion::Events::Minus) { + int direction = (event == Ion::Events::Right || event == Ion::Events::Plus) ? 1 : -1; + if (selectedRow() == 3) { + redGamma += direction; + } + else if (selectedRow() == 4) { + greenGamma += direction; + } + else if (selectedRow() == 5) { + blueGamma += direction; + } + else { + return GenericSubController::handleEvent(event); + } + } + else { + return GenericSubController::handleEvent(event); + } + KDIonContext::sharedContext()->invertEnabled = invertEnabled; + KDIonContext::sharedContext()->zoomEnabled = zoomEnabled; + KDIonContext::sharedContext()->gammaEnabled = gammaEnabled; + KDIonContext::sharedContext()->gamma.setGamma(redGamma, greenGamma, blueGamma); + KDIonContext::sharedContext()->updatePostProcessingEffects(); + m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + AppsContainer::sharedAppsContainer()->redrawWindow(true); + return true; +} + +HighlightCell * AccessibilityController::reusableCell(int index, int type) { + assert(type == 1 || type == 2); + if (type == 2) { + assert(index >= 0 && index < k_totalNumberOfSwitchCells); + return &m_switchCells[index]; + } + else if (type == 1) { + assert(index >= 0 && index < k_totalNumberOfGaugeCells); + return &m_gaugeCells[index]; + } + return nullptr; +} + +int AccessibilityController::reusableCellCount(int type) { + assert(type == 1 || type == 2); + if (type == 2) { + return k_totalNumberOfSwitchCells; + } + else if (type == 1) { + return k_totalNumberOfGaugeCells; + } + return 0; +} + +void AccessibilityController::willDisplayCellForIndex(HighlightCell * cell, int index) { + GenericSubController::willDisplayCellForIndex(cell, index); + + MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell; + + if (index == 0) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->invertEnabled); + } + else if (index == 1) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->zoomEnabled); + } + else if (index == 2) { + SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView(); + mySwitch->setState(KDIonContext::sharedContext()->gammaEnabled); + } + else { + MessageTableCellWithGauge * myGaugeCell = (MessageTableCellWithGauge *)cell; + GaugeView * myGauge = (GaugeView *)myGaugeCell->accessoryView(); + + float redGamma, greenGamma, blueGamma, level; + KDIonContext::sharedContext()->gamma.gamma(redGamma, greenGamma, blueGamma); + if (index == 3) { + level = redGamma; + } + else if (index == 4) { + level = greenGamma; + } + else { + level = blueGamma; + } + myGauge->setLevel(level); + } +} + +int AccessibilityController::typeAtLocation(int i, int j) { + switch (j) { + case 0: + case 1: + case 2: + return 2; + default: + return 1; + } +} + +} diff --git a/apps/settings/sub_menu/accessibility_controller.h b/apps/settings/sub_menu/accessibility_controller.h new file mode 100644 index 000000000..1d42ff6c3 --- /dev/null +++ b/apps/settings/sub_menu/accessibility_controller.h @@ -0,0 +1,26 @@ +#ifndef SETTINGS_ACCESSIBILITY_CONTROLLER_H +#define SETTINGS_ACCESSIBILITY_CONTROLLER_H + +#include "generic_sub_controller.h" +#include "../../hardware_test/pop_up_controller.h" + +namespace Settings { + +class AccessibilityController : public GenericSubController { +public: + AccessibilityController(Responder * parentResponder); + bool handleEvent(Ion::Events::Event event) override; + HighlightCell * reusableCell(int index, int type) override; + int reusableCellCount(int type) override; + void willDisplayCellForIndex(HighlightCell * cell, int index) override; + int typeAtLocation(int i, int j) override; +private: + constexpr static int k_totalNumberOfSwitchCells = 3; + constexpr static int k_totalNumberOfGaugeCells = 3; + MessageTableCellWithGauge m_gaugeCells[k_totalNumberOfGaugeCells]; + MessageTableCellWithSwitch m_switchCells[k_totalNumberOfSwitchCells]; +}; + +} + +#endif diff --git a/apps/settings/sub_menu/generic_sub_controller.h b/apps/settings/sub_menu/generic_sub_controller.h index 132cc1773..039d25ede 100644 --- a/apps/settings/sub_menu/generic_sub_controller.h +++ b/apps/settings/sub_menu/generic_sub_controller.h @@ -17,7 +17,7 @@ public: KDCoordinate rowHeight(int j) override; KDCoordinate cumulatedHeightFromIndex(int j) override; int indexFromCumulatedHeight(KDCoordinate offsetY) override; - int typeAtLocation(int i, int j) override; + virtual int typeAtLocation(int i, int j) override; void willDisplayCellForIndex(HighlightCell * cell, int index) override; void setMessageTreeModel(const MessageTree * messageTreeModel); void viewWillAppear() override;