Merge overrightarrow

This commit is contained in:
Laury
2021-11-11 20:21:44 +01:00
11 changed files with 168 additions and 14 deletions

View File

@@ -79,6 +79,7 @@ Layout TexParser::popText(char stop) {
while (m_text < m_endOfText && *m_text != stop) {
switch (*m_text) {
// TODO: Factorize this code
case '\\':
if (start != m_text) {
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
@@ -129,23 +130,30 @@ Layout TexParser::popText(char stop) {
}
Layout TexParser::popCommand() {
// TODO: Factorize this code
if (strncmp(k_fracCommand, m_text, strlen(k_fracCommand)) == 0) {
m_text += strlen(k_fracCommand);
if (*m_text == ' ' || *m_text == '{') {
if (isCommandEnded(*(m_text + strlen(k_fracCommand)))) {
m_text += strlen(k_fracCommand);
return popFracCommand();
}
}
else if (strncmp(k_sqrtCommand, m_text, strlen(k_sqrtCommand)) == 0) {
m_text += strlen(k_sqrtCommand);
if (*m_text == ' ' || *m_text == '{' || *m_text == '[') {
if (strncmp(k_sqrtCommand, m_text, strlen(k_sqrtCommand)) == 0) {
if (isCommandEnded(*(m_text + strlen(k_sqrtCommand)))) {
m_text += strlen(k_sqrtCommand);
return popSqrtCommand();
}
}
if (strncmp(k_overrightArrowCommand, m_text, strlen(k_overrightArrowCommand)) == 0) {
if (isCommandEnded(*(m_text + strlen(k_overrightArrowCommand)))) {
m_text += strlen(k_overrightArrowCommand);
return popOverrightarrowCommand();
}
}
for (int i = 0; i < k_NumberOfSymbols; i++) {
if (strncmp(k_SymbolsCommands[i], m_text, strlen(k_SymbolsCommands[i])) == 0) {
m_text += strlen(k_SymbolsCommands[i]);
if (*m_text == ' ' || *m_text == '\\' || *m_text == '$') {
if (isCommandEnded(*(m_text + strlen(k_SymbolsCommands[i])))) {
m_text += strlen(k_SymbolsCommands[i]);
return popSymbolCommand(i);
}
}
@@ -153,8 +161,8 @@ Layout TexParser::popCommand() {
for (int i = 0; i < k_NumberOfFunctionCommands; i++) {
if (strncmp(k_FunctionCommands[i], m_text, strlen(k_FunctionCommands[i])) == 0) {
m_text += strlen(k_FunctionCommands[i]);
if (*m_text == ' ' || *m_text == '(' || *m_text == '{') {
if (isCommandEnded(*(m_text + strlen(k_FunctionCommands[i])))) {
m_text += strlen(k_FunctionCommands[i]);
return LayoutHelper::String(k_FunctionCommands[i], strlen(k_FunctionCommands[i]));
}
}
@@ -187,10 +195,16 @@ Layout TexParser::popSqrtCommand() {
}
}
Layout TexParser::popOverrightarrowCommand() {
return VectorLayout::Builder(popBlock());
}
Layout TexParser::popSymbolCommand(int SymbolIndex) {
uint32_t codePoint = k_SymbolsCodePoints[SymbolIndex];
return CodePointLayout::Builder(codePoint);
}
inline bool TexParser::isCommandEnded(char c) const {
return !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z');
}
}

View File

@@ -22,6 +22,7 @@ private:
// Expressions
Layout popFracCommand();
Layout popSqrtCommand();
Layout popOverrightarrowCommand();
//Symbols
Layout popSymbolCommand(int SymbolIndex);
@@ -30,9 +31,12 @@ private:
const char * m_endOfText;
bool m_hasError;
inline bool isCommandEnded(char c) const;
// Expressions that require specific handling
static constexpr char const * k_fracCommand = "frac";
static constexpr char const * k_sqrtCommand = "sqrt";
static constexpr char const * k_overrightArrowCommand = "overrightarrow";
static constexpr int const k_NumberOfSymbols = 70;
static constexpr int const k_NumberOfFunctionCommands = 32;

View File

@@ -131,7 +131,7 @@ const char * StartOfPrintableWord(const char * word, const char * start) {
if (word == start) {
return word;
}
UTF8Decoder decoder(word);
UTF8Decoder decoder(start, word);
CodePoint codePoint = decoder.previousCodePoint();
const char * result = word;
while (codePoint != '\n' && codePoint != ' ' && codePoint != '%' && codePoint != '$') {

View File

@@ -40,7 +40,7 @@ void WordWrapTextView::previousPage() {
const int charHeight = m_font->glyphSize().height();
const char * endOfFile = text() + m_length;
const char * endOfWord = text() + m_pageOffset - 1;
const char * endOfWord = text() + m_pageOffset;
const char * startOfWord = StartOfPrintableWord(endOfWord, text());
KDSize textSize = KDSizeZero;
@@ -48,8 +48,8 @@ void WordWrapTextView::previousPage() {
KDPoint textEndPosition(m_frame.width() - k_margin, m_frame.height() - k_margin);
while(startOfWord>=text()) {
startOfWord = StartOfPrintableWord(endOfWord, text());
endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
startOfWord = StartOfPrintableWord(endOfWord-1, text());
//endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
if (*startOfWord == '%') {
if (updateTextColorBackward(startOfWord)) {

View File

@@ -26,6 +26,7 @@ poincare_src += $(addprefix poincare/src/,\
right_square_bracket_layout.cpp \
sequence_layout.cpp \
sum_layout.cpp \
vector_layout.cpp \
vertical_offset_layout.cpp \
)

View File

@@ -23,6 +23,7 @@ class LayoutCursor final {
friend class MatrixLayoutNode;
friend class NthRootLayoutNode;
friend class SequenceLayoutNode;
friend class VectorLayoutNode;
friend class VerticalOffsetLayoutNode;
public:
constexpr static KDCoordinate k_cursorWidth = 1;

View File

@@ -40,6 +40,7 @@ public:
RightParenthesisLayout,
RightSquareBracketLayout,
SumLayout,
VectorLayout,
VectorNormLayout,
VerticalOffsetLayout
};

View File

@@ -0,0 +1,53 @@
#ifndef POINCARE_VECTOR_LAYOUT_NODE_H
#define POINCARE_VECTOR_LAYOUT_NODE_H
#include <poincare/layout.h>
#include <poincare/layout_cursor.h>
#include <poincare/serialization_helper.h>
namespace Poincare {
class VectorLayoutNode final : public LayoutNode {
public:
// Layout
Type type() const override { return Type::VectorLayout; }
// SerializationHelperInterface
int serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const override {
return SerializationHelper::Prefix(this, buffer, bufferSize, floatDisplayMode, numberOfSignificantDigits, "vector", true, 0);
}
virtual void moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool forSelection = false);
virtual void moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool forSelection = false);
// TreeNode
size_t size() const override { return sizeof(VectorLayoutNode); }
int numberOfChildren() const override { return 1; }
#if POINCARE_TREE_LOG
void logNodeName(std::ostream & stream) const override {
stream << "VectorLayout";
}
#endif
constexpr static KDCoordinate k_arrowWidth = 5;
constexpr static KDCoordinate k_arrowHeight = 9;
protected:
virtual KDSize computeSize();
virtual KDCoordinate computeBaseline();
virtual KDPoint positionOfChild(LayoutNode * child);
private:
virtual void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor, Layout * selectionStart = nullptr, Layout * selectionEnd = nullptr, KDColor selectionColor = KDColorRed);
constexpr static KDCoordinate k_sideMargin = 2;
constexpr static KDCoordinate k_topMargin = 1;
constexpr static KDCoordinate k_arrowLineHeight = 1; // k_arrowHeight - k_arrowLineHeight must be even
};
class VectorLayout final : public Layout {
public:
static VectorLayout Builder(Layout child) { return TreeHandle::FixedArityBuilder<VectorLayout, VectorLayoutNode>({child}); }
VectorLayout() = delete;
};
}
#endif

View File

@@ -24,6 +24,7 @@
#include <poincare/right_square_bracket_layout.h>
#include <poincare/square_bracket_layout.h>
#include <poincare/sum_layout.h>
#include <poincare/vector_layout.h>
#include <poincare/vector_norm_layout.h>
#include <poincare/vertical_offset_layout.h>

View File

@@ -375,6 +375,7 @@ template VectorCross TreeHandle::FixedArityBuilder<VectorCross, VectorCrossNode>
template VectorDot TreeHandle::FixedArityBuilder<VectorDot, VectorDotNode>(const Tuple &);
template VectorNorm TreeHandle::FixedArityBuilder<VectorNorm, VectorNormNode>(const Tuple &);
template VectorNormLayout TreeHandle::FixedArityBuilder<VectorNormLayout, VectorNormLayoutNode>(const Tuple &);
template VectorLayout TreeHandle::FixedArityBuilder<VectorLayout, VectorLayoutNode>(const Tuple &);
template MatrixLayout TreeHandle::NAryBuilder<MatrixLayout, MatrixLayoutNode>(const Tuple &);
}

View File

@@ -0,0 +1,78 @@
#include <poincare/vector_layout.h>
namespace Poincare
{
const uint8_t arrowMask[VectorLayoutNode::k_arrowHeight][VectorLayoutNode::k_arrowWidth] = {
{0xff, 0xf7, 0xff, 0xff, 0xff},
{0xf3, 0x2c, 0xd9, 0xff, 0xff},
{0xff, 0x93, 0x46, 0xfb, 0xff},
{0xff, 0xfb, 0x46, 0x93, 0xff},
{0x13, 0x13, 0x13, 0x13, 0xf0},
{0xff, 0xfb, 0x46, 0x93, 0xff},
{0xff, 0x93, 0x46, 0xfb, 0xff},
{0xf3, 0x2c, 0xd9, 0xff, 0xff},
{0xff, 0xf7, 0xff, 0xff, 0xff}
};
void VectorLayoutNode::moveCursorLeft(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool forSelection) {
if (cursor->layoutNode() == childAtIndex(0)
&& cursor->position() == LayoutCursor::Position::Left)
{
// Case: Left of the operand. Go Left of the brackets.
cursor->setLayout(this);
return;
}
assert(cursor->layoutNode() == this);
if (cursor->position() == LayoutCursor::Position::Right) {
// Case: Right of the brackets. Go Right of the operand.
cursor->setLayout(childAtIndex(0));
return;
}
assert(cursor->position() == LayoutCursor::Position::Left);
// Case: Left of the brackets. Ask the parent.
LayoutNode * parentNode = parent();
if (parentNode != nullptr) {
parentNode->moveCursorLeft(cursor, shouldRecomputeLayout);
}
}
void VectorLayoutNode::moveCursorRight(LayoutCursor * cursor, bool * shouldRecomputeLayout, bool forSelection) {
if (cursor->layoutNode() == childAtIndex(0)
&& cursor->position() == LayoutCursor::Position::Right)
{
// Case: Right of the operand. Go Right of the brackets.
cursor->setLayout(this);
return;
}
assert(cursor->layoutNode() == this);
if (cursor->position() == LayoutCursor::Position::Left) {
// Case: Left of the brackets. Go Left of the operand.
cursor->setLayout(childAtIndex(0));
return;
}
assert(cursor->position() == LayoutCursor::Position::Right);
// Case: Right of the brackets. Ask the parent.
LayoutNode * parentNode = parent();
if (parentNode != nullptr) {
parentNode->moveCursorRight(cursor, shouldRecomputeLayout);
}
}
KDSize VectorLayoutNode::computeSize() {
KDSize size = childAtIndex(0)->layoutSize();
return KDSize(2 * k_sideMargin + size.width() + k_arrowWidth + k_sideMargin, k_topMargin + (k_arrowHeight+k_arrowLineHeight)/2 + size.height());
}
KDCoordinate VectorLayoutNode::computeBaseline() {
return childAtIndex(0)->baseline() + (k_arrowHeight+k_arrowLineHeight)/2 + k_arrowLineHeight + k_topMargin;
}
KDPoint VectorLayoutNode::positionOfChild(LayoutNode * child) {
assert(child == childAtIndex(0));
return KDPoint(k_sideMargin * 2, k_topMargin + (k_arrowHeight+k_arrowLineHeight)/2 + k_arrowLineHeight);
}
void VectorLayoutNode::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor, Layout * selectionStart, Layout * selectionEnd, KDColor selectionColor) {
KDColor workingBuffer[k_arrowWidth * k_arrowHeight];
ctx->fillRect(KDRect(p.x() + k_sideMargin, p.y() + k_topMargin + (k_arrowHeight-k_arrowLineHeight)/2, 2 * k_sideMargin + childAtIndex(0)->layoutSize().width(), k_arrowLineHeight), expressionColor);
ctx->blendRectWithMask(KDRect(p.x() + 2 * k_sideMargin + childAtIndex(0)->layoutSize().width(), p.y() + k_topMargin, k_arrowWidth, k_arrowHeight), expressionColor, (const uint8_t *)arrowMask, workingBuffer);
}
}