You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

493 lines
14 KiB

/*
* EEZ Modular Firmware
* Copyright (C) 2015-present, Envox d.o.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <eez/gui/data.h>
#include <eez/gui/widget.h>
namespace eez {
namespace gui {
static const uint32_t HEADER_TAG = 0x7A65657E;
static const uint8_t PROJECT_VERSION_V2 = 2;
static const uint8_t PROJECT_VERSION_V3 = 3;
static const uint8_t ASSETS_TYPE_FIRMWARE = 1;
static const uint8_t ASSETS_TYPE_FIRMWARE_MODULE = 2;
static const uint8_t ASSETS_TYPE_RESOURCE = 3;
static const uint8_t ASSETS_TYPE_APPLET = 4;
static const uint8_t ASSETS_TYPE_DASHBOARD = 5;
struct Header {
uint32_t tag; // HEADER_TAG
uint8_t projectMajorVersion;
uint8_t projectMinorVersion;
uint8_t assetsType;
uint8_t reserved;
uint32_t decompressedSize;
};
extern bool g_isMainAssetsLoaded;
extern Assets *g_mainAssets;
extern Assets *g_externalAssets;
////////////////////////////////////////////////////////////////////////////////
/* This template is used (on 64-bit systems) to pack asset pointers into 32-bit values.
* All pointers are relative to MEMORY_BEGIN.
* This way, the assets created by Studio can be used without having to fix all
* the sizes - Studio creates 32-bit pointers that are relative to the
* beginning of the assets, which the firmware rewrites to global pointers
* during initialization. On a 32-bit system this works just fine, but for a
* 64-bit system the pointers have different sizes and this breaks. By
* inserting a 'middleman' structure that stores the pointers as a 32-bit
* offset to MEMORY_BEGIN, we can keep the pointer sizes and initialization
* code the same.
*/
template<typename T>
struct AssetsPtrImpl {
/* Conversion to a T pointer */
operator T*() { return ptr(); }
operator const T*() const { return ptr(); }
/* Dereferencing operators */
T* operator->() { return ptr(); }
const T* operator->() const { return ptr(); }
void operator=(T* ptr) {
if (ptr != nullptr) {
offset = (uint8_t *)ptr - MEMORY_BEGIN;
} else {
offset = 0;
}
}
uint32_t offset = 0;
private:
T* ptr() {
return offset ? (T *)(MEMORY_BEGIN + offset) : nullptr;
}
const T* ptr() const {
return offset ? (const T *)(MEMORY_BEGIN + offset) : nullptr;
}
};
/* This struct chooses the type used for AssetsPtr<T> - by default it uses an AssetsPtrImpl<> */
template<typename T, uint32_t ptrSize>
struct AssetsPtrChooser
{
using type = AssetsPtrImpl<T>;
};
/* On 32-bit systems, we can just use raw pointers */
template<typename T>
struct AssetsPtrChooser<T, 4>
{
using type = T*;
};
/* Utility typedef that delegates to AssetsPtrChooser */
template<typename T>
using AssetsPtr = typename AssetsPtrChooser<T, sizeof(void*)>::type;
////////////////////////////////////////////////////////////////////////////////
template<typename T>
struct ListOfAssetsPtr {
/* Array access */
T* operator[](uint32_t i) { return item(i); }
const T* operator[](uint32_t i) const { return item(i); }
uint32_t count = 0;
AssetsPtr<AssetsPtr<T>> items;
private:
T* item(int i) {
return static_cast<T *>(static_cast<AssetsPtr<T> *>(items)[i]);
}
const T* item(int i) const {
return static_cast<const T *>(static_cast<const AssetsPtr<T> *>(items)[i]);
}
};
template<typename T>
struct ListOfFundamentalType {
/* Array access */
T& operator[](uint32_t i) { return ptr()[i]; }
const T& operator[](uint32_t i) const { return ptr()[i]; }
uint32_t count;
AssetsPtr<T> items;
private:
T *ptr() {
return static_cast<T *>(items);
}
};
////////////////////////////////////////////////////////////////////////////////
struct Settings {
uint16_t displayWidth;
uint16_t displayHeight;
};
////////////////////////////////////////////////////////////////////////////////
#define WIDGET_FLAG_PIN_TO_LEFT (1 << 0)
#define WIDGET_FLAG_PIN_TO_RIGHT (1 << 1)
#define WIDGET_FLAG_PIN_TO_TOP (1 << 2)
#define WIDGET_FLAG_PIN_TO_BOTTOM (1 << 3)
#define WIDGET_FLAG_FIX_WIDTH (1 << 4)
#define WIDGET_FLAG_FIX_HEIGHT (1 << 5)
#define WIDGET_TIMELINE_PROPERTY_X (1 << 0)
#define WIDGET_TIMELINE_PROPERTY_Y (1 << 1)
#define WIDGET_TIMELINE_PROPERTY_WIDTH (1 << 2)
#define WIDGET_TIMELINE_PROPERTY_HEIGHT (1 << 3)
#define WIDGET_TIMELINE_PROPERTY_OPACITY (1 << 4)
#define EASING_FUNC_LINEAR 0
#define EASING_FUNC_IN_QUAD 1
#define EASING_FUNC_OUT_QUAD 2
#define EASING_FUNC_IN_OUT_QUAD 3
#define EASING_FUNC_IN_CUBIC 4
#define EASING_FUNC_OUT_CUBIC 5
#define EASING_FUNC_IN_OUT_CUBIC 6
#define EASING_FUNC_IN__QUART 7
#define EASING_FUNC_OUT_QUART 8
#define EASING_FUNC_IN_OUT_QUART 9
#define EASING_FUNC_IN_QUINT 10
#define EASING_FUNC_OUT_QUINT 11
#define EASING_FUNC_IN_OUT_QUINT 12
#define EASING_FUNC_IN_SINE 13
#define EASING_FUNC_OUT_SINE 14
#define EASING_FUNC_IN_OUT_SINE 15
#define EASING_FUNC_IN_EXPO 16
#define EASING_FUNC_OUT_EXPO 17
#define EASING_FUNC_IN_OUT_EXPO 18
#define EASING_FUNC_IN_CIRC 19
#define EASING_FUNC_OUT_CIRC 20
#define EASING_FUNC_IN_OUT_CIRC 21
#define EASING_FUNC_IN_BACK 22
#define EASING_FUNC_OUT_BACK 23
#define EASING_FUNC_IN_OUT_BACK 24
#define EASING_FUNC_IN_ELASTIC 25
#define EASING_FUNC_OUT_ELASTIC 26
#define EASING_FUNC_IN_OUT_ELASTIC 27
#define EASING_FUNC_IN_BOUNCE 28
#define EASING_FUNC_OUT_BOUNCE 29
#define EASING_FUNC_IN_OUT_BOUNCE 30
struct TimelineKeyframe {
float start;
float end;
uint32_t enabledProperties;
int16_t x;
int16_t y;
int16_t width;
int16_t height;
float opacity;
uint8_t xEasingFunc;
uint8_t yEasingFunc;
uint8_t widthEasingFunc;
uint8_t heightEasingFunc;
uint8_t opacityEasingFunc;
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
};
struct Widget {
uint16_t type;
int16_t data;
int16_t visible;
int16_t action;
int16_t x;
int16_t y;
int16_t width;
int16_t height;
int16_t style;
uint16_t flags;
ListOfAssetsPtr<TimelineKeyframe> timeline;
};
#define SHADOW_FLAG (1 << 0)
#define CLOSE_PAGE_IF_TOUCHED_OUTSIDE_FLAG (1 << 1)
#define PAGE_IS_USED_AS_CUSTOM_WIDGET (1 << 2)
#define PAGE_CONTAINER (1 << 3)
#define PAGE_SCALE_TO_FIT (1 << 4)
struct PageAsset : public Widget {
ListOfAssetsPtr<Widget> widgets;
uint16_t flags;
int16_t overlay;
};
////////////////////////////////////////////////////////////////////////////////
#define STYLE_FLAGS_HORZ_ALIGN_MASK 0x7
#define STYLE_FLAGS_HORZ_ALIGN_LEFT 0
#define STYLE_FLAGS_HORZ_ALIGN_RIGHT 1
#define STYLE_FLAGS_HORZ_ALIGN_CENTER 2
#define STYLE_FLAGS_VERT_ALIGN_MASK (0x7 << 3)
#define STYLE_FLAGS_VERT_ALIGN_TOP (0 << 3)
#define STYLE_FLAGS_VERT_ALIGN_BOTTOM (1 << 3)
#define STYLE_FLAGS_VERT_ALIGN_CENTER (2 << 3)
#define STYLE_FLAGS_BLINK (1 << 6)
struct Style {
uint16_t flags; // STYLE_FLAGS_...
uint16_t backgroundColor;
uint16_t color;
uint16_t activeBackgroundColor;
uint16_t activeColor;
uint16_t focusBackgroundColor;
uint16_t focusColor;
uint8_t borderSizeTop;
uint8_t borderSizeRight;
uint8_t borderSizeBottom;
uint8_t borderSizeLeft;
uint16_t borderColor;
uint8_t borderRadiusTLX;
uint8_t borderRadiusTLY;
uint8_t borderRadiusTRX;
uint8_t borderRadiusTRY;
uint8_t borderRadiusBLX;
uint8_t borderRadiusBLY;
uint8_t borderRadiusBRX;
uint8_t borderRadiusBRY;
uint8_t font;
uint8_t opacity; // 0 - 255
uint8_t paddingTop;
uint8_t paddingRight;
uint8_t paddingBottom;
uint8_t paddingLeft;
int16_t backgroundImage;
};
////////////////////////////////////////////////////////////////////////////////
struct GlyphData {
int8_t dx; // DWIDTH (-128 indicated empty glyph)
uint8_t width; // BBX width
uint8_t height; // BBX height
int8_t x; // BBX xoffset
int8_t y; // BBX yoffset
uint8_t reserved1;
uint8_t reserved2;
uint8_t reserved3;
uint8_t pixels[1];
};
struct GlyphsGroup {
uint32_t encoding;
uint32_t glyphIndex;
uint32_t length;
};
struct FontData {
uint8_t ascent;
uint8_t descent;
uint8_t reserved1;
uint8_t reserved2;
uint32_t encodingStart;
uint32_t encodingEnd;
ListOfAssetsPtr<GlyphsGroup> groups;
ListOfAssetsPtr<GlyphData> glyphs;
};
////////////////////////////////////////////////////////////////////////////////
struct Bitmap {
int16_t w;
int16_t h;
int16_t bpp;
int16_t reserved;
const uint8_t pixels[1];
};
////////////////////////////////////////////////////////////////////////////////
struct Theme {
AssetsPtr<const char> name;
ListOfFundamentalType<uint16_t> colors;
};
struct Colors {
ListOfAssetsPtr<Theme> themes;
ListOfFundamentalType<uint16_t> colors;
};
////////////////////////////////////////////////////////////////////////////////
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_MASK = 0x0007 << 13;
static const uint16_t EXPR_EVAL_INSTRUCTION_PARAM_MASK = 0xFFFF >> 3;
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_CONSTANT = (0 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_INPUT = (1 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_LOCAL_VAR = (2 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_GLOBAL_VAR = (3 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_PUSH_OUTPUT = (4 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_ARRAY_ELEMENT = (5 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_OPERATION = (6 << 13);
static const uint16_t EXPR_EVAL_INSTRUCTION_TYPE_END = (7 << 13);
struct Property {
uint8_t evalInstructions[1];
};
struct Connection {
uint16_t targetComponentIndex;
uint16_t targetInputIndex;
};
struct ComponentOutput {
ListOfAssetsPtr<Connection> connections;
uint32_t isSeqOut;
};
static const uint16_t BREAKPOINT_ENABLED = 1;
static const uint16_t BREAKPOINT_DISABLED = 2;
struct Component {
uint16_t type;
uint16_t breakpoint;
// These are indexes to Flow::componentInputs.
// We use this to check if component is ready to run (i.e. all mandatory inputs have a value).
ListOfFundamentalType<uint16_t> inputs;
ListOfAssetsPtr<Property> properties;
ListOfAssetsPtr<ComponentOutput> outputs;
int16_t errorCatchOutput;
uint16_t reserved;
};
struct WidgetDataItem {
int16_t componentIndex;
int16_t propertyValueIndex;
};
struct WidgetActionItem {
int16_t componentIndex;
int16_t componentOutputIndex;
};
#define COMPONENT_INPUT_FLAG_IS_SEQ_INPUT (1 << 0)
#define COMPONENT_INPUT_FLAG_IS_OPTIONAL (1 << 1)
typedef uint8_t ComponentInput;
struct Flow {
ListOfAssetsPtr<Component> components;
ListOfAssetsPtr<Value> localVariables;
// List of all component inputs of all components in this flow
// When flow state is created we reserve this many Value's in memory
// to keep the latest value of component input.
ListOfFundamentalType<ComponentInput> componentInputs;
ListOfAssetsPtr<WidgetDataItem> widgetDataItems;
ListOfAssetsPtr<WidgetActionItem> widgetActions;
};
struct FlowDefinition {
ListOfAssetsPtr<Flow> flows;
ListOfAssetsPtr<Value> constants;
ListOfAssetsPtr<Value> globalVariables;
};
struct Language {
AssetsPtr<const char> languageID;
ListOfAssetsPtr<const char> translations;
};
////////////////////////////////////////////////////////////////////////////////
struct Assets {
uint8_t projectMajorVersion;
uint8_t projectMinorVersion;
uint8_t assetsType;
uint8_t external;
AssetsPtr<Settings> settings;
ListOfAssetsPtr<PageAsset> pages;
ListOfAssetsPtr<Style> styles;
ListOfAssetsPtr<FontData> fonts;
ListOfAssetsPtr<Bitmap> bitmaps;
AssetsPtr<Colors> colorsDefinition;
ListOfAssetsPtr<const char> actionNames;
ListOfAssetsPtr<const char> variableNames;
AssetsPtr<FlowDefinition> flowDefinition;
ListOfAssetsPtr<Language> languages;
};
////////////////////////////////////////////////////////////////////////////////
bool decompressAssetsData(const uint8_t *assetsData, uint32_t assetsDataSize, Assets *decompressedAssets, uint32_t maxDecompressedAssetsSize, int *err);
////////////////////////////////////////////////////////////////////////////////
void loadMainAssets(const uint8_t *assets, uint32_t assetsSize);
bool loadExternalAssets(const char *filePath, int *err);
void unloadExternalAssets();
////////////////////////////////////////////////////////////////////////////////
const PageAsset *getPageAsset(int pageId);
const PageAsset* getPageAsset(int pageId, WidgetCursor& widgetCursor);
const Style *getStyle(int styleID);
const FontData *getFontData(int fontID);
const Bitmap *getBitmap(int bitmapID);
int getThemesCount();
const char *getThemeName(int i);
const uint32_t getThemeColorsCount(int themeIndex);
const uint16_t *getThemeColors(int themeIndex);
const uint16_t *getColors();
int getExternalAssetsMainPageId();
const char *getActionName(const WidgetCursor &widgetCursor, int16_t actionId);
int16_t getDataIdFromName(const WidgetCursor &widgetCursor, const char *name);
////////////////////////////////////////////////////////////////////////////////
} // namespace gui
} // namespace eez