mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Merge branch 'upsilon-dev-latex'
This commit is contained in:
4
Makefile
4
Makefile
@@ -27,6 +27,10 @@ ifeq (${MODEL}, n0100)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(filter reader,$(apps_list)),)
|
||||
HAS_READER := 1
|
||||
endif
|
||||
|
||||
ifeq (${MODEL}, n0110)
|
||||
apps_list = ${EPSILON_APPS}
|
||||
else
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
apps += Reader::App
|
||||
app_headers += apps/reader/app.h
|
||||
|
||||
SFLAGS += -DHAS_READER
|
||||
|
||||
app_sreader_src = $(addprefix apps/reader/,\
|
||||
app.cpp \
|
||||
list_book_controller.cpp \
|
||||
utility.cpp \
|
||||
read_book_controller \
|
||||
word_wrap_view.cpp \
|
||||
tex_parser.cpp \
|
||||
)
|
||||
|
||||
apps_src += $(app_sreader_src)
|
||||
@@ -15,4 +18,4 @@ app_images += apps/reader/reader_icon.png
|
||||
|
||||
i18n_files += $(call i18n_without_universal_for,reader/base)
|
||||
|
||||
$(eval $(call depends_on_image,apps/reader/app.cpp,apps/reader/reader_icon.png))
|
||||
$(eval $(call depends_on_image,apps/reader/app.cpp,apps/reader/reader_icon.png))
|
||||
|
||||
@@ -6,8 +6,10 @@ Thanks to [Gabriel79](https://github.com/Gabriel79) for the original reader app,
|
||||
# Rich text format
|
||||
Reader app supports now a rich text format :
|
||||
|
||||
* `$` around a mathematical expression **without spaces** to render it
|
||||
* `$` around a LaTeX expression to render it
|
||||
* `%` around a color-code (see below) to change the color of the text
|
||||
### LaTeX expressions
|
||||
You can read the documentation for the LaTeX Parser [here](TexParser.md).
|
||||
### Color codes :
|
||||
|code|color|
|
||||
| --:| ---:|
|
||||
|
||||
1901
apps/reader/TexParser.html
Normal file
1901
apps/reader/TexParser.html
Normal file
File diff suppressed because it is too large
Load Diff
51
apps/reader/TexParser.md
Normal file
51
apps/reader/TexParser.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# LaTeX Parser
|
||||
|
||||
In the reader app, you can read a txt file. You can also read a txt file with LaTeX expression inside of it.
|
||||
|
||||
All the symbols you can use are listed here :
|
||||
|
||||
|Command|Output||Command|Output|
|
||||
|--:|:--:|--:|--:|:--:|
|
||||
|Math|Expressions||||
|
||||
|`\frac{ab}{cd}`|$\frac{ab}{cd}$||`\sqrt[n]{x}`|$\sqrt[n]{x}$|
|
||||
|Math|Symbols|||
|
||||
|`\times`|$\times$||`\div`|$\div$|
|
||||
|`\forall`|$\forall$||`\exists`|$\exists$|
|
||||
|`\partial`|$\partial$||`\pm`|$\pm$|
|
||||
|`\infty`|$\infty$||`\approx`|$\approx$|
|
||||
|`\neq`|$\neq$||`\equiv`|$\equiv$|
|
||||
|`\leq`|$\leq$||`\geq`|$\geq$|
|
||||
|Simple|Arrows||Double|Arrows|
|
||||
|`\leftarrow`|$\leftarrow$||`\Leftarrow`|$\Leftarrow$|
|
||||
|`\rightarrow`|$\rightarrow$||`\Rightarrow`|$\Rightarrow$|
|
||||
|`\uparrow`|$\uparrow$||`\Uparrow`|$\Uparrow$|
|
||||
|`\downarrow`|$\downarrow$||`\Downarrow`|$\Downarrow$|
|
||||
|`\leftrightarrow`|$\leftrightarrow$||||
|
||||
|`\updownarrow`|$\updownarrow$||||
|
||||
|Greek Capital|Letters||Greek Small|Letters|
|
||||
|`\Alpha`|$\Alpha$||`\alpha`|$\alpha$|
|
||||
|`\Beta`|$\Beta$||`\beta`|$\beta$|
|
||||
|`\Gamma`|$\Gamma$||`\gamma`|$\gamma$|
|
||||
|`\Delta`|$\Delta$||`\delta`|$\delta$|
|
||||
|`\Epsilon`|$\Epsilon$||`\epsilon`|$\epsilon$|
|
||||
|`\Zeta`|$\Zeta$||`\zeta`|$\zeta$|
|
||||
|`\Eta`|$\Eta$||`\eta`|$\eta$|
|
||||
|`\Theta`|$\Theta$||`\theta`|$\theta$|
|
||||
|`\Iota`|$\Iota$||`\iota`|$\iota$|
|
||||
|`\Kappa`|$\Kappa$||`\kappa`|$\kappa$|
|
||||
|`\Lambda`|$\Lambda$||`\lambda`|$\lambda$|
|
||||
|`\Mu`|$\Mu$||`\mu`|$\mu$|
|
||||
|`\Nu`|$\Nu$||`\nu`|$\nu$|
|
||||
|`\Xi`|$\Xi$||`\xi`|$\xi$|
|
||||
|`\Omicron`|$\Omicron$|||
|
||||
|`\Pi`|$\Pi$||`\pi`|$\pi$|
|
||||
|`\Rho`|$\Rho$||`\rho`|$\rho$|
|
||||
|`\Sigma`|$\Sigma$||`\sigma`|$\sigma$|
|
||||
|`\Tau`|$\Tau$||`\tau`|$\tau$|
|
||||
|`\Upsilon`|$\Upsilon$||`\upsilon`|$\upsilon$|
|
||||
|`\Phi`|$\Phi$||`\phi`|$\phi$|
|
||||
|`\Chi`|$\Chi$||`\chi`|$\chi$|
|
||||
|`\Psi`|$\Psi$||`\psi`|$\psi$|
|
||||
|`\Omega`|$\Omega$||`\omega`|$\omega$|
|
||||
|
||||
|
||||
268
apps/reader/tex_parser.cpp
Normal file
268
apps/reader/tex_parser.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "tex_parser.h"
|
||||
#include <ion/unicode/utf8_decoder.h>
|
||||
|
||||
namespace Reader {
|
||||
|
||||
// List of available Symbols
|
||||
static constexpr char const * k_SymbolsCommands[] = {
|
||||
"times", "div", "forall", "partial", "exists", "pm", "approx", "infty", "neq", "equiv", "leq", "geq",
|
||||
"leftarrow", "uparrow", "rightarrow", "downarrow", "leftrightarrow", "updownarrow", "Leftarrow", "Uparrow", "Rightarrow", "Downarrow",
|
||||
"Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda",
|
||||
"Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi","Omega",
|
||||
"alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda",
|
||||
"mu", "nu", "xi", "omicron", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega",
|
||||
"sim",
|
||||
};
|
||||
|
||||
// List of the available Symbol's CodePoints in the same order of the Symbol's list
|
||||
static constexpr uint32_t const k_SymbolsCodePoints[] = {
|
||||
0xd7, 0xf7, 0x2200, 0x2202, 0x2203, 0xb1, 0x2248, 0x221e, 0x2260, 0x2261, 0x2264, 0x2265,
|
||||
0x2190, 0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
|
||||
0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39a, 0x39b,
|
||||
0x39c, 0x39d, 0x39e, 0x39f, 0x3a0, 0x3a1, 0x3a3, 0x3a4, 0x3a5, 0x3a6, 0x3a7, 0x3a8, 0x3a9,
|
||||
0x3b1, 0x3b2, 0x3b3, 0x3b4, 0x3b5, 0x3b6, 0x3b7, 0x3b8, 0x3b9, 0x3ba, 0x3bb,
|
||||
0x3bc, 0x3bd, 0x3be, 0x3bf, 0x3c0, 0x3c1, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7, 0x3c8, 0x3c9,
|
||||
0x7e,
|
||||
};
|
||||
|
||||
// List of available Function Commands that don't require a specific handling
|
||||
static constexpr char const * k_FunctionCommands[] = {
|
||||
"arcos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth",
|
||||
"csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf",
|
||||
"ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max",
|
||||
"min", "Pr", "sec", "sin", "sinh", "sup", "tan", "tanh"
|
||||
};
|
||||
|
||||
TexParser::TexParser(const char * text, const char * endOfText) :
|
||||
m_text(text),
|
||||
m_endOfText(endOfText),
|
||||
m_hasError(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Layout TexParser::getLayout() {
|
||||
Layout layout = popText(0);
|
||||
|
||||
if (m_hasError) {
|
||||
return CodePointLayout::Builder(CodePoint(0xfffd));
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
Layout TexParser::popBlock() {
|
||||
while (*m_text == ' ') {
|
||||
m_text ++;
|
||||
}
|
||||
|
||||
if (*m_text == '{') {
|
||||
m_text ++;
|
||||
return popText('}');
|
||||
}
|
||||
|
||||
if (*m_text == '\\') {
|
||||
m_text ++;
|
||||
return popCommand();
|
||||
}
|
||||
|
||||
if (m_text >= m_endOfText) {
|
||||
m_hasError = true;
|
||||
}
|
||||
|
||||
UTF8Decoder decoder(m_text);
|
||||
m_text ++;
|
||||
return CodePointLayout::Builder(decoder.nextCodePoint());
|
||||
}
|
||||
|
||||
Layout TexParser::popText(char stop) {
|
||||
HorizontalLayout layout = HorizontalLayout::Builder();
|
||||
const char * start = m_text;
|
||||
|
||||
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);
|
||||
}
|
||||
m_text ++;
|
||||
layout.addOrMergeChildAtIndex(popCommand(), layout.numberOfChildren(), false);
|
||||
start = m_text;
|
||||
break;
|
||||
case ' ':
|
||||
if (start != m_text) {
|
||||
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
|
||||
}
|
||||
m_text ++;
|
||||
start = m_text;
|
||||
break;
|
||||
case '^':
|
||||
if (start != m_text) {
|
||||
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
|
||||
}
|
||||
m_text ++;
|
||||
layout.addOrMergeChildAtIndex(VerticalOffsetLayout::Builder(popBlock(), VerticalOffsetLayoutNode::Position::Superscript), layout.numberOfChildren(), false);
|
||||
start = m_text;
|
||||
break;
|
||||
case '_':
|
||||
if (start != m_text) {
|
||||
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
|
||||
}
|
||||
m_text ++;
|
||||
layout.addOrMergeChildAtIndex(VerticalOffsetLayout::Builder(popBlock(), VerticalOffsetLayoutNode::Position::Subscript), layout.numberOfChildren(), false);
|
||||
start = m_text;
|
||||
break;
|
||||
default:
|
||||
m_text ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (start != m_text) {
|
||||
layout.addOrMergeChildAtIndex(LayoutHelper::String(start, m_text - start), layout.numberOfChildren(), false);
|
||||
}
|
||||
|
||||
m_text ++;
|
||||
|
||||
if (layout.numberOfChildren() == 1) {
|
||||
return layout.squashUnaryHierarchyInPlace();
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
Layout TexParser::popCommand() {
|
||||
// TODO: Factorize this code
|
||||
if (strncmp(k_ceilCommand, m_text, strlen(k_ceilCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_ceilCommand)))) {
|
||||
m_text += strlen(k_ceilCommand);
|
||||
return popCeilCommand();
|
||||
}
|
||||
}
|
||||
if (strncmp(k_floorCommand, m_text, strlen(k_floorCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_floorCommand)))) {
|
||||
m_text += strlen(k_floorCommand);
|
||||
return popFloorCommand();
|
||||
}
|
||||
}
|
||||
if (strncmp(k_fracCommand, m_text, strlen(k_fracCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_fracCommand)))) {
|
||||
m_text += strlen(k_fracCommand);
|
||||
return popFracCommand();
|
||||
}
|
||||
}
|
||||
if (strncmp(k_leftCommand, m_text, strlen(k_leftCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_leftCommand)))) {
|
||||
m_text += strlen(k_leftCommand);
|
||||
return popLeftCommand();
|
||||
}
|
||||
}
|
||||
if (strncmp(k_rightCommand, m_text, strlen(k_rightCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_rightCommand)))) {
|
||||
m_text += strlen(k_rightCommand);
|
||||
return popRightCommand();
|
||||
}
|
||||
}
|
||||
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_spaceCommand, m_text, strlen(k_spaceCommand)) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_spaceCommand)))) {
|
||||
m_text += strlen(k_spaceCommand);
|
||||
return popSpaceCommand();
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_SymbolsCommands[i])))) {
|
||||
m_text += strlen(k_SymbolsCommands[i]);
|
||||
return popSymbolCommand(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < k_NumberOfFunctionCommands; i++) {
|
||||
if (strncmp(k_FunctionCommands[i], m_text, strlen(k_FunctionCommands[i])) == 0) {
|
||||
if (isCommandEnded(*(m_text + strlen(k_FunctionCommands[i])))) {
|
||||
m_text += strlen(k_FunctionCommands[i]);
|
||||
return LayoutHelper::String(k_FunctionCommands[i], strlen(k_FunctionCommands[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_hasError = true;
|
||||
return EmptyLayout::Builder();
|
||||
}
|
||||
|
||||
// Expressions
|
||||
Layout TexParser::popCeilCommand() {
|
||||
Layout ceil = popBlock();
|
||||
return CeilingLayout::Builder(ceil);
|
||||
}
|
||||
|
||||
Layout TexParser::popFloorCommand() {
|
||||
Layout floor = popBlock();
|
||||
return FloorLayout::Builder(floor);
|
||||
}
|
||||
|
||||
Layout TexParser::popFracCommand() {
|
||||
Layout numerator = popBlock();
|
||||
Layout denominator = popBlock();
|
||||
FractionLayout l = FractionLayout::Builder(numerator, denominator);
|
||||
return l;
|
||||
}
|
||||
|
||||
Layout TexParser::popLeftCommand() {
|
||||
m_text++;
|
||||
return LeftParenthesisLayout::Builder();
|
||||
}
|
||||
|
||||
Layout TexParser::popRightCommand() {
|
||||
m_text++;
|
||||
return RightParenthesisLayout::Builder();
|
||||
}
|
||||
|
||||
Layout TexParser::popSqrtCommand() {
|
||||
while (*m_text == ' ') {
|
||||
m_text ++;
|
||||
}
|
||||
if (*m_text == '[') {
|
||||
m_text ++;
|
||||
Layout rootFactor = popText(']');
|
||||
Layout belowRoot = popBlock();
|
||||
return NthRootLayout::Builder(belowRoot, rootFactor);
|
||||
}
|
||||
else {
|
||||
return NthRootLayout::Builder(popBlock());
|
||||
}
|
||||
}
|
||||
|
||||
Layout TexParser::popSpaceCommand() {
|
||||
return LayoutHelper::String(" ", 1);
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
}
|
||||
57
apps/reader/tex_parser.h
Normal file
57
apps/reader/tex_parser.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef __TEX_PARSER_H__
|
||||
#define __TEX_PARSER_H__
|
||||
|
||||
#include <poincare_layouts.h>
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
namespace Reader
|
||||
{
|
||||
/// @brief Class used in the WordWrapTextView class to parse a Tex expression
|
||||
class TexParser {
|
||||
public:
|
||||
TexParser(const char * text, const char * endOfText);
|
||||
Layout getLayout();
|
||||
private:
|
||||
Layout popBlock();
|
||||
Layout popText(char stop);
|
||||
Layout popCommand();
|
||||
|
||||
// Expressions
|
||||
Layout popCeilCommand();
|
||||
Layout popFloorCommand();
|
||||
Layout popFracCommand();
|
||||
Layout popLeftCommand();
|
||||
Layout popRightCommand();
|
||||
Layout popSqrtCommand();
|
||||
Layout popSpaceCommand();
|
||||
Layout popOverrightarrowCommand();
|
||||
|
||||
//Symbols
|
||||
Layout popSymbolCommand(int SymbolIndex);
|
||||
|
||||
const char * m_text;
|
||||
const char * m_endOfText;
|
||||
bool m_hasError;
|
||||
|
||||
inline bool isCommandEnded(char c) const;
|
||||
|
||||
// Expressions that require specific handling
|
||||
static constexpr char const * k_ceilCommand = "ceil";
|
||||
static constexpr char const * k_floorCommand = "floor";
|
||||
static constexpr char const * k_fracCommand = "frac";
|
||||
static constexpr char const * k_leftCommand = "left";
|
||||
static constexpr char const * k_rightCommand = "right";
|
||||
static constexpr char const * k_sqrtCommand = "sqrt";
|
||||
static constexpr char const * k_spaceCommand = "space";
|
||||
static constexpr char const * k_overrightArrowCommand = "overrightarrow";
|
||||
|
||||
static constexpr int const k_NumberOfSymbols = 71;
|
||||
static constexpr int const k_NumberOfFunctionCommands = 32;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -117,7 +117,7 @@ const char * EndOfPrintableWord(const char * word, const char * end) {
|
||||
UTF8Decoder decoder(word);
|
||||
CodePoint codePoint = decoder.nextCodePoint();
|
||||
const char * result = word;
|
||||
while (codePoint != '\n' && codePoint != ' ' && codePoint != '%') {
|
||||
while (codePoint != '\n' && codePoint != ' ' && codePoint != '%' && codePoint != '$') {
|
||||
result = decoder.stringPosition();
|
||||
if (result >= end) {
|
||||
break;
|
||||
@@ -127,4 +127,21 @@ const char * EndOfPrintableWord(const char * word, const char * end) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const char * StartOfPrintableWord(const char * word, const char * start) {
|
||||
if (word == start) {
|
||||
return word;
|
||||
}
|
||||
UTF8Decoder decoder(start, word);
|
||||
CodePoint codePoint = decoder.previousCodePoint();
|
||||
const char * result = word;
|
||||
while (codePoint != '\n' && codePoint != ' ' && codePoint != '%' && codePoint != '$') {
|
||||
result = decoder.stringPosition();
|
||||
if (result <= start) {
|
||||
break;
|
||||
}
|
||||
codePoint = decoder.previousCodePoint();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ bool stringEndsWith(const char* str, const char* end);
|
||||
int filesWithExtension(const char* extension, External::Archive::File* files, int filesSize);
|
||||
void stringNCopy(char* dest, int max, const char* src, int len);
|
||||
const char * EndOfPrintableWord(const char * word, const char * end);
|
||||
const char * StartOfPrintableWord(const char * word, const char * start);
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
#include "word_wrap_view.h"
|
||||
#include "utility.h"
|
||||
#include "tex_parser.h"
|
||||
#include <poincare/expression.h>
|
||||
#include "../shared/poincare_helpers.h"
|
||||
#include <poincare/undefined.h>
|
||||
@@ -40,16 +41,17 @@ void WordWrapTextView::previousPage() {
|
||||
const int charWidth = m_font->glyphSize().width();
|
||||
const int charHeight = m_font->glyphSize().height();
|
||||
|
||||
const char * endOfWord = text() + m_pageOffset - 1;
|
||||
const char * startOfWord = UTF8Helper::BeginningOfWord(text(), endOfWord);
|
||||
const char * endOfFile = text() + m_length;
|
||||
const char * endOfWord = text() + m_pageOffset;
|
||||
const char * startOfWord = StartOfPrintableWord(endOfWord, text());
|
||||
|
||||
KDSize textSize = KDSizeZero;
|
||||
|
||||
KDPoint textEndPosition(m_frame.width() - k_margin, m_frame.height() - k_margin);
|
||||
|
||||
while(startOfWord>=text()) {
|
||||
startOfWord = UTF8Helper::BeginningOfWord(text(), endOfWord);
|
||||
endOfWord = UTF8Helper::EndOfWord(startOfWord);
|
||||
startOfWord = StartOfPrintableWord(endOfWord-1, text());
|
||||
//endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
|
||||
|
||||
if (*startOfWord == '%') {
|
||||
if (updateTextColorBackward(startOfWord)) {
|
||||
@@ -57,20 +59,28 @@ void WordWrapTextView::previousPage() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*startOfWord == '$' && *(endOfWord-1) == '$') {
|
||||
const int wordMaxLength = 128;
|
||||
char word[wordMaxLength];
|
||||
stringNCopy(word, wordMaxLength, startOfWord + 1, endOfWord-startOfWord-2);
|
||||
Poincare::Expression expr = Poincare::Expression::Parse(word, nullptr);
|
||||
if (expr.isUninitialized()) {
|
||||
expr = Poincare::Undefined::Builder();
|
||||
|
||||
if (*endOfWord == '$') {
|
||||
startOfWord = endOfWord - 1;
|
||||
while (*startOfWord != '$') {
|
||||
if (startOfWord < text()) {
|
||||
break; // File isn't rightly formated
|
||||
}
|
||||
startOfWord --;
|
||||
}
|
||||
Poincare::Layout layout = Shared::PoincareHelpers::CreateLayout(expr);
|
||||
textSize = layout.layoutSize();
|
||||
|
||||
startOfWord --;
|
||||
|
||||
TexParser parser = TexParser(startOfWord + 1, endOfWord - 2);
|
||||
Poincare::Layout layout = parser.getLayout();
|
||||
textSize = layout.layoutSize();
|
||||
}
|
||||
else {
|
||||
textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
|
||||
if (*startOfWord == '\\' || *(startOfWord + 1) == '$') {
|
||||
textSize = m_font->stringSizeUntil(startOfWord + 1, endOfWord);
|
||||
}
|
||||
else {
|
||||
textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
|
||||
}
|
||||
}
|
||||
KDPoint textStartPosition = KDPoint(textEndPosition.x()-textSize.width(), textEndPosition.y());
|
||||
|
||||
@@ -111,7 +121,7 @@ void WordWrapTextView::previousPage() {
|
||||
m_pageOffset = 0;
|
||||
}
|
||||
else {
|
||||
m_pageOffset = UTF8Helper::EndOfWord(startOfWord) - text() + 1;
|
||||
m_pageOffset = EndOfPrintableWord(startOfWord, endOfFile) - text() + 1;
|
||||
}
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
@@ -121,7 +131,12 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
|
||||
const char * endOfFile = text() + m_length;
|
||||
const char * startOfWord = text() + m_pageOffset;
|
||||
const char * endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
|
||||
const char * endOfWord;
|
||||
|
||||
if (*startOfWord != '$') {
|
||||
endOfWord = EndOfPrintableWord(startOfWord, endOfFile);
|
||||
} // Else we don't need to update endOfWord
|
||||
|
||||
KDPoint textPosition(k_margin, k_margin);
|
||||
|
||||
const int wordMaxLength = 128;
|
||||
@@ -154,18 +169,26 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (*startOfWord == '$' && *(endOfWord-1) == '$') { // Look for expression
|
||||
stringNCopy(word, wordMaxLength, startOfWord + 1, endOfWord-startOfWord-2);
|
||||
Poincare::Expression expr = Poincare::Expression::Parse(word, nullptr);
|
||||
if (expr.isUninitialized()) {
|
||||
expr = Poincare::Undefined::Builder();
|
||||
|
||||
if (*startOfWord == '$') { // Look for expression
|
||||
endOfWord = startOfWord + 1;
|
||||
while (*endOfWord != '$') {
|
||||
if (endOfWord > endOfFile) {
|
||||
break; // If we are here, it's bad...
|
||||
}
|
||||
endOfWord ++;
|
||||
}
|
||||
layout = Shared::PoincareHelpers::CreateLayout(expr);
|
||||
endOfWord ++;
|
||||
|
||||
TexParser parser = TexParser(startOfWord + 1, endOfWord - 1);
|
||||
layout = parser.getLayout();
|
||||
textSize = layout.layoutSize();
|
||||
toDraw = ToDraw::Expression;
|
||||
}
|
||||
else {
|
||||
if (*startOfWord == '\\' || *(startOfWord + 1) == '$') {
|
||||
startOfWord ++;
|
||||
}
|
||||
textSize = m_font->stringSizeUntil(startOfWord, endOfWord);
|
||||
stringNCopy(word, wordMaxLength, startOfWord, endOfWord-startOfWord);
|
||||
toDraw = ToDraw::Text;
|
||||
@@ -187,7 +210,7 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
|
||||
if (toDraw == ToDraw::Expression) {
|
||||
layout.draw(ctx, textPosition, m_textColor);
|
||||
layout.draw(ctx, textPosition, m_textColor, m_backgroundColor);
|
||||
}
|
||||
else if (toDraw == ToDraw::Text) {
|
||||
ctx->drawString(word, textPosition, m_font, m_textColor, m_backgroundColor);
|
||||
@@ -224,7 +247,10 @@ void WordWrapTextView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
|
||||
textPosition = nextTextPosition;
|
||||
endOfWord = EndOfPrintableWord(startOfWord+1, endOfFile);
|
||||
|
||||
if (*startOfWord != '$') {
|
||||
endOfWord = EndOfPrintableWord(startOfWord+1, endOfFile);
|
||||
} // Else we don't need to update endOfWord
|
||||
}
|
||||
|
||||
m_nextPageOffset = startOfWord - text();
|
||||
|
||||
@@ -39,7 +39,7 @@ openocd:
|
||||
|
||||
# The flasher target is defined here because otherwise $(%_src) has not been
|
||||
# fully filled
|
||||
flasher_src = $(ion_src) $(ion_device_flasher_src) $(liba_src) $(kandinsky_src)
|
||||
flasher_src = $(ion_src) $(ion_device_flasher_src) $(liba_src) $(simple_kandinsky_src)
|
||||
$(BUILD_DIR)/flasher.light.$(EXE): $(call flavored_object_for,$(flasher_src),light usbxip)
|
||||
$(BUILD_DIR)/flasher.verbose.$(EXE): $(call flavored_object_for,$(flasher_src),usbxip)
|
||||
$(BUILD_DIR)/flasher.verbose.flash.$(EXE): $(call flavored_object_for,$(flasher_src))
|
||||
@@ -48,7 +48,7 @@ $(BUILD_DIR)/flasher.%.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld
|
||||
$(BUILD_DIR)/flasher.%.flash.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/$(MODEL)/internal_flash.ld
|
||||
|
||||
#TODO Do not build all apps... Put elsewhere?
|
||||
bench_src = $(ion_src) $(liba_src) $(kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_device_bench_src)
|
||||
bench_src = $(ion_src) $(liba_src) $(default_kandinsky_src) $(poincare_src) $(libaxx_src) $(app_shared_src) $(ion_device_bench_src)
|
||||
$(BUILD_DIR)/bench.ram.$(EXE): $(call flavored_object_for,$(bench_src),consoleuart usbxip)
|
||||
$(BUILD_DIR)/bench.ram.$(EXE): LDFLAGS += -Lion/src/$(PLATFORM)/bench
|
||||
$(BUILD_DIR)/bench.ram.$(EXE): LDSCRIPT = ion/src/$(PLATFORM)/shared/ram.ld
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
HANDY_TARGETS += test.external_flash.write test.external_flash.read
|
||||
|
||||
$(BUILD_DIR)/test.external_flash.%.$(EXE): LDSCRIPT = ion/test/device/n0110/external_flash_tests.ld
|
||||
test_external_flash_src = $(ion_src) $(liba_src) $(libaxx_src) $(kandinsky_src) $(poincare_src) $(ion_device_dfu_relogated_src) $(runner_src)
|
||||
test_external_flash_src = $(ion_src) $(liba_src) $(libaxx_src) $(default_kandinsky_src) $(poincare_src) $(ion_device_dfu_relogated_src) $(runner_src)
|
||||
$(BUILD_DIR)/test.external_flash.read.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_external_flash_read_symbols.o $(call object_for,$(test_external_flash_src) $(test_ion_external_flash_read_src))
|
||||
$(BUILD_DIR)/test.external_flash.write.$(EXE): $(BUILD_DIR)/quiz/src/test_ion_external_flash_write_symbols.o $(call object_for,$(test_external_flash_src) $(test_ion_external_flash_write_src))
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ HANDY_TARGETS_EXTENSIONS ?=
|
||||
|
||||
# Epsilon base target
|
||||
|
||||
base_src = $(ion_src) $(liba_src) $(kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src)
|
||||
base_src = $(ion_src) $(liba_src) $(default_kandinsky_src) $(escher_src) $(libaxx_src) $(poincare_src) $(python_src)
|
||||
|
||||
epsilon_src = $(base_src) $(apps_src)
|
||||
|
||||
|
||||
@@ -21,10 +21,8 @@ kandinsky_src += $(addprefix kandinsky/src/,\
|
||||
rect.cpp \
|
||||
)
|
||||
|
||||
kandinsky_src += $(addprefix kandinsky/fonts/, \
|
||||
LargeFont.ttf \
|
||||
SmallFont.ttf \
|
||||
)
|
||||
simple_kandinsky_src := $(kandinsky_src)
|
||||
default_kandinsky_src := $(kandinsky_src)
|
||||
|
||||
tests_src += $(addprefix kandinsky/test/,\
|
||||
color.cpp\
|
||||
@@ -53,16 +51,53 @@ $(eval $(call rule_for, \
|
||||
|
||||
RASTERIZER := $(BUILD_DIR)/kandinsky/fonts/rasterizer
|
||||
|
||||
# Define a rasterizing recipe. Parameters : font name, size, packed_width, packed_height
|
||||
# Define a rasterizing recipe. Parameters : font source, font name, size, packed_width, packed_height
|
||||
define raster_font
|
||||
$(call rule_for, \
|
||||
RASTER, \
|
||||
kandinsky/fonts/$(1).cpp, \
|
||||
kandinsky/fonts/$(2).cpp, \
|
||||
kandinsky/fonts/$(1).ttf $$(RASTERIZER), \
|
||||
$$(RASTERIZER) $$< $(2) $(2) $(3) $(4) $(1) $$@ $(if $(HAS_LIBPNG),$$(basename $$@).png), \
|
||||
$$(RASTERIZER) $$< $(3) $(4) $(4) $(5) $(6) $(1) $$@ $(if $(HAS_LIBPNG),$$(basename $$@).png), \
|
||||
global \
|
||||
)
|
||||
endef
|
||||
|
||||
$(eval $(call raster_font,SmallFont,12,7,14))
|
||||
$(eval $(call raster_font,LargeFont,16,10,18))
|
||||
ifdef HAS_READER
|
||||
|
||||
kandinsky_src += $(addprefix kandinsky/fonts/, \
|
||||
LargeFontExtended.ttf \
|
||||
SmallFontExtended.ttf \
|
||||
LargeFontSimple.ttf \
|
||||
SmallFontSimple.ttf \
|
||||
)
|
||||
|
||||
default_kandinsky_src += $(addprefix kandinsky/fonts/, \
|
||||
LargeFontExtended.ttf \
|
||||
SmallFontExtended.ttf \
|
||||
)
|
||||
|
||||
simple_kandinsky_src += $(addprefix kandinsky/fonts/, \
|
||||
LargeFontSimple.ttf \
|
||||
SmallFontSimple.ttf \
|
||||
)
|
||||
|
||||
$(eval $(call raster_font,SmallFont,SmallFontExtended,1,12,7,14))
|
||||
$(eval $(call raster_font,LargeFont,LargeFontExtended,1,16,10,18))
|
||||
|
||||
$(eval $(call raster_font,SmallFont,SmallFontSimple,0,12,7,14))
|
||||
$(eval $(call raster_font,LargeFont,LargeFontSimple,0,16,10,18))
|
||||
|
||||
else
|
||||
|
||||
kandinsky_src += $(addprefix kandinsky/fonts/, \
|
||||
LargeFont.ttf \
|
||||
SmallFont.ttf \
|
||||
)
|
||||
|
||||
simple_kandinsky_src = $(kandinsky_src)
|
||||
default_kandinsky_src = $(kandinsky_src)
|
||||
|
||||
$(eval $(call raster_font,SmallFont,SmallFontSimple,0,12,7,14))
|
||||
$(eval $(call raster_font,LargeFont,LargeFontSimple,0,16,10,18))
|
||||
|
||||
endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
/* This array lists the code points that are rasterized by rasterizer.c. We put
|
||||
* most characters from the LATIN charset, and some mathematical characters. */
|
||||
|
||||
uint32_t CodePoints[] = {
|
||||
uint32_t SimpleCodePoints[] = {
|
||||
0x20, // // SPACE
|
||||
0x21, // ! // EXCLAMATION MARK
|
||||
0x22, // " // QUOTATION MARK
|
||||
@@ -153,6 +153,206 @@ uint32_t CodePoints[] = {
|
||||
0x1d422, // 𝐢 // MATHEMATICAL BOLD SMALL I"
|
||||
};
|
||||
|
||||
int NumberOfCodePoints = sizeof(CodePoints)/sizeof(CodePoints[0]);
|
||||
uint32_t ExtendedCodePoints[] = {
|
||||
0x20, // // SPACE
|
||||
0x21, // ! // EXCLAMATION MARK
|
||||
0x22, // " // QUOTATION MARK
|
||||
0x23, // # // NUMBER SIGN
|
||||
0x24, // $ // DOLLAR SIGN
|
||||
0x25, // % // PERCENT SIGN
|
||||
0x26, // & // AMPERSAND
|
||||
0x27, // ' // APOSTROPHE
|
||||
0x28, // ( // LEFT PARENTHESIS
|
||||
0x29, // ) // RIGHT PARENTHESIS
|
||||
0x2a, // * // ASTERISK
|
||||
0x2b, // + // PLUS SIGN
|
||||
0x2c, // , // COMMA
|
||||
0x2d, // - // HYPHEN-MINUS
|
||||
0x2e, // . // FULL STOP
|
||||
0x2f, // / // SOLIDUS
|
||||
0x30, // 0 // DIGIT ZERO
|
||||
0x31, // 1 // DIGIT ONE
|
||||
0x32, // 2 // DIGIT TWO
|
||||
0x33, // 3 // DIGIT THREE
|
||||
0x34, // 4 // DIGIT FOUR
|
||||
0x35, // 5 // DIGIT FIVE
|
||||
0x36, // 6 // DIGIT SIX
|
||||
0x37, // 7 // DIGIT SEVEN
|
||||
0x38, // 8 // DIGIT EIGHT
|
||||
0x39, // 9 // DIGIT NINE
|
||||
0x3a, // : // COLON
|
||||
0x3b, // ; // SEMICOLON
|
||||
0x3c, // < // LESS-THAN SIGN
|
||||
0x3d, // = // EQUALS SIGN
|
||||
0x3e, // > // GREATER-THAN SIGN
|
||||
0x3f, // ? // QUESTION MARK
|
||||
0x40, // @ // COMMERCIAL AT
|
||||
0x41, // A // LATIN CAPITAL LETTER A
|
||||
0x42, // B // LATIN CAPITAL LETTER B
|
||||
0x43, // C // LATIN CAPITAL LETTER C
|
||||
0x44, // D // LATIN CAPITAL LETTER D
|
||||
0x45, // E // LATIN CAPITAL LETTER E
|
||||
0x46, // F // LATIN CAPITAL LETTER F
|
||||
0x47, // G // LATIN CAPITAL LETTER G
|
||||
0x48, // H // LATIN CAPITAL LETTER H
|
||||
0x49, // I // LATIN CAPITAL LETTER I
|
||||
0x4a, // J // LATIN CAPITAL LETTER J
|
||||
0x4b, // K // LATIN CAPITAL LETTER K
|
||||
0x4c, // L // LATIN CAPITAL LETTER L
|
||||
0x4d, // M // LATIN CAPITAL LETTER M
|
||||
0x4e, // N // LATIN CAPITAL LETTER N
|
||||
0x4f, // O // LATIN CAPITAL LETTER O
|
||||
0x50, // P // LATIN CAPITAL LETTER P
|
||||
0x51, // Q // LATIN CAPITAL LETTER Q
|
||||
0x52, // R // LATIN CAPITAL LETTER R
|
||||
0x53, // S // LATIN CAPITAL LETTER S
|
||||
0x54, // T // LATIN CAPITAL LETTER T
|
||||
0x55, // U // LATIN CAPITAL LETTER U
|
||||
0x56, // V // LATIN CAPITAL LETTER V
|
||||
0x57, // W // LATIN CAPITAL LETTER W
|
||||
0x58, // X // LATIN CAPITAL LETTER X
|
||||
0x59, // Y // LATIN CAPITAL LETTER Y
|
||||
0x5a, // Z // LATIN CAPITAL LETTER Z
|
||||
0x5b, // [ // LEFT SQUARE BRACKET
|
||||
0x5c, // \ // REVERSE SOLIDUS
|
||||
0x5d, // ] // RIGHT SQUARE BRACKET
|
||||
0x5e, // ^ // CIRCUMFLEX ACCENT
|
||||
0x5f, // _ // LOW LINE
|
||||
0x60, // ` // GRAVE ACCENT
|
||||
0x61, // a // LATIN SMALL LETTER A
|
||||
0x62, // b // LATIN SMALL LETTER B
|
||||
0x63, // c // LATIN SMALL LETTER C
|
||||
0x64, // d // LATIN SMALL LETTER D
|
||||
0x65, // e // LATIN SMALL LETTER E
|
||||
0x66, // f // LATIN SMALL LETTER F
|
||||
0x67, // g // LATIN SMALL LETTER G
|
||||
0x68, // h // LATIN SMALL LETTER H
|
||||
0x69, // i // LATIN SMALL LETTER I
|
||||
0x6a, // j // LATIN SMALL LETTER J
|
||||
0x6b, // k // LATIN SMALL LETTER K
|
||||
0x6c, // l // LATIN SMALL LETTER L
|
||||
0x6d, // m // LATIN SMALL LETTER M
|
||||
0x6e, // n // LATIN SMALL LETTER N
|
||||
0x6f, // o // LATIN SMALL LETTER O
|
||||
0x70, // p // LATIN SMALL LETTER P
|
||||
0x71, // q // LATIN SMALL LETTER Q
|
||||
0x72, // r // LATIN SMALL LETTER R
|
||||
0x73, // s // LATIN SMALL LETTER S
|
||||
0x74, // t // LATIN SMALL LETTER T
|
||||
0x75, // u // LATIN SMALL LETTER U
|
||||
0x76, // v // LATIN SMALL LETTER V
|
||||
0x77, // w // LATIN SMALL LETTER W
|
||||
0x78, // x // LATIN SMALL LETTER X
|
||||
0x79, // y // LATIN SMALL LETTER Y
|
||||
0x7a, // z // LATIN SMALL LETTER Z
|
||||
0x7b, // { // LEFT CURLY BRACKET
|
||||
0x7c, // | // VERTICAL LINE
|
||||
0x7d, // } // RIGHT CURLY BRACKET
|
||||
0x7e, // ~ // TILDE
|
||||
|
||||
0xb0, // ° // DEGREE SIGN
|
||||
0xb1, // ± // PLUS OR MINUS
|
||||
0xb7, // · // MIDDLE DOT
|
||||
|
||||
0xc6, // Æ // LATIN CAPITAL LETTER AE
|
||||
0xd0, // Ð // LATIN CAPITAL LETTER ETH
|
||||
0xd7, // × // MULTIPLICATION SIGN
|
||||
0xd8, // Ø // LATIN CAPITAL LETTER O WITH STROKE
|
||||
0xde, // Þ // LATIN CAPITAL LETTER THORN
|
||||
0xdf, // ß // LATIN SMALL LETTER SHARP S
|
||||
0xe6, // æ // LATIN SMALL LETTER AE
|
||||
0xf0, // ð // LATIN SMALL LETTER ETH
|
||||
0xf7, // ÷ // DIVISION SIGN
|
||||
0xf8, // ø // LATIN SMALL LETTER O WITH STROKE
|
||||
0xfe, // þ // LATIN SMALL LETTER THORN
|
||||
|
||||
0x300, // ̀ // COMBINING GRAVE ACCENT
|
||||
0x301, // ́ // COMBINING ACUTE ACCENT
|
||||
0x302, // ̂ // COMBINING CIRCUMFLEX ACCENT
|
||||
0x303, // ̃ // COMBINING TILDE
|
||||
0x305, // ̅ // COMBINING OVERLINE
|
||||
0x308, // ̈ // COMBINING DIAERESIS
|
||||
0x30a, // ̊ // COMBINING RING ABOVE
|
||||
0x30b, // ˝// COMBINING DOUBLE ACUTE ACCENT
|
||||
0x327, // ̧ // COMBINING CEDILLA
|
||||
|
||||
0x391, // Α // GREEK CAPITAL LETTER ALPHA
|
||||
0x392, // Β // GREEK CAPITAL LETTER BETA
|
||||
0x393, // Γ // GREEK CAPITAL LETTER GAMMA
|
||||
0x394, // Δ // GREEK CAPITAL LETTER DELTA
|
||||
0x395, // Ε // GREEK CAPITAL LETTER EPSILON
|
||||
0x396, // Ζ // GREEK CAPITAL LETTER ZETA
|
||||
0x397, // Η // GREEK CAPITAL LETTER ETA
|
||||
0x398, // Θ // GREEK CAPITAL LETTER THETA
|
||||
0x399, // Ι // GREEK CAPITAL LETTER IOTA
|
||||
0x39a, // Κ // GREEK CAPITAL LETTER KAPPA
|
||||
0x39b, // Λ // GREEK CAPITAL LETTER LAMBDA
|
||||
0x39c, // Μ // GREEK CAPITAL LETTER MU
|
||||
0x39d, // Ν // GREEK CAPITAL LETTER NU
|
||||
0x39e, // Ξ // GREEK CAPITAL LETTER KSI
|
||||
0x39f, // Ο // GREEK CAPITAL LETTER OMICRON
|
||||
0x3a0, // Π // GREEK CAPITAL LETTER PI
|
||||
0x3a1, // Ρ // GREEK CAPITAL LETTER RHO
|
||||
0x3a3, // Σ // GREEK CAPITAL LETTER SIGMA
|
||||
0x3a4, // Τ // GREEK CAPITAL LETTER TAU
|
||||
0x3a5, // Υ // GREEK CAPITAL LETTER UPSILON
|
||||
0x3a6, // Φ // GREEK CAPITAL LETTER PHI
|
||||
0x3a7, // Χ // GREEK CAPITAL LETTER KHI
|
||||
0x3a8, // Ψ // GREEK CAPITAL LETTER PSI
|
||||
0x3a9, // Ω // GREEK CAPITAL LETTER OMEGA
|
||||
0x3b1, // α // GREEK SMALL LETTER ALPHA
|
||||
0x3b2, // β // GREEK SMALL LETTER BETA
|
||||
0x3b3, // γ // GREEK SMALL LETTER GAMMA
|
||||
0x3b4, // δ // GREEK SMALL LETTER DELTA
|
||||
0x3b5, // ε // GREEK SMALL LETTER EPSILON
|
||||
0x3b6, // ζ // GREEK SMALL LETTER ZETA
|
||||
0x3b7, // η // GREEK SMALL LETTER ETA
|
||||
0x3b8, // θ // GREEK SMALL LETTER THETA
|
||||
0x3b9, // ι // GREEK SMALL LETTER IOTA
|
||||
0x3ba, // κ // GREEK SMALL LETTER KAPPA
|
||||
0x3bb, // λ // GREEK SMALL LETTER LAMBDA
|
||||
0x3bc, // μ // GREEK SMALL LETTER MU
|
||||
0x3bd, // ν // GREEK SMALL LETTER NU
|
||||
0x3be, // ξ // GREEK SMALL LETTER KSI
|
||||
0x3bf, // ο // GREEK SMALL LETTER OMICRON
|
||||
0x3c0, // π // GREEK SMALL LETTER PI
|
||||
0x3c1, // ρ // GREEK SMALL LETTER RHO
|
||||
0x3c3, // σ // GREEK SMALL LETTER SIGMA
|
||||
0x3c4, // τ // GREEK SMALL LETTER TAU
|
||||
0x3c5, // υ // GREEK SMALL LETTER UPSILON
|
||||
0x3c6, // φ // GREEK SMALL LETTER PHI
|
||||
0x3c7, // χ // GREEK SMALL LETTER KHI
|
||||
0x3c8, // ψ // GREEK SMALL LETTER PSI
|
||||
0x3c9, // ω // GREEK SMALL LETTER OMEGA
|
||||
0x1d07, // ᴇ // LATIN LETTER SMALL CAPITAL E
|
||||
0x212f, // ℯ // SCRIPT SMALL E
|
||||
0x2190, // ← // BACKWARD ARROW (leftarrow)
|
||||
0x2191, // ↑ // TOP ARROW (uparrow)
|
||||
0x2192, // → // FORWARD ARROW (rightarrow)
|
||||
0x2193, // ↓ // BOTTOM ARROW (downarrow)
|
||||
0x2194, // ↔ // BACKWARD FORWARD ARROW (leftrightarrow)
|
||||
0x2195, // ↕ // TOP BOTTOM ARROW (updownarrow)
|
||||
0x21d0, // ⇐ // DOUBLE BACKWARD ARROW (Leftarrow)
|
||||
0x21d1, // ⇑ // DOUBLE TOP ARROW (Uparrow)
|
||||
0x21d2, // ⇒ // DOUBLE FORWARD ARROW (Rightarrow)
|
||||
0x21d3, // ⇓ // DOUBLE BOTTOM ARROW (Downarrow)
|
||||
0x2200, // ∀ // FORALL
|
||||
0x2202, // ∂ // PARTIAL
|
||||
0x2203, // ∃ // EXIST
|
||||
0x2211, // ∑ // N-ARY SUMMATION
|
||||
0x221a, // √ // SQUARE ROOT
|
||||
0x221e, // ∞ // INFINITY
|
||||
0x222b, // ∫ // INTEGRAL
|
||||
0x2248, // ≈ // ALMOST EQUAL TO
|
||||
0x2260, // ≠ // NOT EQUAL TO
|
||||
0x2261, // ≡ // IS CONGRUENT TO
|
||||
0x2264, // ≤ // LESS-THAN OR EQUAL TO
|
||||
0x2265, // ≥ // GREATER-THAN OR EQUAL TO
|
||||
0xFFFD, // <20> // REPLACEMENT CHARACTER
|
||||
0x1d422, // 𝐢 // MATHEMATICAL BOLD SMALL I"
|
||||
};
|
||||
|
||||
int NumberOfSimpleCodePoints = sizeof(SimpleCodePoints)/sizeof(SimpleCodePoints[0]);
|
||||
int NumberOfExtendedCodePoints = sizeof(ExtendedCodePoints)/sizeof(ExtendedCodePoints[0]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "code_points.h"
|
||||
|
||||
#include "../../ion/src/external/lz4/lz4hc.h"
|
||||
|
||||
|
||||
@@ -49,17 +50,18 @@ int main(int argc, char * argv[]) {
|
||||
FT_Face face;
|
||||
image_t bitmap_image;
|
||||
|
||||
int expectedNumberOfArguments = 8;
|
||||
int expectedNumberOfArguments = 9;
|
||||
#ifdef GENERATE_PNG
|
||||
expectedNumberOfArguments = 9;
|
||||
expectedNumberOfArguments = 10;
|
||||
#endif
|
||||
if (argc != expectedNumberOfArguments) {
|
||||
#ifdef GENERATE_PNG
|
||||
fprintf(stderr, "Usage: %s font_file glyph_width glyph_height font_name output_cpp output_png\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s font_file extended glyph_width glyph_height font_name output_cpp output_png\n", argv[0]);
|
||||
#else
|
||||
fprintf(stderr, "Usage: %s font_file glyph_width glyph_height font_name output_cpp\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s font_file extended glyph_width glyph_height font_name output_cpp\n", argv[0]);
|
||||
#endif
|
||||
fprintf(stderr, " font_file: Path of the font file to load\n");
|
||||
fprintf(stderr, " extended: 0 if simple set of code points, else 1\n");
|
||||
fprintf(stderr, " glyph_width: Width of bitmap glyphs, in pixels\n");
|
||||
fprintf(stderr, " glyph_height: Height of bitmap glyphs, in pixels\n");
|
||||
fprintf(stderr, " packed_glyph_width: Minimal glyph width in pixels. Pass 0 if unsure.\n");
|
||||
@@ -73,16 +75,20 @@ int main(int argc, char * argv[]) {
|
||||
}
|
||||
|
||||
char * font_file = argv[1];
|
||||
int requested_glyph_width = atoi(argv[2]);
|
||||
int requested_glyph_height = atoi(argv[3]);
|
||||
int packed_glyph_width = atoi(argv[4]);
|
||||
int packed_glyph_height = atoi(argv[5]);
|
||||
char * font_name = argv[6];
|
||||
char * output_cpp = argv[7];
|
||||
int extended_set = atoi(argv[2]);
|
||||
int requested_glyph_width = atoi(argv[3]);
|
||||
int requested_glyph_height = atoi(argv[4]);
|
||||
int packed_glyph_width = atoi(argv[5]);
|
||||
int packed_glyph_height = atoi(argv[6]);
|
||||
char * font_name = argv[7];
|
||||
char * output_cpp = argv[8];
|
||||
#ifdef GENERATE_PNG
|
||||
char * output_png = argv[8];
|
||||
char * output_png = argv[9];
|
||||
#endif
|
||||
|
||||
uint32_t * CodePoints = extended_set ? ExtendedCodePoints : SimpleCodePoints;
|
||||
int NumberOfCodePoints = extended_set ? NumberOfExtendedCodePoints : NumberOfSimpleCodePoints;
|
||||
|
||||
ENSURE(!FT_Init_FreeType(&library), "Initializing library");
|
||||
|
||||
// 0 means we're picking the first face in the provided file
|
||||
|
||||
@@ -155,7 +155,7 @@ KDFont::GlyphIndex KDFont::indexForCodePoint(CodePoint c) const {
|
||||
return endPair->glyphIndex();
|
||||
}
|
||||
NoMatchingGlyph:
|
||||
assert(CodePoints[IndexForReplacementCharacterCodePoint] == 0xFFFD);
|
||||
assert(SimpleCodePoints[IndexForReplacementCharacterCodePoint] == 0xFFFD);
|
||||
return IndexForReplacementCharacterCodePoint;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -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