[Update] Epsilon 15.3.1

This commit is contained in:
Joachim LF
2021-01-21 17:27:39 +01:00
700 changed files with 15118 additions and 7297 deletions

View File

@@ -177,6 +177,9 @@ void Turtle::setVisible(bool visible) {
void Turtle::write(const char * string) {
// We erase the turtle to redraw it on top of the text
if (isOutOfBounds()) {
return;
}
erase();
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
KDContext * ctx = KDIonContext::sharedContext();
@@ -195,6 +198,10 @@ void Turtle::viewDidDisappear() {
m_drawn = false;
}
bool Turtle::isOutOfBounds() const {
return absF(x()) > k_maxPosition || absF(y()) > k_maxPosition;
};
// Private functions
void Turtle::setHeadingPrivate(mp_float_t angle) {
@@ -255,6 +262,7 @@ bool Turtle::hasDotBuffers() {
}
KDRect Turtle::iconRect() const {
assert(!isOutOfBounds());
KDPoint iconOffset = KDPoint(-k_iconSize/2, -k_iconSize/2);
return KDRect(position().translatedBy(iconOffset), k_iconSize, k_iconSize);
}
@@ -262,7 +270,7 @@ KDRect Turtle::iconRect() const {
bool Turtle::draw(bool force) {
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
if ((m_speed > 0 || force) && m_visible && !m_drawn && hasUnderneathPixelBuffer()) {
if ((m_speed > 0 || force) && m_visible && !m_drawn && hasUnderneathPixelBuffer() && !isOutOfBounds()) {
KDContext * ctx = KDIonContext::sharedContext();
// Get the pixels underneath the turtle
@@ -344,7 +352,7 @@ bool Turtle::dot(mp_float_t x, mp_float_t y) {
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()->displaySandbox();
// Draw the dot if the pen is down
if (m_penDown && hasDotBuffers()) {
if (m_penDown && hasDotBuffers() && !isOutOfBounds()) {
KDContext * ctx = KDIonContext::sharedContext();
KDRect rect(
position(x, y).translatedBy(KDPoint(-m_penSize/2, -m_penSize/2)),
@@ -369,6 +377,7 @@ bool Turtle::dot(mp_float_t x, mp_float_t y) {
void Turtle::drawPaw(PawType type, PawPosition pos) {
assert(!m_drawn);
assert(m_underneathPixelBuffer != nullptr);
assert(!isOutOfBounds());
KDCoordinate pawOffset = 5;
constexpr float crawlOffset = 0.6f;
constexpr float angles[] = {M_PI_4, 3*M_PI_4, -3*M_PI_4, -M_PI_4};
@@ -391,7 +400,7 @@ void Turtle::drawPaw(PawType type, PawPosition pos) {
}
void Turtle::erase() {
if (!m_drawn || m_underneathPixelBuffer == nullptr) {
if (!m_drawn || m_underneathPixelBuffer == nullptr || isOutOfBounds()) {
return;
}
KDContext * ctx = KDIonContext::sharedContext();

View File

@@ -82,6 +82,13 @@ public:
void viewDidDisappear();
/* isOutOfBounds returns true if nothing should be drawn at current position.
* We avoid drawing at extreme position (far from screen bounds) to prevent
* coordinate overflows. However, this solution makes the turtle go faster
* when out of bound, and can prevent text that would have been visible to be
* drawn. We use very large bounds to temper these effects. */
bool isOutOfBounds() const;
private:
static constexpr mp_float_t k_headingScale = M_PI / 180;
/* The Y axis is oriented upwards in Turtle and downwards in Kandinsky, so we
@@ -94,6 +101,7 @@ private:
static constexpr KDColor k_defaultColor = KDColorBlack;
static constexpr uint8_t k_defaultPenSize = 1;
static constexpr const KDFont * k_font = KDFont::LargeFont;
static constexpr mp_float_t k_maxPosition = KDCOORDINATE_MAX * 0.75f;
enum class PawType : uint8_t {
FrontRight = 0,

View File

@@ -164,15 +164,16 @@ void MicroPython::init(void * heapStart, void * heapEnd) {
static mp_obj_t pystack[1024];
mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]);
#endif
volatile int stackTop;
void * stackTopAddress = (void *)(&stackTop);
/* We delimit the stack part that will be used by Python. The stackTop is the
* address of the first object that can be allocated on Python stack. This
* boundaries are used:
* - by gc_collect to determine where to collect roots of the objects that
* must be kept on the heap
* - to check if the maximal recursion depth has been reached. */
* - to check if the maximal recursion depth has been reached.
* Current stack pointer could go backward after initialization. A stack start
* pointer defined in main is therefore used. */
void * stackTopAddress = Ion::stackStart();
#if MP_PORT_USE_STACK_SYMBOLS
mp_stack_set_top(stackTopAddress);
size_t stackLimitInBytes = (char *)stackTopAddress - (char *)&_stack_end;
@@ -218,7 +219,7 @@ void MicroPython::collectRootsAtAddress(char * address, int byteLength) {
alignedByteLength += reinterpret_cast<uintptr_t>(address) & bitMaskOnes;
assert(alignedAddress % ((uintptr_t)sizeof(uintptr_t)) == 0);
gc_collect_root((void **)alignedAddress, byteLength / sizeof(uintptr_t));
gc_collect_root((void **)alignedAddress, alignedByteLength / sizeof(uintptr_t));
}
KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
@@ -243,7 +244,8 @@ KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
NamedColor("pink", Palette::Pink),
NamedColor("orange", Palette::Orange),
NamedColor("purple", Palette::Purple),
NamedColor("grey", Palette::GreyDark),
NamedColor("gray", Palette::GrayDark),
NamedColor("grey", Palette::GrayDark),
NamedColor("cyan", Palette::Cyan),
NamedColor("magenta", Palette::Magenta)
};
@@ -262,12 +264,12 @@ KDColor MicroPython::Color::Parse(mp_obj_t input, Mode mode){
return KDColor::RGB24(colorInt);
}
mp_float_t greyLevel = mp_obj_float_get(mp_parse_num_decimal(color, strlen(color), false, false, NULL));
if (greyLevel >= 0.0 && greyLevel <= 1.0) {
uint8_t color = maxColorIntensity * (float) greyLevel;
mp_float_t grayLevel = mp_obj_float_get(mp_parse_num_decimal(color, strlen(color), false, false, NULL));
if (grayLevel >= 0.0 && grayLevel <= 1.0) {
uint8_t color = maxColorIntensity * (float) grayLevel;
return KDColor::RGB888(color, color, color);
}
mp_raise_ValueError("Grey levels are between 0.0 and 1.0");
mp_raise_ValueError("Gray levels are between 0.0 and 1.0");
} else if(mp_obj_is_int(input)) {
mp_raise_TypeError("Int are not colors");
//See https://github.com/numworks/epsilon/issues/1533#issuecomment-618443492