diff --git a/poincare/Makefile b/poincare/Makefile index 808c3c747..3ada6fb0c 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -36,6 +36,7 @@ objs += $(addprefix poincare/src/layout/,\ fraction_layout.o\ horizontal_layout.o\ matrix_layout.o\ + nth_root_layout.o\ string_layout.o\ ) diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index 6e2595032..9880ba20f 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -10,6 +10,7 @@ public: Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; + ExpressionLayout * createLayout() const override; }; #endif diff --git a/poincare/src/layout/nth_root_layout.cpp b/poincare/src/layout/nth_root_layout.cpp new file mode 100644 index 000000000..6d45100a7 --- /dev/null +++ b/poincare/src/layout/nth_root_layout.cpp @@ -0,0 +1,113 @@ +#include +#include +#include "nth_root_layout.h" + +const uint8_t radixPixel[NthRootLayout::k_leftRadixHeight][NthRootLayout::k_leftRadixWidth] = { + {0x00, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x00, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF}, + {0xFF, 0xFF, 0xFF, 0x00, 0xFF}, + {0xFF, 0xFF, 0xFF, 0xFF, 0x00}, +}; + +NthRootLayout::NthRootLayout(ExpressionLayout * radicandLayout, ExpressionLayout * indexLayout) : + ExpressionLayout(), + m_radicandLayout(radicandLayout), + m_indexLayout(indexLayout) +{ + m_radicandLayout->setParent(this); + m_indexLayout->setParent(this); + m_baseline = max(m_radicandLayout->baseline() + k_radixLineThickness + k_heightMargin, + m_indexLayout->size().height() + k_leftRadixHeight - m_radicandLayout->size().height() - k_heightMargin + m_radicandLayout->baseline()); +} + +NthRootLayout::~NthRootLayout() { + delete m_radicandLayout; + delete m_indexLayout; +} + +void NthRootLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + KDSize radicandSize = m_radicandLayout->size(); + KDSize indexSize = m_indexLayout->size(); + KDColor workingBuffer[k_leftRadixWidth*k_leftRadixHeight]; + KDRect leftRadixFrame(p.x() + indexSize.width() + k_widthMargin - k_leftRadixWidth, + p.y() + max(indexSize.height(), k_radixLineThickness+2*k_heightMargin+radicandSize.height()-k_leftRadixHeight), + k_leftRadixWidth, k_leftRadixHeight); + ctx->blendRectWithMask(leftRadixFrame, expressionColor, (const uint8_t *)radixPixel, (KDColor *)workingBuffer); + if (indexSize.height() + k_leftRadixHeight > k_radixLineThickness + radicandSize.height() + 2*k_heightMargin) { + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y() + indexSize.height() + k_leftRadixHeight - radicandSize.height() - k_radixLineThickness - 2*k_heightMargin, + k_radixLineThickness, + radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y() + indexSize.height() + k_leftRadixHeight - radicandSize.height() - k_radixLineThickness - 2*k_heightMargin, + radicandSize.width() + 2*k_widthMargin, + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin, + p.y() + indexSize.height() + k_leftRadixHeight - radicandSize.height() - k_radixLineThickness - 2*k_heightMargin, + k_radixLineThickness, + k_rightRadixHeight + k_radixLineThickness), expressionColor); + } else { + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y(), + k_radixLineThickness, + radicandSize.height() + 2*k_heightMargin + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin, + p.y(), + radicandSize.width() + 2*k_widthMargin, + k_radixLineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + indexSize.width() + k_widthMargin + radicandSize.width() + 2*k_widthMargin, + p.y(), + k_radixLineThickness, + k_rightRadixHeight + k_radixLineThickness), expressionColor); + } + +} + +KDSize NthRootLayout::computeSize() { + KDSize radicandSize = m_radicandLayout->size(); + KDSize indexSize = m_indexLayout->size(); + return KDSize( + indexSize.width() + 3*k_widthMargin + 2*k_radixLineThickness + radicandSize.width(), + max(k_radixLineThickness + 2*k_heightMargin + radicandSize.height(), indexSize.height() + k_leftRadixHeight) + ); +} + +ExpressionLayout * NthRootLayout::child(uint16_t index) { + switch (index) { + case 0: + return m_indexLayout; + case 1: + return m_radicandLayout; + default: + return nullptr; + } +} + +KDPoint NthRootLayout::positionOfChild(ExpressionLayout * child) { + KDCoordinate x = 0; + KDCoordinate y = 0; + KDSize radicandSize = m_radicandLayout->size(); + KDSize indexSize = m_indexLayout->size(); + if (child == m_indexLayout) { + x = 0; + if (indexSize.height() + k_leftRadixHeight > k_radixLineThickness + radicandSize.height() + 2*k_heightMargin) { + y = 0; + } else { + y = k_radixLineThickness+2*k_heightMargin+radicandSize.height()-k_leftRadixHeight - indexSize.height(); + } + } else if (child == m_radicandLayout) { + x = indexSize.width() + 2*k_widthMargin + k_radixLineThickness; + if (indexSize.height() + k_leftRadixHeight > k_radixLineThickness + radicandSize.height() + 2*k_heightMargin) { + y = indexSize.height() + k_leftRadixHeight - radicandSize.height() - k_heightMargin; + } else { + y = k_radixLineThickness + k_heightMargin; + } + } else { + assert(false); + } + return KDPoint(x,y); +} diff --git a/poincare/src/layout/nth_root_layout.h b/poincare/src/layout/nth_root_layout.h new file mode 100644 index 000000000..d9a679140 --- /dev/null +++ b/poincare/src/layout/nth_root_layout.h @@ -0,0 +1,27 @@ +#ifndef POINCARE_NTH_ROOT_LAYOUT_H +#define POINCARE_NTH_ROOT_LAYOUT_H + +#include +#include + +class NthRootLayout : public ExpressionLayout { +public: + NthRootLayout(ExpressionLayout * radicandLayout, ExpressionLayout * indexLayout); + ~NthRootLayout(); + constexpr static KDCoordinate k_leftRadixHeight = 8; + constexpr static KDCoordinate k_leftRadixWidth = 5; +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + ExpressionLayout * child(uint16_t index) override; + KDPoint positionOfChild(ExpressionLayout * child) override; +private: + constexpr static KDCoordinate k_rightRadixHeight = 2; + constexpr static KDCoordinate k_heightMargin = 2; + constexpr static KDCoordinate k_widthMargin = 1; + constexpr static KDCoordinate k_radixLineThickness = 1; + ExpressionLayout * m_radicandLayout; + ExpressionLayout * m_indexLayout; +}; + +#endif diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index f9844267f..d379b065d 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -1,4 +1,5 @@ #include +#include "layout/nth_root_layout.h" extern "C" { #include @@ -26,3 +27,7 @@ Expression * NthRoot::cloneWithDifferentOperands(Expression** newOperands, float NthRoot::approximate(Context& context) const { return powf(m_args[0]->approximate(context), 1.0f/m_args[1]->approximate(context)); } + +ExpressionLayout * NthRoot::createLayout() const { + return new NthRootLayout(m_args[0]->createLayout(), m_args[1]->createLayout()); +} \ No newline at end of file