mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[poincare] CodePointLayout
This commit is contained in:
@@ -16,8 +16,12 @@ private:
|
||||
uint32_t m_code;
|
||||
};
|
||||
|
||||
static constexpr CodePoint KDCodePointNull = 0x0;
|
||||
static constexpr CodePoint KDCodePointTabulation = 0x9;
|
||||
static constexpr CodePoint KDCodePointLineFeed = 0xA;
|
||||
static constexpr CodePoint KDCodePointNull = 0x0;
|
||||
static constexpr CodePoint KDCodePointTabulation = 0x9;
|
||||
static constexpr CodePoint KDCodePointLineFeed = 0xA;
|
||||
static constexpr CodePoint KDCodePointMiddleDot = 0xB7;
|
||||
static constexpr CodePoint KDCodePointMultiplicationSign = 0xD7;
|
||||
static constexpr CodePoint KDCodePointLatinLetterSmallCapitalE = 0x1d07;
|
||||
static constexpr CodePoint KDCodePointRightwardsArrow = 0x2192;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@ src += $(addprefix poincare/src/,\
|
||||
bracket_layout.cpp \
|
||||
bracket_pair_layout.cpp \
|
||||
char_layout.cpp \
|
||||
code_point_layout.cpp\
|
||||
condensed_sum_layout.cpp \
|
||||
conjugate_layout.cpp \
|
||||
empty_layout.cpp \
|
||||
|
||||
76
poincare/include/poincare/code_point_layout.h
Normal file
76
poincare/include/poincare/code_point_layout.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef POINCARE_CODEPOINT_LAYOUT_NODE_H
|
||||
#define POINCARE_CODEPOINT_LAYOUT_NODE_H
|
||||
|
||||
#include <kandinsky/include/kandinsky/unicode/code_point.h>
|
||||
#include <poincare/layout_cursor.h>
|
||||
#include <poincare/layout.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
/* TODO: Make several code point classes depending on codepoint size?
|
||||
* (m_codePoint sometimes fits in a char, no need for a whole CodePoint */
|
||||
|
||||
class CodePointLayoutNode final : public LayoutNode {
|
||||
public:
|
||||
static constexpr const KDFont * k_defaultFont = KDFont::LargeFont;
|
||||
CodePointLayoutNode(CodePoint c = KDCodePointNull, const KDFont * font = k_defaultFont) :
|
||||
LayoutNode(),
|
||||
m_codePoint(c),
|
||||
m_font(font)
|
||||
{}
|
||||
|
||||
// CodePointLayout
|
||||
CodePoint codePoint() const { return m_codePoint; }
|
||||
const KDFont * font() const { return m_font; }
|
||||
|
||||
// LayoutNode
|
||||
void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) override;
|
||||
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override;
|
||||
bool isCodePoint() const override { return true; }
|
||||
bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const override;
|
||||
bool canBeOmittedMultiplicationLeftFactor() const override;
|
||||
bool canBeOmittedMultiplicationRightFactor() const override;
|
||||
|
||||
// TreeNode
|
||||
size_t size() const override { return sizeof(CodePointLayoutNode); }
|
||||
int numberOfChildren() const override { return 0; }
|
||||
#if POINCARE_TREE_LOG
|
||||
virtual void logNodeName(std::ostream & stream) const override {
|
||||
stream << "CodePointLayout";
|
||||
}
|
||||
virtual void logAttributes(std::ostream & stream) const override {
|
||||
stream << " CodePoint=\"" << m_codePoint << "\"";
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// LayoutNode
|
||||
KDSize computeSize() override;
|
||||
KDCoordinate computeBaseline() override;
|
||||
KDPoint positionOfChild(LayoutNode * child) override {
|
||||
assert(false);
|
||||
return KDPointZero;
|
||||
}
|
||||
|
||||
private:
|
||||
void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override;
|
||||
bool isMultiplicationCodePoint() const;
|
||||
CodePoint m_codePoint;
|
||||
const KDFont * m_font;
|
||||
};
|
||||
|
||||
class CodePointLayout final : public Layout {
|
||||
public:
|
||||
CodePointLayout(const CodePointLayoutNode * n) : Layout(n) {}
|
||||
static CharLayout Builder(CodePoint c, const KDFont * font = KDFont::LargeFont);
|
||||
const KDFont * font() const { return const_cast<CodePointLayout *>(this)->node()->font(); }
|
||||
CodePoint codePoint() const { return const_cast<CodePointLayout *>(this)->node()->codePoint(); }
|
||||
private:
|
||||
using Layout::node;
|
||||
CodePointLayoutNode * node() { return static_cast<CodePointLayoutNode *>(Layout::node()); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
bool isVerticalOffset() const { return const_cast<Layout *>(this)->node()->isVerticalOffset(); }
|
||||
bool isLeftParenthesis() const { return const_cast<Layout *>(this)->node()->isLeftParenthesis(); }
|
||||
bool isChar() const { return const_cast<Layout *>(this)->node()->isChar(); }
|
||||
bool isCodePoint() const { return const_cast<Layout *>(this)->node()->isCodePoint(); }
|
||||
bool isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const { return const_cast<Layout *>(this)->node()->isCollapsable(numberOfOpenParenthesis, goingLeft); }
|
||||
int leftCollapsingAbsorbingChildIndex() const { return const_cast<Layout *>(this)->node()->leftCollapsingAbsorbingChildIndex(); }
|
||||
int rightCollapsingAbsorbingChildIndex() const { return const_cast<Layout *>(this)->node()->rightCollapsingAbsorbingChildIndex(); }
|
||||
|
||||
@@ -105,6 +105,7 @@ public:
|
||||
virtual bool isEmpty() const { return false; }
|
||||
virtual bool isMatrix() const { return false; }
|
||||
virtual bool isChar() const { return false; }
|
||||
virtual bool isCodePoint() const { return false; }
|
||||
virtual bool hasUpperLeftIndex() const { return false; }
|
||||
virtual char XNTChar() const {
|
||||
LayoutNode * p = parent();
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
#define POINCARE_SERIALIZATION_HELPER_H
|
||||
|
||||
#include <poincare/tree_node.h>
|
||||
#include <kandinsky/include/kandinsky/unicode/code_point.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
namespace SerializationHelper {
|
||||
/* SerializableReference to Text */
|
||||
// SerializableReference to text
|
||||
int Infix(
|
||||
const TreeNode * node,
|
||||
char * buffer,
|
||||
@@ -26,8 +27,10 @@ namespace SerializationHelper {
|
||||
const char * operatorName,
|
||||
bool writeFirstChild = true);
|
||||
|
||||
/* Write one char in buffer */
|
||||
int Char(char * buffer, int bufferSize, char charToWrite);
|
||||
// Write one char in buffer
|
||||
int Char(char * buffer, int bufferSize, char charToWrite); // TODO REMOVE
|
||||
// Write one code point in a buffer
|
||||
int CodePoint(char * buffer, int bufferSize, CodePoint c);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <poincare/binomial_coefficient_layout.h>
|
||||
#include <poincare/bracket_pair_layout.h>
|
||||
#include <poincare/char_layout.h>
|
||||
#include <poincare/code_point_layout.h>
|
||||
#include <poincare/ceiling_layout.h>
|
||||
#include <poincare/condensed_sum_layout.h>
|
||||
#include <poincare/conjugate_layout.h>
|
||||
|
||||
108
poincare/src/code_point_layout.cpp
Normal file
108
poincare/src/code_point_layout.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <poincare/code_point_layout.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/serialization_helper.h>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
// LayoutNode
|
||||
void CodePointLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
if (cursor->position() == LayoutCursor::Position::Right) {
|
||||
cursor->setPosition(LayoutCursor::Position::Left);
|
||||
return;
|
||||
}
|
||||
LayoutNode * parentNode = parent();
|
||||
if (parentNode != nullptr) {
|
||||
parentNode->moveCursorLeft(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
}
|
||||
|
||||
void CodePointLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout) {
|
||||
if (cursor->position() == LayoutCursor::Position::Left) {
|
||||
cursor->setPosition(LayoutCursor::Position::Right);
|
||||
return;
|
||||
}
|
||||
LayoutNode * parentNode = parent();
|
||||
if (parentNode != nullptr) {
|
||||
parentNode->moveCursorRight(cursor, shouldRecomputeLayout);
|
||||
}
|
||||
}
|
||||
|
||||
int CodePointLayoutNode::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
|
||||
return SerializationHelper::CodePoint(buffer, bufferSize, m_codePoint);
|
||||
}
|
||||
|
||||
bool CodePointLayoutNode::isCollapsable(int * numberOfOpenParenthesis, bool goingLeft) const {
|
||||
if (*numberOfOpenParenthesis <= 0) {
|
||||
if (m_codePoint == '+'
|
||||
|| m_codePoint == KDCodePointRightwardsArrow
|
||||
|| m_codePoint == '='
|
||||
|| m_codePoint == ',')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_codePoint == '-') {
|
||||
/* If the expression is like 3ᴇ-200, we want '-' to be collapsable.
|
||||
* Otherwise, '-' is not collapsable. */
|
||||
Layout thisRef = CodePointLayout(this);
|
||||
Layout parent = thisRef.parent();
|
||||
if (!parent.isUninitialized()) {
|
||||
int indexOfThis = parent.indexOfChild(thisRef);
|
||||
if (indexOfThis > 0) {
|
||||
Layout leftBrother = parent.childAtIndex(indexOfThis-1);
|
||||
if (leftBrother.isCodePoint()
|
||||
&& static_cast<CodePointLayout&>(leftBrother).codePoint() == KDCodePointLatinLetterSmallCapitalE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CodePointLayoutNode::canBeOmittedMultiplicationLeftFactor() const {
|
||||
if (isMultiplicationCodePoint()) {
|
||||
return false;
|
||||
}
|
||||
return LayoutNode::canBeOmittedMultiplicationRightFactor();
|
||||
}
|
||||
|
||||
bool CodePointLayoutNode::canBeOmittedMultiplicationRightFactor() const {
|
||||
if (m_codePoint == '!' || isMultiplicationCodePoint()) {
|
||||
return false;
|
||||
}
|
||||
return LayoutNode::canBeOmittedMultiplicationRightFactor();
|
||||
}
|
||||
|
||||
// Sizing and positioning
|
||||
KDSize CodePointLayoutNode::computeSize() {
|
||||
return m_font->glyphSize();
|
||||
}
|
||||
|
||||
KDCoordinate CodePointLayoutNode::computeBaseline() {
|
||||
return m_font->glyphSize().height()/2;
|
||||
}
|
||||
|
||||
void CodePointLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) {
|
||||
constexpr int bufferSize = sizeof(CodePoint)/sizeof(char) + 1; // Null-terminating char
|
||||
char buffer[bufferSize];
|
||||
SerializationHelper::CodePoint(buffer, bufferSize, m_codePoint);
|
||||
ctx->drawString(buffer, p, m_font, expressionColor, backgroundColor);
|
||||
}
|
||||
|
||||
bool CodePointLayoutNode::isMultiplicationCodePoint() const {
|
||||
return m_codePoint == '*'
|
||||
|| m_codePoint == KDCodePointMultiplicationSign
|
||||
|| m_codePoint == KDCodePointMiddleDot;
|
||||
}
|
||||
|
||||
CodePointLayout CodePointLayout::Builder(CodePoint c, const KDFont * font) {
|
||||
void * bufferNode = TreePool::sharedPool()->alloc(sizeof(CodePointLayoutNode));
|
||||
CodePointLayoutNode * node = new (bufferNode) CodePointLayoutNode(c, font);
|
||||
TreeHandle h = TreeHandle::BuildWithGhostChildren(node);
|
||||
return static_cast<CodePointLayout &>(h);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <poincare/serialization_helper.h>
|
||||
#include <kandinsky/include/kandinsky/unicode/utf8_decoder.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -149,4 +150,21 @@ int SerializationHelper::Char(char * buffer, int bufferSize, char charToWrite) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SerializationHelper::CodePoint(char * buffer, int bufferSize, class CodePoint c) {
|
||||
if (bufferSize == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (bufferSize == 1) {
|
||||
buffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
constexpr int maxCodePointSize = sizeof(class CodePoint)/sizeof(char) + 1; // Null-terminating char
|
||||
char helpBuffer[maxCodePointSize];
|
||||
size_t size = UTF8Decoder::CodePointToChars(c, helpBuffer, maxCodePointSize);
|
||||
assert(size < maxCodePointSize);
|
||||
helpBuffer[size] = 0;
|
||||
strlcpy(buffer, helpBuffer, bufferSize);
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user