[python/turtle] Prevent position overflow from turtle

Change-Id: Ieb8a7b64bab1ce6fac23ca4c8dcb43467b8d4d5c
This commit is contained in:
Hugo Saint-Vignes
2020-09-23 15:27:14 +02:00
committed by Émilie Feral
parent 6a9a5dbe27
commit 7e5ddcd36b
2 changed files with 20 additions and 3 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,