mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Merge overrightarrow
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 != '$') {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 \
|
||||
)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -40,6 +40,7 @@ public:
|
||||
RightParenthesisLayout,
|
||||
RightSquareBracketLayout,
|
||||
SumLayout,
|
||||
VectorLayout,
|
||||
VectorNormLayout,
|
||||
VerticalOffsetLayout
|
||||
};
|
||||
|
||||
53
poincare/include/poincare/vector_layout.h
Normal file
53
poincare/include/poincare/vector_layout.h
Normal 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
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 &);
|
||||
|
||||
}
|
||||
|
||||
78
poincare/src/vector_layout.cpp
Normal file
78
poincare/src/vector_layout.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user