Files
Upsilon/apps/shared/function.h
Yaya-Cout 3b293c822a [apps/graph] Added a color menu in graph and list (#189)
* Revert "[github/workflows] Update Metrics to remove NumWorksBot"

This reverts commit 110f333122.

* Added a color menu in graph and list

* Fixed color select display issue and build issue

* Changed color_cell to a circle

* Revert "Changed color_cell to a circle"

This reverts commit 28dddb42af.

* Color_cell with mask

* Fixed build issue

* Color selection : Added right handle and color name display in menu

* Fixed constexpr static colorMask

* Changed font in color_parameter_controller

* Fix building without debug

* Re-Fix building without debug

* Update colors

Co-authored-by: Hugo Saint-Vignes <hugo.saint-vignes@numworks.com>
Co-authored-by: Joachim LF <joachimlf@pm.me>
2022-03-23 08:36:23 +01:00

108 lines
4.2 KiB
C++

#ifndef SHARED_FUNCTION_H
#define SHARED_FUNCTION_H
#include <poincare/function.h>
#include <poincare/symbol.h>
#include <escher/i18n.h>
#include "expression_model_handle.h"
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif
namespace Shared {
class Function : public ExpressionModelHandle {
public:
enum class NameNotCompliantError {
None = 0,
CharacterNotAllowed,
NameCannotStartWithNumber,
ReservedName
};
static NameNotCompliantError BaseNameCompliant(const char * baseName);
/* Possible arguments: n, x, t, θ
* The CodePoint θ is two char long. */
constexpr static int k_parenthesedArgumentCodePointLength = 3;
constexpr static int k_parenthesedThetaArgumentByteLength = 4;
constexpr static int k_parenthesedXNTArgumentByteLength = 3;
constexpr static int k_maxNameWithArgumentSize = Poincare::SymbolAbstract::k_maxNameSize + k_parenthesedThetaArgumentByteLength; /* Function name and null-terminating char + "(θ)" */;
// Constructors
Function(Ion::Storage::Record record) : ExpressionModelHandle(record){}
// Properties
bool isActive() const;
KDColor color() const;
void setActive(bool active);
void setColor(KDColor color);
// Definition Interval
virtual bool shouldClipTRangeToXRange() const { return true; } // Returns true if the function will not be displayed if t is outside x range.
virtual float tMin() const { return NAN; }
virtual float tMax() const { return NAN; }
virtual float rangeStep() const { return NAN; }
// Name
int name(char * buffer, size_t bufferSize);
virtual int nameWithArgument(char * buffer, size_t bufferSize);
virtual int printValue(double cursorT, double cursorX, double cursorY, char * buffer, int bufferSize, int precision, Poincare::Context * context);
virtual I18n::Message parameterMessageName() const = 0;
// Evaluation
virtual Poincare::Coordinate2D<float> evaluateXYAtParameter(float t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<double> evaluateXYAtParameter(double t, Poincare::Context * context) const = 0;
virtual Poincare::Expression sumBetweenBounds(double start, double end, Poincare::Context * context) const = 0;
// Range
virtual void rangeForDisplay(float * xMin, float * xMax, float * yMin, float * yMax, float targetRatio, Poincare::Context * context) const = 0;
protected:
/* RecordDataBuffer is the layout of the data buffer of Record
* representing a Function. We want to avoid padding which would:
* - increase the size of the storage file
* - introduce junk memory zone which are then crc-ed in Storage::checksum
* creating dependency on uninitialized values.
* - complicate getters, setters and record handling
* In addition, Record::value() is a pointer to an address inside
* Ion::Storage::sharedStorage(), and it might be unaligned. We use the packed
* keyword to warn the compiler that it members are potentially unaligned
* (otherwise, the compiler can emit instructions that work only on aligned
* objects). It also solves the padding issue mentioned above.
*/
class __attribute__((packed)) RecordDataBuffer {
public:
RecordDataBuffer(KDColor color) : m_color(color), m_active(true) {}
KDColor color() const {
return KDColor::RGB16(m_color);
}
void setColor(KDColor color) { m_color = color; }
bool isActive() const { return m_active; }
void setActive(bool active) { m_active = active; }
private:
#if __EMSCRIPTEN__
/* For emscripten memory representation, loads and stores must be aligned;
* performing a normal load or store on an unaligned address can fail
* silently. We thus use 'emscripten_align1_short' type, the unaligned
* version of uint16_t type to avoid producing an alignment error on the
* emscripten platform. */
static_assert(sizeof(emscripten_align1_short) == sizeof(uint16_t), "emscripten_align1_short should have the same size as uint16_t");
emscripten_align1_short m_color;
#else
uint16_t m_color;
#endif
bool m_active;
};
void protectedFullRangeForDisplay(float tMin, float tMax, float tStep, float * min, float * max, Poincare::Context * context, bool xRange) const;
virtual void didBecomeInactive() {}
private:
RecordDataBuffer * recordData() const;
};
}
#endif